---
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,於是參考二手資料再交叉比對)