2011-11-21 74 views
1

我有走過的進程樹和打印進程名和UID的,直到init進程內核模塊下面的代碼:行走過程中樹在Linux內核

// recursivly walk the task's parent until we reach init 

void parent_task_walk(struct task_struct *task) { 

    struct task_struct *parent; 
    char filename[MAX_FILE_LEN]; 

    if (task && task->mm) { 

     parent = get_task_parent(task); 

     printk("%s (uid:%d)", exe_from_mm(task->mm, filename, MAX_FILE_LEN), 
      get_task_uid(task)); 

     if (parent && task->pid != 1) { 
      printk(", "); 
      parent_task_walk(parent); 
     } 
    } 

} 

注:我做使用一些引用真實內核函數的宏,因爲這是一個跨越多個版本的內核模塊。源代碼是在這個文件中:https://github.com/cormander/tpe-lkm/blob/319e1e29ea23055cca1c0a3bce3c865def14d3d2/core.c#L61

輸出最終看起來是這樣的:

/bin/bash (uid:500), /usr/sbin/sshd (uid:500), /usr/sbin/sshd (uid:0), /usr/sbin/sshd (uid:0), /sbin/init (uid:0)

這是一個遞歸函數。正如你可以想象的那樣,當你發射200個bash炮彈然後觸發事件時,事情就會變糟。我不確定發生了什麼,但機器凍結。內核跑出了我所假設的堆棧空間,去了OOM,然後自己開槍?

我想知道什麼是處理這種情況的最佳方式。我看到幾個選項:

1)停止走流程樹數處理後

2)停止一些字符數組後步行(最終將被打印的)充滿

3)利用一個goto而不是遞歸函數,並且仍然聽從從選項#1和#2

4)的新規則中使用,你會說出我

這是發生在其他一些非遞歸方法內核sp王牌,所以不是最好客的環境。任何人都可以給出任何指示,以採取這種最好的方法?

+0

'get_task_parent'不是Linux內核中的一個現有函數,至少不是我知道的內核源代碼。另外,'MAX_FILE_LEN'大小未知。您的問題假設缺少詳細信息。 –

+0

我更新了問題,並添加了關於該問題的註釋。謝謝 –

回答

5

事實上,你內核崩潰的原因可能是你正在使用遞歸函數。

你可以使用一個非常簡單的循環,而不是遞歸函數......你是來自一個函數式編程世界嗎? while循環在C中是標準的,但如果你真的想使用goto,你可以......;)下面是使用循環的代碼。

void parent_task_walk(struct task_struct* task) 
{ 

    struct task_struct *parent = NULL; 
    char filename[MAX_FILE_LEN]; 


    while (task && task->mm) { 

     parent = get_task_parent(task); 

     printk("%s (uid:%d)", 
       exe_from_mm(task->mm, filename, MAX_FILE_LEN), 
       get_task_uid(task)); 

     if (parent && task->pid != 1) 
      printk(", "); 

     task = parent; 
    } 

} 
+1

有時顯然逃脫我:) –