我可以使用kprobe
机制使用以下示例代码附加处理程序:
#include <asm/uaccess.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/kallsyms.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/kprobes.h>
static struct kprobe kp;
int Pre_Handler(struct kprobe *p, struct pt_regs *regs){
printk("pre_handler\n");
return 0;
}
void Post_Handler(struct kprobe *p, struct pt_regs *regs, unsigned long flags) {
printk("post_handler\n");
}
int __init init (void) {
kp.pre_handler = Pre_Handler;
kp.post_handler = Post_Handler;
kp.addr = (kprobe_opcode_t *)kallsyms_lookup_name("sys_fork");
printk("%d\n", register_kprobe(&kp));
return 0;
}
void __exit cleanup(void) {
unregister_kprobe(&kp);
}
MODULE_LICENSE("GPL");
module_init(init);
module_exit(cleanup);
但是,看起来并非所有内核例程都可以通过这种方式进行跟踪。我试图将处理程序附加到system_call
,以便在执行任何系统调用时调用它们,并进行以下更改:
kp.addr = (kprobe_opcode_t *)kallsyms_lookup_name("system_call");
未插入探针。 dmesg
表示register_kprobe
返回-22,即-EINVAL
。为什么这个功能无法追踪?是否可以在调度任何系统调用之前附加kprobe处理程序?
$ uname -r
3.8.0-29-generic
答案 0 :(得分:2)
system_call受kprobes保护,无法探测system_call函数。 我认为在调用任何实际系统调用之前,我们没有任何有用的信息。例如,如果您看到函数system_call:
RING0_INT_FRAME # can't unwind into user space anyway
ASM_CLAC
pushl_cfi %eax # save orig_eax
SAVE_ALL
GET_THREAD_INFO(%ebp)
# system call tracing in operation / emulation
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
jnz syscall_trace_entry
cmpl $(NR_syscalls), %eax
jae syscall_badsys
syscall_call:
call *sys_call_table(,%eax,4)
在调用实际系统调用之前,有一些指令。是的,我不确定你是否需要这些说明中的任何信息。