获取当前进程上下文的实际可执行路径-Linux内核

问题描述:

我正在尝试通过内核驱动程序获取正在运行的进程的实际可执行路径.

I'm trying to get the actual executable path of a running process through my kernel driver.

我已完成以下操作:

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函数:

The executable_path function:

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运行可执行文件,如下所示:

The problem is that if I run an executable using bash as follows:

./execname

我得到以下输出:

Executable path = /bin/bash

我真正想要的是:execname(实际上是其完整路径,但可以从名称开始)

While what I really want is the : execname (Actually its full path but lets start with the name)

有什么建议吗?

目前尚不清楚您尝试获得什么,因此下面是选项列表:

It is unclear what you try to get, so here are list of options:

  • execname,因为SystemTap认为它.简单的process->comm就足够了.这就是在内核中定义comm字段的方式:

  • execname as it is considered by SystemTap. Simple process->comm should suffice. That is how comm field defined in Kernel:

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应该包含符号链接的名称,而不是实际的可执行文件名称.

But if bash is a symlink, than comm should contain symlink's name, not the real executable name.

argv[0]命令行参数数组的第一个元素,因为它是我的应用程序(可能会被其更改).内核中有一个get_cmdline()函数,但似乎没有导出.

argv[0] first element of command line arguments array as it seen my application (and may be altered by it). There is a get_cmdline() function in kernel, but it seem not to be exported.

完整路径的基本名称.在这种情况下,请勿调用d_path,而仅使用dentry的d_name字段:

Basename of full path. In this case, do not call d_path, just take d_name field of dentry:

strlcpy(pathname, mm->exe_file->f_path->d_name, PATH_MAX);

但这听起来像是XY问题.您试图获取所有分支过程的可执行文件名称吗?为什么不直接使用 SystemTap ?

But it sounds like a XY problem. You trying to get executable names for all forking processes? Why not use SystemTap directly?

# stap -v -e 'probe scheduler.process_fork { println(execname()); }'