# 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 方法,讓自己本身也不會被函數抓到。