diff --git a/kernel/tkernel/killblock/kill_block.c b/kernel/tkernel/killblock/kill_block.c index c9063937253581ee35815ba19d2e48df37599b2a..87ca1f0e463b5927fe7cf63bb54e5ad886af7144 100644 --- a/kernel/tkernel/killblock/kill_block.c +++ b/kernel/tkernel/killblock/kill_block.c @@ -284,38 +284,81 @@ bool kill_block_whitelist_match(struct task_struct *p, int sig, return match; } +static char *kill_block_full_cgrp_path(struct cgroup *cgrp) +{ + char *buf = kmalloc(PATH_MAX, GFP_KERNEL); + + if (!buf) + return NULL; + cgroup_path(cgrp, buf, PATH_MAX); + return buf; +} + static int kill_block_hook_func(int sig, struct kernel_siginfo *info, struct task_struct *t) { #define KILL_BLOCK_CGRP_PATH_LEN 256 #define KILL_BLOCK_CGRP_NAME_LEN 128 - struct cgroup *src_cgrp, *dst_cgrp; + struct cgroup_subsys_state *src_css, *dst_css; char src_cgrp_path[KILL_BLOCK_CGRP_PATH_LEN]; char dst_cgrp_path[KILL_BLOCK_CGRP_PATH_LEN]; char src_cgrp_name[KILL_BLOCK_CGRP_NAME_LEN]; char dst_cgrp_name[KILL_BLOCK_CGRP_NAME_LEN]; + char *src_path = src_cgrp_path; + char *dst_path = dst_cgrp_path; int ret = 0; bool block = false; + bool got_src = false, got_dst = false; if (sig != SIGKILL && sig != SIGTERM) return 0; rcu_read_lock(); - src_cgrp = task_cgroup(current, cpu_cgrp_subsys.id); - dst_cgrp = task_cgroup(t, cpu_cgrp_subsys.id); - if (src_cgrp && dst_cgrp) { - cgroup_path(src_cgrp, src_cgrp_path, KILL_BLOCK_CGRP_PATH_LEN); - cgroup_path(dst_cgrp, dst_cgrp_path, KILL_BLOCK_CGRP_PATH_LEN); - cgroup_name(src_cgrp, src_cgrp_name, KILL_BLOCK_CGRP_NAME_LEN); - cgroup_name(dst_cgrp, dst_cgrp_name, KILL_BLOCK_CGRP_NAME_LEN); - - block = kill_block_whitelist_match( - t, sig, src_cgrp_path, src_cgrp_name, - dst_cgrp_path, dst_cgrp_name); - if (block) - ret = -EPERM; - } + src_css = task_css(current, cpu_cgrp_subsys.id); + dst_css = task_css(t, cpu_cgrp_subsys.id); + if (src_css && css_tryget_online(src_css)) + got_src = true; + if (dst_css && css_tryget_online(dst_css)) + got_dst = true; rcu_read_unlock(); + if (!got_src || !got_dst) + goto out_put; + + if (cgroup_path(src_css->cgroup, src_cgrp_path, + KILL_BLOCK_CGRP_PATH_LEN) < 0) + src_cgrp_path[0] = '\0'; + else if (strlen(src_cgrp_path) == KILL_BLOCK_CGRP_PATH_LEN - 1) + src_path = kill_block_full_cgrp_path(src_css->cgroup); + if (cgroup_path(dst_css->cgroup, dst_cgrp_path, + KILL_BLOCK_CGRP_PATH_LEN) < 0) + dst_cgrp_path[0] = '\0'; + else if (strlen(dst_cgrp_path) == KILL_BLOCK_CGRP_PATH_LEN - 1) + dst_path = kill_block_full_cgrp_path(dst_css->cgroup); + if (!src_path || !dst_path) { + /* fall back to the stack buffers so name matching still runs */ + src_path = src_cgrp_path; + dst_path = dst_cgrp_path; + } + + cgroup_name(src_css->cgroup, src_cgrp_name, KILL_BLOCK_CGRP_NAME_LEN); + cgroup_name(dst_css->cgroup, dst_cgrp_name, KILL_BLOCK_CGRP_NAME_LEN); + + block = kill_block_whitelist_match( + t, sig, src_path, src_cgrp_name, + dst_path, dst_cgrp_name); + if (block) + ret = -EPERM; + + if (src_path != src_cgrp_path) + kfree(src_path); + if (dst_path != dst_cgrp_path) + kfree(dst_path); +out_put: + if (got_src) + css_put(src_css); + if (got_dst) + css_put(dst_css); + return ret; }