diff --git a/cgroupv2_freeze/Makefile b/cgroupv2_freeze/Makefile index 5eb0449..76959a1 100644 --- a/cgroupv2_freeze/Makefile +++ b/cgroupv2_freeze/Makefile @@ -1,4 +1,4 @@ -MYKPM_VERSION := 1.0.4 +MYKPM_VERSION := 1.0.5 ifndef KP_DIR KP_DIR = ../KernelPatch diff --git a/cgroupv2_freeze/README.md b/cgroupv2_freeze/README.md index 885cc17..ab83ef4 100644 --- a/cgroupv2_freeze/README.md +++ b/cgroupv2_freeze/README.md @@ -3,6 +3,8 @@ 为低版本内核添加 cgroup.freeze ## 更新记录 +### 1.0.5 +补全uid模式, 不再需要附加模块 ### 1.0.4 使用其他方式替代所有内核版本判断条件,变更 task_struct->jobctl 获取方式 ### 1.0.3 diff --git a/cgroupv2_freeze/cfv2_offsets.c b/cgroupv2_freeze/cfv2_offsets.c new file mode 100644 index 0000000..4d36d2d --- /dev/null +++ b/cgroupv2_freeze/cfv2_offsets.c @@ -0,0 +1,55 @@ +// task_state_ptr +static inline volatile long* task_state_ptr(struct task_struct* task) { + volatile long* state = (volatile long*)((uintptr_t)task + task_struct_state_offset); + return state; +} +// task_flags +static inline unsigned int task_flags(struct task_struct* task) { + unsigned int flags = *(unsigned int*)((uintptr_t)task + task_struct_flags_offset); + return flags; +} +// task_flags_ptr +static inline unsigned int* task_flags_ptr(struct task_struct* task) { + unsigned int* flags = (unsigned int*)((uintptr_t)task + task_struct_flags_offset); + return flags; +} +// task_jobctl +static inline unsigned long task_jobctl(struct task_struct* task) { + unsigned long jobctl = *(unsigned long*)((uintptr_t)task + task_struct_jobctl_offset); + return jobctl; +} +// task_jobctl_ptr +static inline unsigned long* task_jobctl_ptr(struct task_struct* task) { + unsigned long* jobctl = (unsigned long*)((uintptr_t)task + task_struct_jobctl_offset); + return jobctl; +} +// task_signal +static inline struct signal_struct* task_signal(struct task_struct* task) { + struct signal_struct* signal = (struct signal_struct*)((uintptr_t)task + task_struct_signal_offset); + return signal; +} +// signal_group_exit_task +static inline struct task_struct* signal_group_exit_task(struct signal_struct* sig) { + struct task_struct* group_exit_task = *(struct task_struct**)((uintptr_t)sig + signal_struct_group_exit_task_offset); + return group_exit_task; +} +// signal_flags +static inline unsigned int signal_flags(struct signal_struct* sig) { + unsigned int flags = *(unsigned int*)((uintptr_t)sig + signal_struct_flags_offset); + return flags; +} +// seq_file_private +static inline struct kernfs_open_file* seq_file_private(struct seq_file* seq) { + struct kernfs_open_file* private = *(struct kernfs_open_file**)((uintptr_t)seq + seq_file_private_offset); + return private; +} +// cgroup_flags_ptr +static inline unsigned long* cgroup_flags_ptr(struct cgroup* cgrp) { + unsigned long* flags = (unsigned long*)((uintptr_t)cgrp + cgroup_flags_offset); + return flags; +} +// css_set_dfl_cgrp +static inline struct cgroup* css_set_dfl_cgrp(struct css_set* cset) { + struct cgroup* cgrp = *(struct cgroup**)((uintptr_t)cset + css_set_dfl_cgrp_offset); + return cgrp; +} diff --git a/cgroupv2_freeze/cgroupv2_freeze.c b/cgroupv2_freeze/cgroupv2_freeze.c index d98a1db..4a21606 100644 --- a/cgroupv2_freeze/cgroupv2_freeze.c +++ b/cgroupv2_freeze/cgroupv2_freeze.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include "cgroupv2_freeze.h" #include "cfv2_utils.h" @@ -24,7 +24,7 @@ KPM_NAME("cgroupv2_freeze"); KPM_VERSION(MYKPM_VERSION); KPM_LICENSE("GPL v2"); KPM_AUTHOR("lzghzr"); -KPM_DESCRIPTION("add cgroup.freeze, support 4.4, 4.9 4.19"); +KPM_DESCRIPTION("add cgroup.freeze, support 4.4 ~ 4.19"); #define GLOBAL_SYSTEM_UID KUIDT_INIT(1000) #define GLOBAL_SYSTEM_GID KGIDT_INIT(1000) @@ -32,6 +32,9 @@ KPM_DESCRIPTION("add cgroup.freeze, support 4.4, 4.9 4.19"); #define IZERO (1UL << 0x10) #define UZERO (1UL << 0x20) +// 延迟加载, KernelPatch支持 事件加载 后弃用 +static struct file* (*do_filp_open)(int dfd, struct filename* pathname, const struct open_flags* op); + // do_freezer_trap static int (*proc_pid_wchan)(struct seq_file* m, struct pid_namespace* ns, struct pid* pid, struct task_struct* task); void kfunc_def(schedule)(void); @@ -44,7 +47,7 @@ static void (*css_task_iter_start_v4)(struct cgroup_subsys_state* css, struct cs static struct task_struct* (*css_task_iter_next)(struct css_task_iter* it); static void (*css_task_iter_end)(struct css_task_iter* it); // cgroup_freeze -struct cgroup_subsys_state* (*css_next_descendant_pre)(struct cgroup_subsys_state* pos, struct cgroup_subsys_state* root); +static struct cgroup_subsys_state* (*css_next_descendant_pre)(struct cgroup_subsys_state* pos, struct cgroup_subsys_state* root); // cgroup_freeze_show struct cgroup_subsys_state* kfunc_def(of_css)(struct kernfs_open_file* of); void kfunc_def(seq_printf)(struct seq_file* m, const char* f, ...); @@ -54,30 +57,37 @@ static struct cgroup* (*cgroup_kn_lock_live_v4)(struct kernfs_node* kn); static void (*cgroup_kn_unlock)(struct kernfs_node* kn); int kfunc_def(kstrtoint)(const char* s, unsigned int base, int* res); char* kfunc_def(strim)(char* s); +// run_cmd +int kfunc_def(call_usermodehelper)(const char* path, char** argv, char** envp, int wait); +static int* selinux_enforcing; // hook cgroup_addrm_files static int (*cgroup_addrm_files)(struct cgroup_subsys_state* css, struct cgroup* cgrp, struct cftype cfts[], bool is_add); static int (*cgroup_init_cftypes)(struct cgroup_subsys* ss, struct cftype* cfts); // hook cgroup_procs_write -ssize_t(*cgroup_procs_write)(struct kernfs_open_file* of, char* buf, size_t nbytes, loff_t off); +static ssize_t(*cgroup_procs_write)(struct kernfs_open_file* of, char* buf, size_t nbytes, loff_t off); +// hook css_set_move_task +static void (*css_set_move_task)(struct task_struct* task, struct css_set* from_cset, struct css_set* to_cset, bool use_mg_tasks); // hook __kernfs_create_file -ssize_t(*__kernfs_create_file)(struct kernfs_node* parent, const char* name, umode_t mode, loff_t size, const struct kernfs_ops* ops, void* priv, const void* ns, struct lock_class_key* key); -ssize_t(*kernfs_setattr)(struct kernfs_node* kn, const struct iattr* iattr); +static ssize_t(*__kernfs_create_file)(struct kernfs_node* parent, const char* name, umode_t mode, loff_t size, const struct kernfs_ops* ops, void* priv, const void* ns, struct lock_class_key* key); +static ssize_t(*kernfs_setattr)(struct kernfs_node* kn, const struct iattr* iattr); // hook get_signal static bool(*get_signal)(struct ksignal* ksig); -static uint64_t task_struct_state_offset = UZERO, task_struct_flags_offset = UZERO, task_struct_jobctl_offset = UZERO, task_struct_signal_offset = UZERO, +static uint64_t task_struct_state_offset = UZERO, task_struct_flags_offset = UZERO, task_struct_jobctl_offset = UZERO, task_struct_signal_offset = UZERO, task_struct_css_set_offset = UZERO, signal_struct_group_exit_task_offset = UZERO, signal_struct_flags_offset = UZERO, seq_file_private_offset = UZERO, freezer_state_offset = UZERO, cgroup_flags_offset = UZERO, +css_set_dfl_cgrp_offset = UZERO, css_task_iter_start_ver5 = UZERO, cgroup_kn_lock_live_ver5 = UZERO, cftype_ver5 = UZERO, cgroup_base_files_ver5 = UZERO; +#include "cfv2_offsets.c" // 为待冻结的 task 以及 cgroup 添加必要的标志 static void cgroup_freeze_task(struct task_struct* task, bool freeze) { if (!task) return; - unsigned long* jobctl = (unsigned long*)((uintptr_t)task + task_struct_jobctl_offset); + unsigned long* jobctl = task_jobctl_ptr(task); if (freeze) { *jobctl |= JOBCTL_TRAP_FREEZE; signal_wake_up_state(task, 0); @@ -91,7 +101,7 @@ static void cgroup_do_freeze(struct cgroup* cgrp, bool freeze) { struct css_task_iter it; struct task_struct* task; - unsigned long* flags = (unsigned long*)((uintptr_t)cgrp + cgroup_flags_offset); + unsigned long* flags = cgroup_flags_ptr(cgrp); if (freeze) { set_bit(CGRP_FREEZE, flags); } else { @@ -104,7 +114,7 @@ static void cgroup_do_freeze(struct cgroup* cgrp, bool freeze) { css_task_iter_start_v4(&cgrp->self, &it); } while ((task = css_task_iter_next(&it))) { - unsigned int flags = *(unsigned int*)((uintptr_t)task + task_struct_flags_offset); + unsigned int flags = task_flags(task); if (flags & PF_KTHREAD) continue; cgroup_freeze_task(task, freeze); @@ -112,7 +122,7 @@ static void cgroup_do_freeze(struct cgroup* cgrp, bool freeze) { css_task_iter_end(&it); } -void cgroup_freeze(struct cgroup* cgrp, bool freeze) { +static void cgroup_freeze(struct cgroup* cgrp, bool freeze) { struct cgroup_subsys_state* css; struct cgroup* dsct; @@ -121,13 +131,36 @@ void cgroup_freeze(struct cgroup* cgrp, bool freeze) { cgroup_do_freeze(dsct, freeze); } } -// 处理 v2 uid 模式 + +static ssize_t kernfs_node_freeze(struct kernfs_node* kn, bool freeze, bool force) { + struct cgroup* cgrp; + if (cgroup_kn_lock_live_ver5 == IZERO) { + cgrp = cgroup_kn_lock_live(kn, false); + } else { + cgrp = cgroup_kn_lock_live_v4(kn); + } + + if (!cgrp) + return -ENOENT; + + if (!force) { + unsigned long* flags = cgroup_flags_ptr(cgrp); + freeze = test_bit(CGRP_FREEZE, flags); + } + + cgroup_freeze(cgrp, freeze); + + cgroup_kn_unlock(kn); + + return 0; +} + static int cgroup_freeze_show(struct seq_file* seq, void* v) { - struct kernfs_open_file* private = *(struct kernfs_open_file**)((uintptr_t)seq + seq_file_private_offset); + struct kernfs_open_file* private = seq_file_private(seq); struct cgroup_subsys_state* css = kfunc(of_css)(private); struct cgroup* cgrp = css->cgroup; - unsigned long* flags = (unsigned long*)((uintptr_t)cgrp + cgroup_flags_offset); + unsigned long* flags = cgroup_flags_ptr(cgrp); kfunc(seq_printf)(seq, "%d\n", test_bit(CGRP_FREEZE, flags)); @@ -144,78 +177,92 @@ static ssize_t cgroup_freeze_write(struct kernfs_open_file* of, char* buf, size_ if (freeze < 0 || freeze > 1) return -ERANGE; - struct cgroup* cgrp; - if (cgroup_kn_lock_live_ver5 == IZERO) { - cgrp = cgroup_kn_lock_live(of->kn, false); - } else { - cgrp = cgroup_kn_lock_live_v4(of->kn); - } - - if (!cgrp) - return -ENOENT; - - cgroup_freeze(cgrp, freeze); - - cgroup_kn_unlock(of->kn); - - return nbytes; + ssize_t rc = kernfs_node_freeze(of->kn, freeze, true); + if (rc) + return rc; + else + return nbytes; } static struct cftype cgroup_freeze_files[] = { { .name = "cgroup.freeze", .flags = CFTYPE_NOT_ON_ROOT, - .seq_show = cgroup_freeze_show, - .write = cgroup_freeze_write, - }, - { }, -}; -static struct cftype_v4 cgroup_freeze_files_v4[] = { - { - .name = "cgroup.freeze", - .flags = CFTYPE_NOT_ON_ROOT, - .seq_show = cgroup_freeze_show, - .write = cgroup_freeze_write, }, { }, }; static void cgroup_addrm_files_after(hook_fargs4_t* args, void* udata) { - struct cftype* cfts; - if (cftype_ver5 == IZERO) { - cfts = cgroup_freeze_files; - } else { - cfts = (struct cftype*)cgroup_freeze_files_v4; - } + int ret = (int)args->ret; + if (ret) + return; + ((typeof(cgroup_addrm_files)) - hook_chain_origin_func(args))((struct cgroup_subsys_state*)args->arg0, (struct cgroup*)args->arg1, cfts, (bool)args->arg3); + hook_chain_origin_func(args))((struct cgroup_subsys_state*)args->arg0, (struct cgroup*)args->arg1, cgroup_freeze_files, (bool)args->arg3); } -// 处理 v2 frozen 模式 + +static const char uid_[] = "uid_"; +static const char uid_0[] = "uid_0"; +static const char pid_[] = "pid_"; +// v1 模式并不会附加到 dfl_cgrp, 需要特殊处理 static void cgroup_procs_write_after(hook_fargs4_t* args, void* udata) { + size_t nbytes = (size_t)args->arg2; + size_t ret = (size_t)args->ret; + if (ret != nbytes) + return; + struct kernfs_open_file* of = (struct kernfs_open_file*)args->arg0; - int freeze; + struct kernfs_node* kn = NULL; - if (!strcmp(of->kn->parent->name, "frozen")) { - freeze = 1; - } else if (!strcmp(of->kn->parent->name, "unfrozen")) { - freeze = 0; - } else { - return; + // 处理 v1 frozen 模式 + if (!strcmp(of->kn->parent->name, "frozen") + || !strcmp(of->kn->parent->name, "unfrozen")) { + kn = of->kn->parent; } - - struct cgroup* cgrp; - if (cgroup_kn_lock_live_ver5 == IZERO) { - cgrp = cgroup_kn_lock_live(of->kn, false); - } else { - cgrp = cgroup_kn_lock_live_v4(of->kn); + // 处理 v1 uid 模式 + if (!memcmp(of->kn->parent->name, pid_, sizeof(pid_) - 1) + && (memcmp(of->kn->parent->parent->name, uid_0, sizeof(uid_0))) + && !memcmp(of->kn->parent->parent->name, uid_, sizeof(uid_) - 1)) { + kn = of->kn->parent->parent; } + if (!kn) + return; - if (!cgrp) + kernfs_node_freeze(kn, false, false); +} +// 处理 v2 uid 模式 +static void css_set_move_task_after(hook_fargs4_t* args, void* udata) { + struct task_struct* task = (struct task_struct*)args->arg0; + if (!task) return; - cgroup_freeze(cgrp, freeze); + struct css_set* from_cset = (struct css_set*)args->arg1; + struct cgroup* from_cgrp = NULL; + unsigned long* from_flags = NULL; + + struct css_set* to_cset = (struct css_set*)args->arg2; + struct cgroup* to_cgrp = NULL; + unsigned long* to_flags = NULL; + + if (from_cset) { + from_cgrp = css_set_dfl_cgrp(from_cset); + from_flags = cgroup_flags_ptr(from_cgrp); + } + if (to_cset) { + to_cgrp = css_set_dfl_cgrp(to_cset); + to_flags = cgroup_flags_ptr(to_cgrp); + } - cgroup_kn_unlock(of->kn); + if (!from_cset && to_cset) { + if (test_bit(CGRP_FREEZE, to_flags)) { + unsigned long* jobctl = task_jobctl_ptr(task); + *jobctl |= JOBCTL_TRAP_FREEZE; + } + } else if (from_cset && to_cset) { + if (test_bit(CGRP_FREEZE, from_flags) != test_bit(CGRP_FREEZE, to_flags)) { + cgroup_freeze_task(task, test_bit(CGRP_FREEZE, to_flags)); + } + } } // 修改 cgroup.freeze 所有者为 system:system static void __kernfs_create_file_after(hook_fargs8_t* args, void* udata) { @@ -234,18 +281,18 @@ static void __kernfs_create_file_after(hook_fargs8_t* args, void* udata) { } static inline int signal_group_exit(struct signal_struct* sig) { - unsigned int flags = *(unsigned int*)((uintptr_t)sig + signal_struct_flags_offset); - struct task_struct* group_exit_task = *(struct task_struct**)((uintptr_t)sig + signal_struct_group_exit_task_offset); + unsigned int flags = signal_flags(sig); + struct task_struct* group_exit_task = signal_group_exit_task(sig); return (flags & SIGNAL_GROUP_EXIT) || (group_exit_task != NULL); } static void do_freezer_trap(void) { - unsigned long jobctl = *(unsigned long*)((uintptr_t)current + task_struct_jobctl_offset); + unsigned long jobctl = task_jobctl(current); if ((jobctl & (JOBCTL_PENDING_MASK | JOBCTL_TRAP_FREEZE)) != JOBCTL_TRAP_FREEZE) { return; } - volatile long* state = (volatile long*)((uintptr_t)current + task_struct_state_offset); - unsigned int* flags = (unsigned int*)((uintptr_t)current + task_struct_flags_offset); + volatile long* state = task_state_ptr(current); + unsigned int* flags = task_flags_ptr(current); *state = TASK_INTERRUPTIBLE; clear_thread_flag(TIF_SIGPENDING); @@ -255,8 +302,8 @@ static void do_freezer_trap(void) { } static void get_signal_before(hook_fargs1_t* args, void* udata) { - struct signal_struct* signal = *(struct signal_struct**)((uintptr_t)current + task_struct_signal_offset); - unsigned long* jobctl = (unsigned long*)((uintptr_t)current + task_struct_jobctl_offset); + struct signal_struct* signal = task_signal(current); + unsigned long* jobctl = task_jobctl_ptr(current); for (;;) { if (signal_group_exit(signal)) return; @@ -273,7 +320,7 @@ static void proc_pid_wchan_before(hook_fargs4_t* args, void* udata) { struct seq_file* m = (struct seq_file*)args->arg0; struct task_struct* task = (struct task_struct*)args->arg3; - unsigned long jobctl = *(unsigned long*)((uintptr_t)task + task_struct_jobctl_offset); + unsigned long jobctl = task_jobctl(task); // 用 lookup_symbol_name 判断一下会更好 if (unlikely(jobctl & JOBCTL_TRAP_FREEZE)) { kfunc(seq_printf)(m, "%s", "do_freezer_trap"); @@ -282,6 +329,43 @@ static void proc_pid_wchan_before(hook_fargs4_t* args, void* udata) { } } +static void run_cmd(char* cmd[]) { + char* envp[] = { "HOME=/", "PATH=/sbin:/bin", NULL }; + + *selinux_enforcing = false; + for (int i = 0; cmd[i]; i++) { + char* argv[] = { "/bin/sh", "-c", cmd[i], NULL }; + call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); + } + *selinux_enforcing = true; +} + +static const char apm[] = "/data/adb/modules/"; +static void do_filp_open_after(hook_fargs3_t* args, void* udata) { + struct filename* pathname = (struct filename*)args->arg1; + if (!memcmp(pathname->name, apm, sizeof(apm) - 1)) { + char* cmd[] = { + "if [ ! -d \"/sys/fs/cgroup/uid_0\" ]; then\ + umount /sys/fs/cgroup/freezer;\ + umount /sys/fs/cgroup;\ + \ + chown system:system /sys/fs/cgroup/;\ + mount -t cgroup -o nosuid,nodev,noexec,cpuacct none /sys/fs/cgroup/;\ + \ + mkdir /sys/fs/cgroup/frozen/;\ + chown -R system:system /sys/fs/cgroup/frozen/;\ + echo 1 > /sys/fs/cgroup/frozen/cgroup.freeze;\ + \ + mkdir /sys/fs/cgroup/unfrozen/;\ + chown -R system:system /sys/fs/cgroup/unfrozen/;\ + fi", + NULL + }; + run_cmd(cmd); + unhook_func(do_filp_open); + } +} + static long calculate_offsets() { // 获取 css_task_iter_start 版本, 以参数数量做判断 uint32_t* css_task_iter_start_src = (uint32_t*)css_task_iter_start; @@ -509,17 +593,64 @@ static long calculate_offsets() { if (freezer_state_offset == UZERO) { return -11; } + // 获取 task_struct->css_set + void (*cgroup_fork)(struct task_struct* child); + lookup_name(cgroup_fork); + + uint32_t* cgroup_fork_src = (uint32_t*)cgroup_fork; + for (u32 i = 0; i < 0x10; i++) { +#ifdef CONFIG_DEBUG + logkm("cgroup_fork %x %llx\n", i, cgroup_fork_src[i]); +#endif /* CONFIG_DEBUG */ + if (cgroup_fork_src[i] == ARM64_RET) { + break; + } else if ((cgroup_fork_src[i] & MASK_STR_64) == INST_STR_64) { + uint64_t imm12 = bits32(cgroup_fork_src[i], 21, 10); + task_struct_css_set_offset = sign64_extend((imm12 << 0b11u), 16u); + break; + } + } +#ifdef CONFIG_DEBUG + logkm("task_struct_css_set_offset=0x%llx\n", task_struct_css_set_offset); +#endif /* CONFIG_DEBUG */ + if (task_struct_css_set_offset == UZERO) { + return -11; + } + // 获取 css_set->dfl_cgrp + void (*link_css_set)(struct list_head* tmp_links, struct css_set* cset, struct cgroup* cgrp); + lookup_name(link_css_set); + + uint32_t* link_css_set_src = (uint32_t*)link_css_set; + for (u32 i = 0; i < 0x20; i++) { +#ifdef CONFIG_DEBUG + logkm("link_css_set %x %llx\n", i, link_css_set_src[i]); +#endif /* CONFIG_DEBUG */ + if (link_css_set_src[i] == ARM64_RET) { + break; + } else if ((link_css_set_src[i] & MASK_STR_64) == INST_STR_64) { + uint64_t imm12 = bits32(link_css_set_src[i], 21, 10); + css_set_dfl_cgrp_offset = sign64_extend((imm12 << 0b11u), 16u); + break; + } + } +#ifdef CONFIG_DEBUG + logkm("css_set_dfl_cgrp_offset=0x%llx\n", css_set_dfl_cgrp_offset); +#endif /* CONFIG_DEBUG */ + if (css_set_dfl_cgrp_offset == UZERO) { + return -11; + } return 0; } static long inline_hook_init(const char* args, const char* event, void* __user reserved) { - // 有 do_freezer_trap 函数说明本身就是支持cgroupv2 freezer的 + // 有 do_freezer_trap 函数说明本身就支持cgroupv2 freezer void (*do_freezer_trap)(void); do_freezer_trap = (typeof(do_freezer_trap))kallsyms_lookup_name("do_freezer_trap"); if (do_freezer_trap) return -24; + lookup_name(do_filp_open); lookup_name(proc_pid_wchan); kfunc_lookup_name(schedule); @@ -542,10 +673,14 @@ static long inline_hook_init(const char* args, const char* event, void* __user r kfunc_lookup_name(kstrtoint); kfunc_lookup_name(strim); + kfunc_lookup_name(call_usermodehelper); + lookup_name(selinux_enforcing); + lookup_name(cgroup_addrm_files); lookup_name(cgroup_init_cftypes); lookup_name(cgroup_procs_write); + lookup_name(css_set_move_task); lookup_name(__kernfs_create_file); lookup_name(kernfs_setattr); @@ -557,10 +692,13 @@ static long inline_hook_init(const char* args, const char* event, void* __user r return rc; // 配置文件需要初始化一下 if (cftype_ver5 == IZERO) { - rc = cgroup_init_cftypes(NULL, cgroup_freeze_files); + cgroup_freeze_files->seq_show = cgroup_freeze_show; + cgroup_freeze_files->write = cgroup_freeze_write; } else { - rc = cgroup_init_cftypes(NULL, (struct cftype*)cgroup_freeze_files_v4); + cgroup_freeze_files->seq_show_v4 = cgroup_freeze_show; + cgroup_freeze_files->write_v4 = cgroup_freeze_write; } + rc = cgroup_init_cftypes(NULL, cgroup_freeze_files); if (rc < 0) return rc; @@ -568,11 +706,16 @@ static long inline_hook_init(const char* args, const char* event, void* __user r hook_func(proc_pid_wchan, 4, proc_pid_wchan_before, NULL, NULL); hook_func(cgroup_addrm_files, 4, NULL, cgroup_addrm_files_after, NULL); hook_func(cgroup_procs_write, 4, NULL, cgroup_procs_write_after, NULL); + hook_func(css_set_move_task, 4, NULL, css_set_move_task_after, NULL); // 高版本内核会自动处理所有者, 不再需要手动更改 if (cgroup_base_files_ver5 != IZERO) { hook_func(__kernfs_create_file, 8, NULL, __kernfs_create_file_after, NULL); } + if (!event || strcmp(event, "load-file")) { + hook_func(do_filp_open, 3, NULL, do_filp_open_after, NULL); + } + return 0; } @@ -588,7 +731,9 @@ static long inline_hook_exit(void* __user reserved) { unhook_func(proc_pid_wchan); unhook_func(cgroup_addrm_files); unhook_func(cgroup_procs_write); + unhook_func(css_set_move_task); unhook_func(__kernfs_create_file); + unhook_func(do_filp_open); return 0; } diff --git a/cgroupv2_freeze/cgroupv2_freeze.h b/cgroupv2_freeze/cgroupv2_freeze.h index f0263b5..057f332 100644 --- a/cgroupv2_freeze/cgroupv2_freeze.h +++ b/cgroupv2_freeze/cgroupv2_freeze.h @@ -212,41 +212,29 @@ struct cftype { struct cgroup_subsys* ss; struct list_head node; struct kernfs_ops* kf_ops; - int (*open)(struct kernfs_open_file* of); - void (*release)(struct kernfs_open_file* of); - u64(*read_u64)(struct cgroup_subsys_state* css, struct cftype* cft); + int (*open)(struct kernfs_open_file* of); // unknow v4 + void (*release)(struct kernfs_open_file* of); // unknow v4 + // u64(*read_u64)(struct cgroup_subsys_state* css, struct cftype* cft); + int (*seq_show_v4)(struct seq_file* sf, void* v); s64(*read_s64)(struct cgroup_subsys_state* css, struct cftype* cft); int (*seq_show)(struct seq_file* sf, void* v); void* (*seq_start)(struct seq_file* sf, loff_t* ppos); void* (*seq_next)(struct seq_file* sf, void* v, loff_t* ppos); void (*seq_stop)(struct seq_file* sf, void* v); - int (*write_u64)(struct cgroup_subsys_state* css, struct cftype* cft, u64 val); + // int (*write_u64)(struct cgroup_subsys_state* css, struct cftype* cft, u64 val); + ssize_t(*write_v4)(struct kernfs_open_file* of, char* buf, size_t nbytes, loff_t off); int (*write_s64)(struct cgroup_subsys_state* css, struct cftype* cft, s64 val); ssize_t(*write)(struct kernfs_open_file* of, char* buf, size_t nbytes, loff_t off); unsigned int (*poll)(struct kernfs_open_file* of, struct poll_table_struct* pt); }; -struct cftype_v4 { - char name[MAX_CFTYPE_NAME]; - unsigned long private; - size_t max_write_len; - unsigned int flags; - unsigned int file_offset; - struct cgroup_subsys* ss; - struct list_head node; - struct kernfs_ops* kf_ops; - // int (*open)(struct kernfs_open_file* of); - // void (*release)(struct kernfs_open_file* of); - u64(*read_u64)(struct cgroup_subsys_state* css, struct cftype* cft); - s64(*read_s64)(struct cgroup_subsys_state* css, struct cftype* cft); - int (*seq_show)(struct seq_file* sf, void* v); - void* (*seq_start)(struct seq_file* sf, loff_t* ppos); - void* (*seq_next)(struct seq_file* sf, void* v, loff_t* ppos); - void (*seq_stop)(struct seq_file* sf, void* v); - int (*write_u64)(struct cgroup_subsys_state* css, struct cftype* cft, u64 val); - int (*write_s64)(struct cgroup_subsys_state* css, struct cftype* cft, s64 val); - ssize_t(*write)(struct kernfs_open_file* of, char* buf, size_t nbytes, loff_t off); - unsigned int (*poll)(struct kernfs_open_file* of, struct poll_table_struct* pt); +// fs/internal.h +struct open_flags { + int open_flag; + umode_t mode; + int acc_mode; + int intent; + int lookup_flags; }; #endif /* __CGROUP_FREEZE_H */