# 2021q3 Homework1 (quiz1) contributed by < `KiwiWang` > ## Reference 1. https://www.kernel.org/doc/html/latest/trace/ftrace-uses.html 2. https://github.com/torvalds/linux/blob/master/include/linux/list.h 3. https://elixir.bootlin.com/linux/latest/source/include/linux/ftrace.h ## 解釋程式碼運作原理,包含 ftrace 的使用 建立 `ftrace_ops`,並將觸發條件設在 `find_ge_pid` 被呼叫時。 ```c static void init_hook(void) { real_find_ge_pid = (find_ge_pid_func) kallsyms_lookup_name("find_ge_pid"); hook.name = "find_ge_pid"; hook.func = hook_find_ge_pid; hook.orig = &real_find_ge_pid; hook_install(&hook); } // static int hook_install(struct ftrace_hook *hook) { // 解析出 find_ge_pid 的 address int err = hook_resolve_addr(hook); if (err) return err; // 在 find_ge_pid 被呼叫時,進入hook_ftrace_thunk hook->ops.func = hook_ftrace_thunk; // 重點是 FTRACE_OPS_FL_SAVE_REGS 和 FTRACE_OPS_FL_IPMODIFY // 因為我們在 callback 中想要變更 regs->ip // 將程式執行導向自定義的 hook_find_ge_pid // hook_find_ge_pid() 執行真正的 find_ge_pid() 後 // 搜尋 linked list 看 find_ge_pid() 回傳的 pid_t 是否在隱藏名單中 // 如果在,則將 nr (即 pid_t) 加 1 後再執行 // 以此達到讓 Module 外部呼叫的find_ge_pid() // 找不到想隱藏的 pid hook->ops.flags = FTRACE_OPS_FL_SAVE_REGS | FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_IPMODIFY; err = ftrace_set_filter_ip(&hook->ops, hook->address, 0, 0); // ... err = register_ftrace_function(&hook->ops); // ... return 0; } ``` 除了上述基本流程,還有 `within_module()` 以及 `real_find_ge_pid` 的應用,確保此核心模組可以使用到真正的 `find_ge_pid()`。 然而,目前(7/25)還看不出來為何一定要使用 `list_add_tail()` 。 linked list 在此的應用僅僅是作為 table ,且程式碼是以單純的 for-loop 來執行搜尋(複雜度 `O(N)` ),新 node 安插在 list 頭或尾應該沒有差異。 需要再實驗看看。 另外: 1. `unhide_process()` 的實作不完全,沒有去檢查 `pid` 2. `module_exit` 至少要移除 `ftrace_ops` (需要再檢查有沒有其他漏的資源...) 3. linked list 應該可以改為 Hash Table ## 本核心模組只能隱藏單一 PID,請擴充為允許其 PPID 也跟著隱藏,或允許給定一組 PID 列表,而非僅有單一 PID 1. `get_ppid()` 2. 給定一組 PID 列表的功能,目前想起來需要處理 command-line string。或者也可以用檔案溝通,只是要研究核心模組如何打開檔案及相關權限問題 ## 指出程式碼可改進的地方,並動手實作 <s>來得及的話</s>預計會修正上面提到的 1. `unhide_process()` 的實作不完全,沒有去check `pid` 2. `module_exit` 至少要移除 ftrace_ops (需要再檢查有沒有其他漏的資源) 實際上因為 2. 的關係,再次 insmod 時會出問題 > Note, only one ftrace_ops with FTRACE_OPS_FL_IPMODIFY set may be registered to any given function at a time. 3. <s>來得及就</s>將 linked list 換成 hash 寫寫看... :::warning 不需要特別說「來得及就」,看到哪裡有坑洞,就去填補! :notes: jserv OK. Thanks :) :notes: Kiwi ::: ## 修正resource leakage ```c static struct cdev cdev; static struct class *hideproc_class = NULL; // originate from alloc_chrdev_region(&dev, ...) // dev_major is obtained by MAJOR(dev) static unsigned int dev_major; // ... static void _hideproc_exit(void) { pid_node_t *proc, *tmp_proc; printk(KERN_INFO "@ %s\n", __func__); list_for_each_entry_safe (proc, tmp_proc, &hidden_proc, list_node) { list_del(&proc->list_node); kfree(proc); } hook_remove(&hook); device_destroy(hideproc_class, MKDEV(dev_major, MINOR_VERSION)); class_destroy(hideproc_class); cdev_del(&cdev); unregister_chrdev_region(MKDEV(dev_major, MINOR_VERSION), MINOR_VERSION); } ``` ## 測試script 增加一個簡單的測試 [script](https://github.com/KiwiWang/linux-summer-2021/blob/main/quiz1/run_test.py) 以測試 `list_add()`, `list_add_tail()` 在這個 [script](https://github.com/KiwiWang/linux-summer-2021/blob/main/quiz1/run_test.py) 覆蓋的測試範圍下兩者都可正常工作。 ## Hash Table TODO...