# 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...