From 04a0fd3e23bf031bd7099f71b3071fb87d5d298b Mon Sep 17 00:00:00 2001 From: hushijia Date: Fri, 29 May 2026 17:24:06 +0800 Subject: [PATCH] fork: normalize copy_process() error return before ERR_PTR(). copy_process() returns ERR_PTR(retval) from its error path, so retval must be a negative errno. If retval is zero or positive, ERR_PTR(retval) produces a non-error pointer that is not caught by IS_ERR() in kernel_clone(). A BPF_MODIFY_RETURN program attached to security_task_alloc() can return a positive value. copy_process() treats the non-zero return as a failure and then returns ERR_PTR(1). kernel_clone() does not treat that as an error and later dereferences the pointer, causing a kernel crash. Normalize unexpected non-negative values before returning ERR_PTR() from copy_process(). This keeps the fix local to the fork error path and does not change BPF_MODIFY_RETURN verifier behavior. The issue has been reported and discussed upstream, but the verifier-side fix attempt has not been accepted. Carry this targeted fix in deepin-kernel to prevent the reported denial-of-service. Link: https://lore.kernel.org/bpf/973a1b7b-8ee7-407a-890a-11455d9cc5bf@std.uestc.edu.cn/ Link: https://lore.kernel.org/all/20260411163556.8567-1-yangfeng59949@163.com/ Reported-by: Quan Sun <2022090917019@std.uestc.edu.cn> Reported-by: Yinhao Hu Reported-by: Kaiyan Mei Signed-off-by: hushijia --- kernel/fork.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/fork.c b/kernel/fork.c index a420db040f6b4..450a5d7586bb9 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2512,6 +2512,13 @@ __latent_entropy struct task_struct *copy_process( spin_lock_irq(¤t->sighand->siglock); hlist_del_init(&delayed.node); spin_unlock_irq(¤t->sighand->siglock); + /* + * The error path returns ERR_PTR(retval), which requires retval to be a + * negative errno in the range [-MAX_ERRNO, -1]. Normalize unexpected + * values to avoid returning non-error pointers to callers. + */ + if (unlikely(retval >= 0 || retval < -MAX_ERRNO)) + retval = -EINVAL; return ERR_PTR(retval); }