如何在内核模块中使用proc_pid_cmdline

时间:2022-03-25 02:56:35

I am writing a kernel module to get the list of pids with their complete process name. The proc_pid_cmdline() gives the complete process name;using same function /proc/*/cmdline gets the complete process name. (struct task_struct) -> comm gives hint of what process it is, but not the complete path.

我正在编写一个内核模块来获取带有完整进程名称的pids列表。 proc_pid_cmdline()给出完整的进程名称;使用相同的函数/ proc / * / cmdline获取完整的进程名称。 (struct task_struct) - > comm提示它是什么进程,但不是完整路径。

I have included the function name, but it gives error because it does not know where to find the function.

我已经包含了函数名称,但它给出了错误,因为它不知道在哪里找到该函数。

How to use proc_pid_cmdline() in a module ?

如何在模块中使用proc_pid_cmdline()?

3 个解决方案

#1


2  

You are not supposed to call proc_pid_cmdline().

你不应该调用proc_pid_cmdline()。

It is a non-public function in fs/proc/base.c:

它是fs / proc / base.c中的非公共函数:

static int proc_pid_cmdline(struct seq_file *m, struct pid_namespace *ns,
                            struct pid *pid, struct task_struct *task)

However, what it does is simple:

但是,它做的很简单:

get_cmdline(task, m->buf, PAGE_SIZE);

That is not likely to return the full path though and it will not be possible to determine the full path in every case. The arg[0] value may be overwritten, the file could be deleted or moved, etc. A process may exec() in a way which obscures the original command line, and all kinds of other maladies.

这不太可能返回完整路径,并且无法确定每种情况下的完整路径。可以覆盖arg [0]值,可以删除或移动文件等。进程可以以隐藏原始命令行和各种其他疾病的方式执行()。

A scan of my Fedora 20 system /proc/*/cmdline turns up all kinds of less-than-useful results:

扫描我的Fedora 20系统/ proc / * / cmdline会出现各种不太有用的结果:

