Linux内核 - 如何将jprobe与kretprobe相匹配?

rvk*_*rvk 6 c linux kernel kernel-module linux-kernel

我正在编写一个内核模块来监视一些想要在调用成功时将函数参数返回到user-land(通过netlink socket)的系统调用.

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;
}
Run Code Online (Sandbox Code Playgroud)

我担心另一个重命名系统调用可以抢占[1] jprobe之后的当前一个,我将发送错误的返回码和参数.

jprobe: rename(a, b)
    jprobe rename(c, d)
    kretprobe
kretprobe
Run Code Online (Sandbox Code Playgroud)

编辑:本文[2]指出在kprobe处理程序期间禁用了中断.但这是否意味着整个链中断(jprobe - > kprobe - > kretprobe)或仅针对那个单独的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/

Dan*_*art 1

每次调用都禁用中断jprobe:而不是整个序列。

在应用程序处理这些呼叫的时间内,您预计会有多少个呼叫?根据您期望调用进入的速度,有不同的方法。如果您只期望在处理它们之前可能有几百个调用,并且您将静态内存专用于该目的,那么最简单的方法是实现一个内存中对象的静态数组rename_obj_t,然后使用atomic_add内核 asm include 指向下一个条目(mod 数组的大小)。

这样,只要在处理返回值之前计数器不会回绕,您每次都会返回一个唯一的静态引用。 atomic_add保证具有正确的内存屏障,因此您不必担心缓存一致性等问题。