我正在編寫一個內核模塊來獲取帶有完整進程名稱的pid列表。 proc_pid_cmdline()
給出了完整的進程名稱;使用相同的功能/proc/*/cmdline
獲取完整的進程名稱。 (struct task_struct) -> comm
給出了它是什麼過程的提示,但不是完整的路徑。如何在內核模塊中使用proc_pid_cmdline
我已經包含了函數名稱,但它給出了錯誤,因爲它不知道在哪裏找到函數。
如何在模塊中使用proc_pid_cmdline()
?
我正在編寫一個內核模塊來獲取帶有完整進程名稱的pid列表。 proc_pid_cmdline()
給出了完整的進程名稱;使用相同的功能/proc/*/cmdline
獲取完整的進程名稱。 (struct task_struct) -> comm
給出了它是什麼過程的提示,但不是完整的路徑。如何在內核模塊中使用proc_pid_cmdline
我已經包含了函數名稱,但它給出了錯誤,因爲它不知道在哪裏找到函數。
如何在模塊中使用proc_pid_cmdline()
?
你不應該打電話給proc_pid_cmdline()
。
這是一個non-public function在fs/proc/base.c
:
static int proc_pid_cmdline(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task)
然而,它的作用很簡單:
get_cmdline(task, m->buf, PAGE_SIZE);
這是不太可能,雖然返回的完整路徑,這將是不可能的確定每種情況下的完整路徑。 arg [0]值可能會被覆蓋,文件可能被刪除或移動等。一個進程可能會以一種模糊原始命令行的方式執行exec()以及所有其他弊端。
我的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
適用於openSUSE 13.2:'我爲/ proc/*/cmdline;做echo $ I;貓$ | | tr'\ 000''';回聲; done' – myaut 2015-03-06 00:00:58
我目前正在查看proc_exe_link中的源代碼,它返回進程可執行文件的結構。我同意上面的cmd可以僞造。僞造mm-> exe_file有多容易,因爲它似乎是原始原始二進制文件的內存映射? – 2015-03-06 00:10:14
我設法解決這個問題的一個版本。我想訪問所有PID中的cmdline
,但是在內核本身中(而不是內核模塊作爲問題狀態),但也許這些原則也可以應用於內核模塊?
我所做的就是,我增加了以下功能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;
}
然後我加入了申報include/linux/proc_fs.h
int proc_get_cmdline(struct task_struct *, char *);
在這一點上,我可能中訪問的所有進程的cmdline
內核。 要訪問task_struct
,也許你可以參考kernel: efficient way to find task_struct by pid?。
一旦你的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);
我能夠獲得所有進程的這樣的命令行。
獲取進程背後的二進制文件的完整路徑。
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));
凡當前是這個過程中你感興趣的任務結構,變量exepathp得到的完整路徑的字符串。這與進程cmd稍有不同,這是加載啓動進程的二進制文件的路徑。將此路徑與進程cmd結合起來應該能夠爲您提供完整的路徑。
您必須定義進程名稱,因爲Linux(和Unix)完全不使用進程名稱。 – wallyk 2015-03-05 23:33:44