contributed by <93i7xo2
>
Source: quiz1
ftrace 的功用是在目標函式前附加上 callback 來追蹤在 kernel 內的流程,使用這項功能必須用 struct ftrace_ops
來告知 ftrace 何者為 callback。
struct ftrace_hook {
...
struct ftrace_ops ops;
};
啟用/停用方法如下:
register_ftrace_function(&ops);
unregister_ftrace_function(&ops);
以 ftrace_set_filter()
對特定名稱的函式進行 hook,若函式名稱重複可以指定 ip
的方式進行,hook_install()
即採用後者:
/**
* ftrace_set_filter_ip - set a function to filter on in ftrace by address
* @ops - the ops to set the filter with
* @ip - the address to add to or remove from the filter.
* @remove - non zero to remove the ip from the filter
* @reset - non zero to reset all filters before applying this filter.
*
* Filters denote which functions should be enabled when tracing is enabled
* If @ip is NULL, it fails to update filter.
*/
int ftrace_set_filter_ip(struct ftrace_ops *ops, unsigned long ip,
int remove, int reset)
ret = ftrace_set_filter(&ops, "schedule", strlen("schedule"), 0);
ret = ftrace_set_filter_ip(&ops, ip, 0, 0);
在 callback 換掉 regs->ip
達到劫持的作用:
static void notrace hook_ftrace_thunk(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *ops,
struct pt_regs *regs) {
...
regs->ip = (unsigned long)hook->func;
}
hook_install()
行為kallsyms_lookup_name
找尋名稱為 find_ge_pid
的 addressProblem:
hook_find_ge_pid
行為不明,明明有簡單的 find_pid_ns
可用。static struct pid *hook_find_ge_pid(int nr, struct pid_namespace *ns) {
struct pid *pid = real_find_ge_pid(nr, ns);
while (pid && is_hidden_proc(pid->numbers->nr))
pid = real_find_ge_pid(pid->numbers->nr + 1, ns);
return pid;
}
hook.func = hook_find_ge_pid;
而非 hook.func = &hook_find_ge_pid;
$ uname -r
5.4.0-80-generic
To-do
在 device_write()
內以 strsep
分離字串(核心內無法使用 strtok
),達到多個 pid 同時輸入的可能,最後去除輸入時重複 pid 的 entry。
static ssize_t device_write(struct file *filep, const char *buffer, size_t len,
loff_t *offset) {
...
while ((found = strsep(&start, " ")) != NULL) {
if ((ret = kstrtol(found, 10, &pid)) == 0) {
switch (input_mode) {
case _ADD:
hide_process(pid);
break;
case _DEL:
unhide_process(pid);
break;
}
}
}
/* remove duplicate entries */
list_sort(priv, &hidden_proc, &list_cmp);
list_for_each_entry_safe(proc, tmp_proc, &hidden_proc, list_node) {
if (&tmp_proc->list_node != (&hidden_proc) && tmp_proc->id == proc->id) {
list_del(&proc->list_node);
kfree(proc);
}
}
...
}
假設 pid = {1, 2, 7, 8, 6}
的 process 存在,批次隱藏/復原 pid 的步驟如下:
$ sudo insmod hideproc.ko
$ echo "add 8 7 6" | sudo tee /dev/hideproc
add 8 7 6
$ echo "del 1 2 8" | sudo tee /dev/hideproc
del 1 2 8
$ sudo cat /dev/hideproc
pid 6
pid 7
$ echo "del 6" | sudo tee /dev/hideproc
del 6
$ sudo cat /dev/hideproc
pid 7
$ sudo rmmod hideproc
適當的初始化及釋放資源
static int _hideproc_init(void) {
int dev_major;
printk(KERN_INFO "@ %s\n", __func__);
if (alloc_chrdev_region(&dev, 0, MINOR_VERSION, DEVICE_NAME) < 0) {
return -1;
}
dev_major = MAJOR(dev);
cdev_init(&cdev, &fops);
if (cdev_add(&cdev, MKDEV(dev_major, MINOR_VERSION), 1) == -1) {
unregister_chrdev_region(dev, 1);
return -1;
}
if (IS_ERR(hideproc_class = class_create(THIS_MODULE, DEVICE_NAME))) {
cdev_del(&cdev);
unregister_chrdev_region(dev, 1);
return -1;
}
if (IS_ERR(device_create(hideproc_class, NULL,
MKDEV(dev_major, MINOR_VERSION), NULL,
DEVICE_NAME))) {
class_destroy(hideproc_class);
cdev_del(&cdev);
unregister_chrdev_region(dev, 1);
return -1;
}
init_hook();
return 0;
}
static void _hideproc_exit(void) {
hook_remove(&hook);
device_destroy(hideproc_class, MKDEV(MAJOR(dev), MINOR_VERSION));
class_destroy(hideproc_class);
cdev_del(&cdev);
unregister_chrdev_region(dev, 1);
printk(KERN_INFO "@ %s\n", __func__);
}
卸載模組前告知 ftrace 並釋放 list 上所有元素
void hook_remove(struct ftrace_hook *hook) {
pid_node_t *proc, *tmp_proc;
list_for_each_entry_safe(proc, tmp_proc, &hidden_proc, list_node) {
list_del(&proc->list_node);
kfree(proc);
}
int err = unregister_ftrace_function(&hook->ops);
if (err)
printk("unregister_ftrace_function() failed: %d\n", err);
err = ftrace_set_filter_ip(&hook->ops, hook->address, 1, 0);
if (err)
printk("ftrace_set_filter_ip() failed: %d\n", err);
}
contribute by < 93i7xo2 > Source: quiz3 作業區 測驗 11 static inline unsigned long fls(unsigned long word) { int num = 64 - 1;
Mar 16, 2022contributed by < 93i7xo2 > Source: 2021q1 第 4 週測驗題 資料結構 Thread Pool & Job Queue struct __threadpool { size_t count; pthread_t *workers; jobqueue_t *jobqueue;
Mar 11, 2022本篇介紹 Quantization table Huffman table Encoded data 在JPEG檔案內排列的順序,範例參考Understanding and Decoding a JPEG Image using Python,參考規格書補漏,並實作JPEG decoder。 JPEG有4種壓縮格式
Feb 9, 2022簡介 Baseline JPEG Baseline編碼時依序將經過下面流程: RGB to Y'CbCr 2-D DCT Quantization Huffman encoding 最後Header、Huffman table、Quantization table和資料一起包裝成jpg。
Feb 9, 2022or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up