【问题标题】:jprobe do_execve does not work with kernel 4.1jprobe do_execve 不适用于内核 4.1
【发布时间】:2015-11-29 05:57:43
【问题描述】:

我想在 do_execve 上设置一个 jprobe 钩子来捕获每个执行的程序。

我的代码在

[  628.534037] registered: do_execve, ret: 0
[  723.995797] execve: /usr/bin/vi
[  726.807025] execve: /bin/dmesg

在 4.1 内核上,我的结果相同(所有内容都已注册)但没有“execve”:

[ 8621.430568] registered: do_execve, ret: 0

这是我的代码:

static struct jprobe jprobe_hooks[] = {
{
    .entry = jdo_execve,
    .kp = { .symbol_name = "do_execve" }
}};

static long jdo_execve(const char *filename, const char __user *const __user *argv, const char __user *const __user *envp, struct pt_regs *regs)
{
   printk(KERN_INFO "execve: %s", filename );
}

// 
// registration
//
int ret, x, reg_error;

reg_error = 0;
for (x = 0; x < sizeof(jprobe_hooks) / sizeof(jprobe_hooks[0]); x++)
{
    ret = register_jprobe(&jprobe_hooks[x]);
    if (ret < 0)
    {
        printk(KERN_INFO "register_jprobe failed, returned %d, item: %s\n", ret, jprobe_hooks[x].kp.symbol_name);
        reg_error++;
    }
    else
    {
        printk(KERN_INFO "registered: %s, ret: %u\n", jprobe_hooks[x].kp.symbol_name, ret);
    }
}

当我在 kallsyms 上执行 grep 时,我得到了 3.2:

 grep do_execv /proc/kallsyms
 ffffffff81100650 T do_execve

在 4.2 上:

grep do_execv /proc/kallsyms
ffffffff811d2950 T do_execve
ffffffff811d2980 T do_execveat

我什至尝试将函数(因为 do_execve 原型已更改)更改为:

static int jdo_execve(struct filename *fname, const char __user *const __user *__argv, const char __user *const __user *__envp)
{
    int i = 0;

    printk(KERN_INFO "execve: %s ", fname->name );
}

即使这样也无济于事。

我可以在 do_fork 或 sys_open 等其他函数上设置挂钩,但不能在 do_execve 上设置。为什么?有人有想法吗?为什么它不再工作了?

编辑:

我也在挂钩 do_execveat:

 static int jdo_execveat(int fd, struct filename *fname, const char __user *const __user *__argv, const char __user *const __user *__envp, int flags)

【问题讨论】:

  • 可能,新内核的libc 使用execveat 系统调用而不是execve 之一。您还需要挂钩 do_execveat 以执行 catch 程序。
  • 我也喜欢 jdo_execveat :(

标签: linux linux-kernel execve kprobe jprobe


【解决方案1】:

有几个问题可能会阻止您发送 jprobe 消息:

  1. 您不会以换行符结束打印消息printk(KERN_INFO "execve: %s", filename );,因此您的日志缓冲区不会被刷新。
  2. API 已更改。现在do_execve 的文件名参数为struct filename
  3. 你的 jprobe 代码很傻:你没有模块入口,jprobe 例程必须以jprobe_return() call 结束,等等。在“samples/kprobes”查看内核源代码树中的示例

尝试修复它 - 也许会有所帮助。

无论如何,我自己尝试过 - here 是代码 - 确实,事情看起来很奇怪。当我加载模块时,它注册了 2 个 jprobes - 一个用于 do_execve,另一个用于 do_execveat。但是我在执行程序时看不到任何消息。 但是我看到的是这样的定期消息:

jprobe: execve: /usr/lib/systemd/systemd-cgroups-agent

这意味着 jprobe 本身可以工作,但不是对每个execve 调用都有效。

所以我写了a simple C program 来调用execve 只是为了确保它真的被调用了,但我仍然没有任何反应,除了 systemd-cgroups-agent。

【讨论】:

  • 1) 是的,忘记了 \n。 2)我也尝试过(看我的帖子),3)我没有发布整个sn-p,但最后我正在做一个jprobe_return(); return 0;。我不知道发生了什么,但我会看看 systemd-cgroups-agent,谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多