我试图通过我的内核驱动程序获取正在运行的进程的实际可执行路径.
我做了以下事情:
static struct kretprobe do_fork_probe = {
.entry_handler = (kprobe_opcode_t *) process_entry_callback,
.handler = (kprobe_opcode_t *) NULL,
.maxactive = 1000,
.data_size = 0
};
do_fork_probe.kp.addr = (kprobe_opcode_t*)kallsyms_lookup_name("do_fork");
if ((ret = register_kretprobe(&do_fork_probe)) < 0)
return -1;
static int process_entry_callback(struct kretprobe_instance *ri, struct pt_regs *regs)
{
printk("Executable path = %s\n", executable_path(current));
return 0;
}
executable_path函数:
char* executable_path(struct task_struct* process)
{
#define PATH_MAX 4096
char* p = NULL, *pathname;
struct mm_struct* mm = current->mm;
if (mm)
{
down_read(&mm->mmap_sem);
if (mm->exe_file)
{
pathname = kmalloc(PATH_MAX, GFP_ATOMIC);
if (pathname)
p = d_path(&mm->exe_file->f_path, pathname, PATH_MAX);
}
up_read(&mm->mmap_sem);
}
return p;
}
问题是,如果我使用bash运行可执行文件,如下所示:
./execname
我得到以下输出:
Executable path = /bin/bash
虽然我真正想要的是:execname(实际上它的完整路径,但让我们从名称开始)
有什么建议?
最佳答案 目前还不清楚你想要得到什么,所以这里是选项列表:
> execname,因为它被SystemTap考虑.简单的过程 – > comm就足够了.这就是内核中定义的comm字段:
char comm[TASK_COMM_LEN]; /* executable name excluding path
- access with [gs]et_task_comm (which lock
it with task_lock())
- initialized normally by setup_new_exec */
但是如果bash是一个符号链接,那么comm应该包含符号链接的名称,而不是真正的可执行文件名.
> argv [0]命令行参数数组的第一个元素,因为它看到了我的应用程序(并且可能被它改变).内核中有一个get_cmdline()函数,但似乎没有导出.
>完整路径的基本名称.在这种情况下,不要调用d_path,只需取dtry字段为dentry:
strlcpy(pathname, mm->exe_file->f_path->d_name, PATH_MAX);
但这听起来像一个XY问题.您是否尝试获取所有分叉进程的可执行文件名称?为什么不直接使用SystemTap?
# stap -v -e 'probe scheduler.process_fork { println(execname()); }'