jprobe do_execve不适用于内核4.1

时间:2015-09-03 11:56:28

标签: linux linux-kernel execve kprobe jprobe

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

我的代码正在使用< = 3.2 linux kernel(debian)。这是我在linux内核3.2上的输出:

[  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)

1 个答案:

答案 0 :(得分:2)

有几个问题可能会阻止您使用jprobe消息:

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

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

    无论如何,我自己尝试过 - 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。