stux
stux

Reputation: 11

jprobe do_execve does not work with kernel 4.1

I want to set a jprobe hook on do_execve to catch every executed program.

My code is working on <= 3.2 linux kernel (debian). This is my output on linux kernel 3.2:

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

on 4.1 kernel I the same result (everything is registered) but there is no "execve":

[ 8621.430568] registered: do_execve, ret: 0

And this is my code:

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);
    }
}

When I do a grep on kallsyms I get on 3.2:

 grep do_execv /proc/kallsyms
 ffffffff81100650 T do_execve

and on 4.2:

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

I even tried to change the function (because do_execve prototype has changed) to this:

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 );
}

and even that didn't help.

I can set hooks on other functions like do_fork or sys_open, but not on do_execve. Why? Anybody has ideas? Why is it not working anymore?

Edit:

I'm also hooking 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)

Upvotes: 1

Views: 708

Answers (1)

Alexander Dzyoba
Alexander Dzyoba

Reputation: 4189

There are several problems that may prevent you jprobe messages:

  1. You don't end print messages printk(KERN_INFO "execve: %s", filename ); with newline, thus you log buffer is not flushed.
  2. API had changed. Now do_execve has filename parameter as struct filename.
  3. Your jprobe code is silly: you don't have module entry, jprobe routine must end with jprobe_return() call and so on. Look at the samples in kernel source tree at "samples/kprobes"

Try to fix it - maybe it will help.

Anyway, I tried it by myself - here is the code - and things is, indeed, looks strange. When I load the module it registers 2 jprobes - one for do_execve, another for do_execveat. But I don't see any messages when I execute programs. BUT what I do see is periodical messages like this:

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

It means that jprobe itself works, but not for every execve call.

So I wrote a simple C program to call execve just to be sure it's really called and I still nothing happens execpt systemd-cgroups-agent.

Upvotes: 2

Related Questions