-F
BUG:
WARNING: at
WARNING: CPU:
INFO: possible recursive locking detecte
ernel BUG at
list_del corruption
list_add corruption
do_IRQ: stack overflow:
ear stack overflow (cur:
eneral protection fault
nable to handle kernel
ouble fault:
RTNL: assertion failed
eek! page_mapcount(page) went negative!
adness at
NETDEV WATCHDOG
ysctl table check failed
: nobody cared
IRQ handler type mismatch
Machine Check Exception:
Machine check events logged
divide error:
bounds:
coprocessor segment overrun:
invalid TSS:
segment not present:
invalid opcode:
alignment check:
stack segment:
fpu exception:
simd exception:
iret exception:
/var/log/messages
--
/usr/bin/abrt-dump-oops
-xtD

#2


1  

I have managed to solve a version of this problem. I wanted to access the cmdline of all PIDs but within the kernel itself (as opposed to a kernel module as the question states), but perhaps these principles can be applied to kernel modules as well?

我设法解决了这个问题的一个版本。我想访问所有PID的cmdline,但是在内核本身内(与问题所述的内核模块相反),但也许这些原则也可以应用于内核模块?

What I did was, I added the following function to fs/proc/base.c

我做的是,我将以下函数添加到fs / proc / base.c

int proc_get_cmdline(struct task_struct *task, char * buffer) {
    int i;
    int ret = proc_pid_cmdline(task, buffer);

    for(i = 0; i < ret - 1; i++) {
           if(buffer[i] == '\0')
                   buffer[i] = ' ';
   }
    return 0;
}

I then added the declaration in include/linux/proc_fs.h
int proc_get_cmdline(struct task_struct *, char *);

然后我在include / linux / proc_fs.h中添加了声明int proc_get_cmdline(struct task_struct *,char *);

At this point, I could access the cmdline of all processes within the kernel. To access the task_struct, perhaps you could refer to kernel: efficient way to find task_struct by pid?.

此时,我可以访问内核中所有进程的cm​​dline。要访问task_struct,也许你可以参考内核:通过pid找到task_struct的有效方法。

Once you have the task_struct, you should be able to do something like:

拥有task_struct之后,您应该可以执行以下操作:

char cmdline[256];    
proc_get_cmdline(task, cmdline);
if(strlen(cmdline) > 0)
    printk("  cmdline :%s\n", cmdline);
else
    printk("  cmdline :%s\n", task->comm);

I was able to obtain the commandline of all processes this way.

我能够以这种方式获得所有进程的命令行。

#3


0  

To get the full path of the binary behind a process.

获取进程后面的二进制文件的完整路径。

char * exepathp;

struct file * exe_file;
struct mm_struct *mm;
char exe_path [1000];

//straight up stolen from get_mm_exe_file   
mm = get_task_mm(current);
down_read(&mm->mmap_sem); //lock read
exe_file = mm->exe_file;
if (exe_file) get_file(exe_file);
up_read(&mm->mmap_sem); //unlock read

//reduce exe path to a string
exepathp = d_path( &(exe_file->f_path), exe_path, 1000*sizeof(char) );

Where current is the task struct for the process you are interested in. The variable exepathp gets the string of the full path. This is slightly different than the process cmd, this is the path of binary which was loaded to start the process. Combining this path with the process cmd should give you the full path.

current是您感兴趣的进程的任务结构。变量exepathp获取完整路径的字符串。这与进程cmd略有不同,这是为启动进程而加载的二进制路径。将此路径与进程cmd组合应该为您提供完整路径。

#1


2  

You are not supposed to call proc_pid_cmdline().

你不应该调用proc_pid_cmdline()。

It is a non-public function in fs/proc/base.c:

它是fs / proc / base.c中的非公共函数:

static int proc_pid_cmdline(struct seq_file *m, struct pid_namespace *ns,
                            struct pid *pid, struct task_struct *task)

However, what it does is simple:

但是,它做的很简单:

get_cmdline(task, m->buf, PAGE_SIZE);

That is not likely to return the full path though and it will not be possible to determine the full path in every case. The arg[0] value may be overwritten, the file could be deleted or moved, etc. A process may exec() in a way which obscures the original command line, and all kinds of other maladies.

这不太可能返回完整路径,并且无法确定每种情况下的完整路径。可以覆盖arg [0]值,可以删除或移动文件等。进程可以以隐藏原始命令行和各种其他疾病的方式执行()。

A scan of my Fedora 20 system /proc/*/cmdline turns up all kinds of less-than-useful results:

扫描我的Fedora 20系统/ proc / * / cmdline会出现各种不太有用的结果:

-F
BUG:
WARNING: at
WARNING: CPU:
INFO: possible recursive locking detecte
ernel BUG at
list_del corruption
list_add corruption
do_IRQ: stack overflow:
ear stack overflow (cur:
eneral protection fault
nable to handle kernel
ouble fault:
RTNL: assertion failed
eek! page_mapcount(page) went negative!
adness at
NETDEV WATCHDOG
ysctl table check failed
: nobody cared
IRQ handler type mismatch
Machine Check Exception:
Machine check events logged
divide error:
bounds:
coprocessor segment overrun:
invalid TSS:
segment not present:
invalid opcode:
alignment check:
stack segment:
fpu exception:
simd exception:
iret exception:
/var/log/messages
--
/usr/bin/abrt-dump-oops
-xtD

#2


1  

I have managed to solve a version of this problem. I wanted to access the cmdline of all PIDs but within the kernel itself (as opposed to a kernel module as the question states), but perhaps these principles can be applied to kernel modules as well?

我设法解决了这个问题的一个版本。我想访问所有PID的cmdline,但是在内核本身内(与问题所述的内核模块相反),但也许这些原则也可以应用于内核模块?

What I did was, I added the following function to fs/proc/base.c

我做的是,我将以下函数添加到fs / proc / base.c

int proc_get_cmdline(struct task_struct *task, char * buffer) {
    int i;
    int ret = proc_pid_cmdline(task, buffer);

    for(i = 0; i < ret - 1; i++) {
           if(buffer[i] == '\0')
                   buffer[i] = ' ';
   }
    return 0;
}

I then added the declaration in include/linux/proc_fs.h
int proc_get_cmdline(struct task_struct *, char *);

然后我在include / linux / proc_fs.h中添加了声明int proc_get_cmdline(struct task_struct *,char *);

At this point, I could access the cmdline of all processes within the kernel. To access the task_struct, perhaps you could refer to kernel: efficient way to find task_struct by pid?.

此时,我可以访问内核中所有进程的cm​​dline。要访问task_struct,也许你可以参考内核:通过pid找到task_struct的有效方法。

Once you have the task_struct, you should be able to do something like:

拥有task_struct之后,您应该可以执行以下操作:

char cmdline[256];    
proc_get_cmdline(task, cmdline);
if(strlen(cmdline) > 0)
    printk("  cmdline :%s\n", cmdline);
else
    printk("  cmdline :%s\n", task->comm);

I was able to obtain the commandline of all processes this way.

我能够以这种方式获得所有进程的命令行。

#3


0  

To get the full path of the binary behind a process.

获取进程后面的二进制文件的完整路径。

char * exepathp;

struct file * exe_file;
struct mm_struct *mm;
char exe_path [1000];

//straight up stolen from get_mm_exe_file   
mm = get_task_mm(current);
down_read(&mm->mmap_sem); //lock read
exe_file = mm->exe_file;
if (exe_file) get_file(exe_file);
up_read(&mm->mmap_sem); //unlock read

//reduce exe path to a string
exepathp = d_path( &(exe_file->f_path), exe_path, 1000*sizeof(char) );

Where current is the task struct for the process you are interested in. The variable exepathp gets the string of the full path. This is slightly different than the process cmd, this is the path of binary which was loaded to start the process. Combining this path with the process cmd should give you the full path.

current是您感兴趣的进程的任务结构。变量exepathp获取完整路径的字符串。这与进程cmd略有不同,这是为启动进程而加载的二进制路径。将此路径与进程cmd组合应该为您提供完整路径。