2014-08-30 18 views
4

我正在編寫一個內核模塊來獲取帶有完整進程名稱的pid列表。 proc_pid_cmdline()給出了完整的進程名稱;使用相同的功能/proc/*/cmdline獲取完整的進程名稱。 (struct task_struct) -> comm給出了它是什麼過程的提示,但不是完整的路徑。如何在內核模塊中使用proc_pid_cmdline

我已經包含了函數名稱,但它給出了錯誤,因爲它不知道在哪裏找到函數。

如何在模塊中使用proc_pid_cmdline()

+0

您必須定義進程名稱,因爲Linux(和Unix)完全不使用進程名稱。 – wallyk 2015-03-05 23:33:44

回答

2

你不應該打電話給proc_pid_cmdline()

這是一個non-public functionfs/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 
+0

適用於openSUSE 13.2:'我爲/ proc/*/cmdline;做echo $ I;貓$ | | tr'\ 000''';回聲; done' – myaut 2015-03-06 00:00:58

+0

我目前正在查看proc_exe_link中的源代碼,它返回進程可執行文件的結構。我同意上面的cmd可以僞造。僞造mm-> exe_file有多容易,因爲它似乎是原始原始二進制文件的內存映射? – 2015-03-06 00:10:14

1

我設法解決這個問題的一個版本。我想訪問所有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); 

我能夠獲得所有進程的這樣的命令行。

0

獲取進程背後的二進制文件的完整路徑。

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結合起來應該能夠爲您提供完整的路徑。