Jprobe do_execve不能与内核4.1一起工作



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

我的代码是工作在<= 3.2 linux内核(debian)。这是我在linux内核3.2上的输出:

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

在4.1内核I上得到相同的结果(所有内容都已注册),但没有"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: %sn", ret, jprobe_hooks[x].kp.symbol_name);
        reg_error++;
    }
    else
    {
        printk(KERN_INFO "registered: %s, ret: %un", jprobe_hooks[x].kp.symbol_name, ret);
    }
}

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

 grep do_execv /proc/kallsyms
 ffffffff81100650 T do_execve

和on 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. 您没有以换行符结束打印消息printk(KERN_INFO "execve: %s", filename );,因此您的日志缓冲区没有刷新。
  2. API发生变化。现在do_execve的文件名参数为struct filename
  3. 你的jprobe代码是愚蠢的:你没有模块入口,jprobe例程必须以jprobe_return()调用结束等等。查看位于"samples/kprobes"
  4. 的内核源代码树中的示例

试着修复它,也许会有帮助。

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

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

这意味着jprobe本身工作,但不是每个execve调用。

所以我写了一个简单的C程序来调用execve,只是为了确保它真的被调用了,我仍然什么也没发生,除了systemd-cgroups-agent。

最新更新