# 2021q3 Homework1 (quiz1) contributed by < `bochengC` > ###### tags: `linux2021` 參考資料: [ftrace的使用](https://richardweiyang-2.gitbook.io/kernel-exploring/00-index-3/05-kernel_live_patch) 、 [about macro](https://stackoverflow.com/questions/21361854/how-are-linux-kernel-macros-used-as-functions)、[macro2](https://www.programmersought.com/article/51941881025/) ### 1.解釋上述程式碼運作原理,包含 ftrace 的使用 ftrace 的重點部分都是在 hook_install 裡 ```c= static int hook_install(struct ftrace_hook *hook) // after hook_init { int err = hook_resolve_addr(hook);//line 20 給addr if (err) return err; hook->ops.func = hook_ftrace_thunk; 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); if (err) { printk("ftrace_set_filter_ip() failed: %d\n", err); return err; } err = register_ftrace_function(&hook->ops); if (err) { printk("register_ftrace_function() failed: %d\n", err); ftrace_set_filter_ip(&hook->ops, hook->address, 1, 0); // remove return err; } return 0; } ``` 在 hook_install 中,利用 `ftrace_set_filter_ip` 函數由這個函數決定是否要啟動 hook 的功能,只知道跟 `ftrace_ops` 結構中的 `*notrace_hash`, `*filter_hash` 兩個雜湊表有關係,但是詳細在看程式碼時沒有完全明白,只知道換成 `filter_hash` 會觸發 hook 的函式。 再利用 `register_ftrace_function` 將這個 ops 加入到整個系統的 `ops list` 中。 當系統呼叫 `real_find_ge_pid` 時,會引發 hook 透過 `ftrace_ops_test()` 來比對 ops 。 ### 2. 本程式僅在 Linux v5.4 測試,若你用的核心較新,請試著找出替代方案 運氣不錯,剛好用 linux v5.4,沒有遇到這個問題 ### 3.1 隱藏 PPID (未完成) hint: [kstrtol()](http://c.biancheng.net/cpp/html/129.html) return 0 原本設計是想使用 kstrtol() ,作為分割的函數即可,可惜後來發現, kstrtol(),要直到遇到結束符號才會進行回傳,因此會在加入多個 pid 時,只有讀取到最後一個,只好更換策略,使用strsep。 原始 kstrtol 程式碼如下。 ```c= if(state == 1){ ret=kstrtol(message + i, 10, &pid); //return 0 when success printk("i=%d, pid=%ld, ret=%d", i, pid, ret); if(!ret)hide_process(pid); //-22 是parsing error -EINVAL state = 0; } ``` 使用 strsep() 的程式碼如下 ```c= if (!memcmp(message, add_message, sizeof(add_message) - 1)) { cptr = message + sizeof(add_message); for (token = strsep(&cptr, delim); token != NULL; token = strsep(&cptr, delim)) { kstrtol(token, 10, &pid); if (pid) hide_process(pid); } } else if (!memcmp(message, del_message, sizeof(del_message) - 1)) { cptr = message + sizeof(del_message); for (token = strsep(&cptr, delim); token != NULL; token = strsep(&cptr, delim)) { kstrtol(token, 10, &pid); if (pid) unhide_process(pid); } } else { kfree(message); return -EAGAIN; } ``` 但這樣會有讀取到負數的問題, ### 3.2 隱藏 PIDlist (未完成) ?? 兩個混合? ### 4.指出程式碼可改進的地方,並動手實作 ref : [github](https://github.com/lvming/sample-modules/blob/master/sample-cdev.c) 離開 hideproc 的時候,沒有把資源歸還,即便 rmmod 了,仍然會造成系統crash, 因此在程式碼中加入移除 module 時,將使用的資源完全歸還。這部分的做法基本上就是,在 init 增加了什麼,就在 exit 還回去,有一一對應的關係。 根據 `The Linux Kernel Module Guide` 29頁的做法,將` character device` 註銷。 又在 `_hideproc_init` 中沒有看到 `register_chrdev_region ` ,因此把 `unregister` 的部分拿掉。 再把 _hideproc_init() 內的 dev_t dev 變成全域變數。 修改好的 _hideproc_exit() 如下 ```c= static void _hideproc_exit(void) { printk(KERN_INFO "@ %s\n", __func__); hook_remove(&hook); device_destroy(hideproc_class , dev); cdev_del(&cdev); class_destroy(hideproc_class); unregister_chrdev_region(&dev, MINOR_VERSION); /* FIXME: ensure the release of all allocated resources */ } ``` 5. 加入會隱藏hideproc本身的 pid 方法,讓自己本身也不會被函數抓到。