我在编写内核模块,目的是监听进程的启动,获取进程的启动信息
我使用的kprobe来监控do_execveat_common函数,但是对于启动参数始终无法获取,我的代码如下
//监控进程,获取进程信息,进程ID 进程名 NS
static int my_kprobe_pre_handler_dynamic(struct kprobe *p, struct pt_regs *regs)
{
//获取进程的可执行文件路径
struct filename *filename = (struct filename *)PT_REGS_PARM2(regs);
char filename_buf[PATH_MAX];
char *tmp = filename_buf;
tmp = filename->name;
pr_info("process executable file path= %s ", tmp);
show_current_task_info();
//获取启动参数
struct user_arg_ptr argv;
//unsigned int arg_ptr_value = PT_REGS_PARM4(regs);
unsigned long arg_ptr_value = regs->dx;
bpf_probe_read_kernel(&argv, sizeof(argv), (void *)arg_ptr_value);
//我确定是这行有问题 这里牵扯到用户空间和内核空间不同内存的读取,
//除了这个函数,我替换成 copy_from_user,bpf_probe_read_user等都会导致内存崩溃,原因暂时不清楚
printk("argv = %p,ptr = %p,is_compat = %d,native=%p,compat=%p\n",&argv,&(argv.ptr),argv.is_compat,argv.ptr.native,argv.ptr.compat);
int argv_num;
argv_num = count(argv, MAX_ARG_STRINGS);
printk("argv_num = %d\n",argv_num);
return 0;
}
static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr)
{
const char __user *native;
#ifdef CONFIG_COMPAT
if (unlikely(argv.is_compat)) {
compat_uptr_t compat;
if (get_user(compat, argv.ptr.compat + nr))
return ERR_PTR(-EFAULT);
return compat_ptr(compat);
}
#endif
if (get_user(native, argv.ptr.native + nr))
return ERR_PTR(-EFAULT);
return native;
}
/*
* count() counts the number of strings in array ARGV.
*/
static int count(struct user_arg_ptr argv, int max)
{
int i = 0;
if (argv.ptr.native != NULL) {
for (;;) {
const char __user *p = get_user_arg_ptr(argv, i);
if (!p)
break;
if (IS_ERR(p))
return -EFAULT;
if (i >= max)
return -E2BIG;
++i;
if (fatal_signal_pending(current))
return -ERESTARTNOHAND;
cond_resched();
}
}
return i;
}