From 002b304a08c586070def213729fc563b8a902a7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E9=82=A3=E5=87=A0?= <2078634206@qq.com> Date: Sat, 24 Oct 2026 09:03:21 +0800 Subject: [PATCH] tkernel: killblock: match whitelist rules against the full path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit kill_block_hook_func() renders the source and destination cgroup paths into 256-byte stack buffers and hands them straight to the whitelist matcher. cgroup_path() fills such a buffer with a NUL-terminated prefix, so for a hierarchy deeper than 255 bytes the tail of the path - usually the final component a pattern such as "*/target" is written against - is silently dropped. The whitelist rule then fails to match and the whitelisted kill stays blocked with EPERM. Keep the fast stack path, but when the rendered path fills the buffer completely, pin both css's with references and re-render the path into a kmalloc'd PATH_MAX buffer so the matcher sees every component. Name matching keeps working when the allocation fails. Verified in a guest with a 313-byte cpu hierarchy path and the rule "add * * */target": the unfixed module blocks SIGTERM to a sleeper inside that hierarchy (kill returns EPERM) while the fixed module lets the whitelisted kill through; a two-level path still matches unchanged. Signed-off-by: 陈那几 <2078634206@qq.com> --- kernel/tkernel/killblock/kill_block.c | 73 +++++++++++++++++++++------ 1 file changed, 58 insertions(+), 15 deletions(-) diff --git a/kernel/tkernel/killblock/kill_block.c b/kernel/tkernel/killblock/kill_block.c index c90639372535..87ca1f0e463b 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; } -- Gitee