Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linux Kernel - How to match a jprobe to kretprobe?

I am writing a kernel module to monitor a few syscalls wanting to return the function arguments to user-land (via netlink socket) if the call was successful.

jprobe.kp.symbol_name = "rename";
jprobe.entry = rename_handler;

kretprobe.kp.symbol_name = "rename";
kretprobe.handler = rename_ret_handler;

static rename_obj_t _g_cur_rename = NULL;

static void _rename_handler(const char *oldpath, const char *newpath)
{
    _g_cur_rename = create_rename(oldpath, newpath);
    jprobe_return();
}

static void _rename_ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
    /* Send only if successful */
    if (regs_return_value(regs) == 0) {
        add_send_queue(_g_cur_rename);
    }
    return 0;
}

I worry that another rename syscall may preempt[1] the current one after the jprobe and I will send incorrect return codes and arguments.

jprobe: rename(a, b)
    jprobe rename(c, d)
    kretprobe
kretprobe

Edit: This article[2] states that interrupts are disabled during a kprobe handler. But does that mean that interrupts are disable throughout the whole chain (jprobe -> kprobe -> kretprobe) or just for that single kprobe?

  1. https://unix.stackexchange.com/questions/186355/few-questions-about-system-calls-and-kernel-modules-kernel-services-in-parallel
  2. https://lwn.net/Articles/132196/
like image 379
rvk Avatar asked Oct 03 '16 14:10

rvk


1 Answers

Interrupts are disabled for each jprobe call: not for the entire sequence.

How many calls are you expecting in the time it will take the application to process them? There are different approaches depending on how fast you expect the calls to come in. The simplest method, if you are only expecting maybe a few hundred calls before you can process them and you will dedicate the static memory to the purpose, is to implement a static array of rename_obj_t objects in memory and then use atomic_add from the kernel asm includes to point to the next entry (mod the size of your array).

This way you are returning a unique static reference each time, so long as the counter doesn't wrap around before you process the returned values. atomic_add is guaranteed to have the correct memory barriers in place so you don't have to worry about things like cache coherency.

like image 194
Daniel Wisehart Avatar answered Sep 19 '22 20:09

Daniel Wisehart