我编写了一个内核模块(一个字符设备),每当我写入模块时都会注册新的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;
}
为什么在结构中需要这个额外的内存?
答案 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()
。