contributed by < fdgkhdkgh >
linux2021
kernel
在 kernel module 初始化的地方,呼叫 init_hook
static int _hideproc_init(void)
{
.
.
.
init_hook();
return 0;
}
struct ftrace_hook {
const char *name;
void *func, *orig;
unsigned long address;
struct ftrace_ops ops;
};
.
.
.
static void init_hook(void)
{
// 使用 kallsyms_lookup_name 去找到 linux kernel 中 "find_ge_pid" 這個 function 的位址
real_find_ge_pid = (find_ge_pid_func) kallsyms_lookup_name("find_ge_pid");
hook.name = "find_ge_pid";
// 儲存我們想執行的 find_ge_pid 的位址
hook.func = hook_find_ge_pid;
// 儲存真正的 find_ge_pid 的位址
hook.orig = &real_find_ge_pid;
// 開始安裝我們在這裡設定的 ftrace hook
hook_install(&hook);
}
static int hook_install(struct ftrace_hook *hook)
{
// 再抓取一次我們想 hook 的 kernel function 的位址
// 若抓取失敗則回傳錯誤碼
int err = hook_resolve_addr(hook);
if (err)
return err;
// 註冊 ftrace 的 call back function
hook->ops.func = hook_ftrace_thunk;
hook->ops.flags = FTRACE_OPS_FL_SAVE_REGS | FTRACE_OPS_FL_RECURSION_SAFE |
FTRACE_OPS_FL_IPMODIFY;
// hook->address : 被我們 hook 的 kernel function
// ftrace_set_filter_ip : 哪些 ip address 可以使用這個 ftrace 的 call back function。
// e.g. 這邊使用的是真正的 find_ge_pid 的位址,表示當我們呼叫 find_ge_pid 時,
// 會進入此 ftrace 設定的 call back function ( 也就是 hook_ftrace_thunk )
// 而呼叫其他的 function 則不會進入此 ftrace 的 call back function
err = ftrace_set_filter_ip(&hook->ops, hook->address, 0, 0);
if (err) {
printk("ftrace_set_filter_ip() failed: %d\n", err);
return err;
}
// 註冊這個 ftrace,並開始啟用
err = register_ftrace_function(&hook->ops);
if (err) {
printk("register_ftrace_function() failed: %d\n", err);
// 註冊失敗的話,要把這個 filter 關掉
ftrace_set_filter_ip(&hook->ops, hook->address, 1, 0);
return err;
}
return 0;
}
設定好後,每當 linux kernel 裡除了我們的 kernel module 以外的任何地方呼叫 "find_ge_pid" ,就會執行我們所設定的 frace 的 call back function "hook_ftrace_thunk"。
static void notrace hook_ftrace_thunk(unsigned long ip,
unsigned long parent_ip,
struct ftrace_ops *ops,
struct pt_regs *regs)
{
struct ftrace_hook *hook = container_of(ops, struct ftrace_hook, ops);
// 假如 caller 的 instruction pointer 並不在我們這個 kernel module 的範疇內,
// 就將其 instruction pointer 指向我們這個 kernel module 版本的 hook_find_ge_pid
if (!within_module(parent_ip, THIS_MODULE))
regs->ip = (unsigned long) hook->func;
}
從 ftrace 的 call back function "hook_ftrace_thunk" 會跳轉到我們的 kernel module 所實作的 hook_find_ge_pid。
static struct pid *hook_find_ge_pid(int nr, struct pid_namespace *ns)
{
struct pid *pid = real_find_ge_pid(nr, ns);
// 只要想要搜尋的 pid_t 位於 hidden_list 內,就讓 "real_find_ge_pid" 去搜尋 pid_t + 1 ,藉此隱藏 pid_t
while (pid && is_hidden_proc(pid->numbers->nr))
pid = real_find_ge_pid(pid->numbers->nr + 1, ns);
return pid;
}
使用的是 linux-5.4.134 ,剛好不會碰上這個問題。
$ uname -a
Linux tommy-X450VP 5.4.134 #1 SMP Sun Jul 25 17:18:47 CST 2021 x86_64 x86_64 x86_64 GNU/Linux
static ssize_t device_write(struct file *filep,
const char *buffer,
size_t len,
loff_t *offset)
{
long pid;
char *message;
char add_message[] = "add", del_message[] = "del";
if (len < sizeof(add_message) - 1 && len < sizeof(del_message) - 1)
return -EAGAIN;
message = kmalloc(len + 1, GFP_KERNEL);
memset(message, 0, len + 1);
copy_from_user(message, buffer, len);
if (!memcmp(message, add_message, sizeof(add_message) - 1)) {
kstrtol(message + sizeof(add_message), 10, &pid);
struct task_struct *task = pid_task(find_vpid(pid), PIDTYPE_PID);
struct pid_t *ppid = task_ppid_nr(task);
hide_process(pid);
hide_process(ppid);
} else if (!memcmp(message, del_message, sizeof(del_message) - 1)) {
kstrtol(message + sizeof(del_message), 10, &pid);
unhide_process(pid);
} else {
kfree(message);
return -EAGAIN;
}
使用簡易的 parser 將 PID 列表裡的所有 PID 用 hide_process 隱藏起來
static ssize_t device_write(struct file *filep,
const char *buffer,
size_t len,
loff_t *offset)
{
long pid;
char *message;
char add_message[] = "add", del_message[] = "del";
if (len < sizeof(add_message) - 1 && len < sizeof(del_message) - 1)
return -EAGAIN;
message = kmalloc(len + 1, GFP_KERNEL);
memset(message, 0, len + 1);
copy_from_user(message, buffer, len);
if (!memcmp(message, add_message, sizeof(add_message) - 1)) {
hide_processes((char *) message + sizeof(add_message));
} else if (!memcmp(message, del_message, sizeof(del_message) - 1)) {
unhide_processes((char *) message + sizeof(del_message));
} else {
kfree(message);
return -EAGAIN;
}
*offset = len;
kfree(message);
return len;
}
.
.
.
void hide_processes(char *pids) {
char num[32];
memset(num, 0, sizeof(num));
int stat = 0;
int i = 0;
int numi = 0;
long pid = 0;
while(pids[i] != 0) {
if(stat == 0) {
if(pids[i] >= '0' && pids[i] <= '9') {
num[numi++] = pids[i];
stat = 1;
}
} else if(stat == 1) {
if(pids[i] >= '0' && pids[i] <= '9') {
num[numi++] = pids[i];
} else {
kstrtol(num, 10, &pid);
printk("%d\n", pid);
hide_process(pid);
memset(num, 0, sizeof(num));
numi = 0;
stat = 0;
}
}
i++;
}
if(num[0] != 0) {
kstrtol(num, 10, &pid);
printk("%d\n", pid);
hide_process(pid);
}
}
在釋放 kernel module 前使用老師寫好的 hook_remove 將 hook 釋放。
static void _hideproc_exit(void)
{
printk(KERN_INFO "@ %s\n", __func__);
hook_remove(&hook);
}
避免同一個 pid 重複出現在 linked list 裡。
static int hide_process(pid_t pid)
{
if(!is_hidden_proc(pid)) {
pid_node_t *proc = kmalloc(sizeof(pid_node_t), GFP_KERNEL);
proc->id = pid;
// TODO
list_add(&(proc->list_node), &hidden_proc);
}
return SUCCESS;
}
插入節點由 O(1) 變慢成 O(logn)
刪除節點由 O(n) 加快成 O(logn)
查詢節點由 O(n) 加快成 O(logn)
https://github.com/fdgkhdkgh/linux2021-summer-q1/tree/main/main_rb
https://github.com/riscv-collab/riscv-gnu-toolchain
Jun 10, 2024glog[Accepted] https://github.com/google/glog/commit/18836106d1fe6893c5cf3db1682b6916fdd4f34c– this patch make glog 50% faster in specific situaltion– thank ᴀᴇsᴏᴘʜᴏʀ for advice.
Aug 16, 2023contributed by < fdgkhdkgh > 第二週隨堂測驗題 解釋上述程式碼運作原理 /* This returns the same value that is passed as ptr. * Progress condition: wait-free population oblivious. */ uintptr_t list_hp_protect_ptr(list_hp_t *hp, int ihp, uintptr_t ptr) {
Aug 19, 2021測驗 $\gamma\ -\ 1$ 因為 fork 出新的 process 時,會連同 buffered I/O 也一併複製過去。所以總 '-' 數量會是所有 process 數量 * NNN。 在此例題的例子,NNN == 12,總 process 的數量為 4096 ==> 總 '-' 數量 == 49152。 可以用簡易的程式來計算出不同的 NNN 會印出多少的 '-' 以及 fork 出多少個 process。 #include <stdio.h> #include <stdlib.h>
Jul 19, 2021or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up