--- tags: linux2021 --- # 2021q3 Homework1 (quiz1) contributed by <`SmallHanley`> Follow [quiz1](https://hackmd.io/@sysprog/linux2021-summer-quiz1) ___ ## Environment OS: Ubuntu 20.04 (multipass) Kernel version: 5.4.0-80-generic ## Q & A ### Q1 :::success 解釋上述程式碼運作原理,包含 [ftrace](https://www.kernel.org/doc/Documentation/trace/ftrace.txt) 的使用 ::: ### Q3 :::success 本核心模組只能隱藏單一 PID,請擴充為允許其 PPID 也跟著隱藏,或允許給定一組 PID 列表,而非僅有單一 PID ::: 在 `hide_process` 中增加 PPID 隱藏的實作。首先,用 `find_vpid` 得到 `struct pid`,再用 `pid_task` 得到 `task_struct`,利用 `task_struct` 找出 parent 的 pid (`ppid`),與 `pid` 一併加到 list 中,實作如下: ```c static int hide_process(pid_t pid) { pid_node_t *proc, *pproc; struct pid *kpid; struct task_struct *task; proc = kmalloc(sizeof(pid_node_t), GFP_KERNEL); proc->id = pid; list_add_tail(&proc->list_node, &hidden_proc); pproc = kmalloc(sizeof(pid_node_t), GFP_KERNEL); kpid = find_vpid(pid); task = pid_task(kpid, PIDTYPE_PID); pproc->id = task->real_parent->pid; list_add_tail(&pproc->list_node, &hidden_proc); return SUCCESS; } ``` 同理,`unhide_process` 也用一樣方式找 `ppid`: ```c static int unhide_process(pid_t pid) { pid_node_t *proc, *tmp_proc; struct pid *kpid; struct task_struct *task; pid_t ppid; kpid = find_vpid(pid); task = pid_task(kpid, PIDTYPE_PID); ppid = task->real_parent->pid; list_for_each_entry_safe (proc, tmp_proc, &hidden_proc, list_node) { if (proc->id == pid || proc->id == ppid) { list_del(&proc->list_node); kfree(proc); } } return SUCCESS; } ``` 測試程式: ```c #include <unistd.h> int main(void) { fork(); while(1); return 0; } ``` 編譯執行: ```shell $ gcc -o test test.c $ ./test & ``` 查詢測試程式 pid、ppid: ```shell $ ps -ef | grep test ubuntu 1536 1032 49 11:35 pts/0 03:40:11 ./test ubuntu 1537 1536 49 11:35 pts/0 03:40:11 ./test ``` 其中,1536 是 parent process,1537 是 child process,用 1537 做測試,預期 1536 和 1537 會被隱藏: ```shell $ sudo insmod hideproc.ko $ echo "add 1537" | sudo tee /dev/hideproc $ ps -ef | grep test # 無法見到 1536、1537 $ echo "del 1537" | sudo tee /dev/hideproc $ ps -ef | grep test # 再次見到 1536、1537 ubuntu 1536 1032 49 11:35 pts/0 03:40:11 ./test ubuntu 1537 1536 49 11:35 pts/0 03:40:11 ./test $ sudo rmmod hideproc ``` 測試結果符合預期。 ### Q4 :::success 指出程式碼可改進的地方,並動手實作 ::: 細觀 quiz1 的程式碼,缺少資源釋放的實作,於是在 module_exit (`_hideproc_exit`) 的地方增加 hook、device、class 等資源釋放。另外,list 的空間也需要 free。 ```c dev_t dev; static void _hideproc_exit(void) { pid_node_t *proc, *tmp_proc; printk(KERN_INFO "@ %s\n", __func__); /* FIXME: ensure the release of all allocated resources */ hook_remove(&hook); device_destroy(hideproc_class, MKDEV(MAJOR(dev), MINOR_VERSION)); class_destroy(hideproc_class); cdev_del(&cdev); unregister_chrdev_region(dev, MINOR_VERSION); list_for_each_entry_safe (proc, tmp_proc, &hidden_proc, list_node) { list_del(&proc->list_node); kfree(proc); } } ``` 另外,在做 `unhide_process` 時,會發現 `list_for_each_entry_safe` 內會一次刪除所有節點,需要加上條件判斷: ```c static int unhide_process(pid_t pid) { pid_node_t *proc, *tmp_proc; list_for_each_entry_safe (proc, tmp_proc, &hidden_proc, list_node) { if (proc->id == pid) { list_del(&proc->list_node); kfree(proc); } } return SUCCESS; } ``` ## Reference https://elixir.bootlin.com/linux/latest/source https://www.kernel.org/doc/html/latest/index.html https://blog.csdn.net/cnbird2008/article/details/11560109 (直接搜尋 linux document 找不到有關 pid、task 和 ppid 相關的 API,於是參考二手資料再交叉比對)