register_kprobe()在包含struct的情况下返回EINVAL而没有额外的内存

时间:2017-09-30 01:23:43

标签: linux linux-kernel kernel-module kprobe

我编写了一个内核模块(一个字符设备),每当我写入模块时都会注册新的KProbes。

我的结构包含struct kprobe。当我致电register_kprobe()时,会返回-EINVAL。但是当我向(可能还有一些其他数据类型)添加一个虚拟字符数组时,KProbe注册成功。

探针注册

struct my_struct *container = kmalloc(sizeof(struct my_struct));
(container->probe).addr = (kprobe_opcode_t *) kallsyms_lookup_name("my_exported_fn"); /* my_exported_fn is in code section */
(container->probe).pre_handler = Pre_Handler;
(container->probe).post_handler = Post_Handler;
register_probe(&container->probe);
/* Returns -EINVAL if my_struct contains only `struct kprobe`. */

不工作:

struct my_struct {
     struct kprobe probe;
}

工作:

struct my_struct {
     char dummy[512]; /* At 512, it gets consistently registered. At 256, sometimes (maybe one out of 5 - 10 times get registered) */
     struct kprobe probe;
}

为什么在结构中需要这个额外的内存?

1 个答案:

答案 0 :(得分:3)

这个可以是否是未对齐的内存访问,但在这种特殊情况下(我的意思是编辑前的原始代码)我怀疑数据没有正确初始化。即,register_kprobe() calls kprobe_addr()函数反过来暗示以下check

if ((symbol_name && addr) || (!symbol_name && !addr))
    goto invalid;
...
invalid:
    return ERR_PTR(-EINVAL);

因此,如果您确实初始化addr并且没有初始化symbol_name,则后者在某些情况下可能是垃圾指针。也就是说,kmalloc()不会将已分配的内存归零,此外,根据请求的大小,它可能会从不同的获取合适大小的内存对象(有不同的提供不同大小的对象),当你人为增加结构的大小时,kmalloc()必须从合适的池中分配一个更大的对象。从这个角度来看,概率是这样的对象可能偶尔不包含垃圾(因为较少的块经常被请求)。

总而言之,我建议将内存块归零或使用kzalloc()