From e3a2695b21d64968b1ef7a928f88e2262ac2fb9b Mon Sep 17 00:00:00 2001 From: CKI Backport Bot Date: Thu, 28 May 2026 15:09:40 +0000 Subject: [PATCH] exit: prevent preemption of oopsing TASK_DEAD task JIRA: https://redhat.atlassian.net/browse/RHEL-180014 CVE: CVE-2026-46173 Backported from tree(s): linux commit c1fa0bb633e4a6b11e83ffc57fa5abe8ebb87891 Author: Jann Horn Date: Mon May 11 08:55:11 2026 -0700 exit: prevent preemption of oopsing TASK_DEAD task When an already-exiting task oopses, make_task_dead() currently calls do_task_dead() with preemption enabled. That is forbidden: do_task_dead() calls __schedule(), which has a comment saying "WARNING: must be called with preemption disabled!". If an oopsing task is preempted in do_task_dead(), between becoming TASK_DEAD and entering the scheduler explicitly, bad things happen: finish_task_switch() assumes that once the scheduler has switched away from a TASK_DEAD task, the task can never run again and its stack is no longer needed; but that assumption apparently doesn't hold if the dead task was preempted (the SM_PREEMPT case). This means that the scheduler ends up repeatedly dropping references on the dead task's stack, which can lead to use-after-free or double-free of the entire task stack; in other words, two tasks can end up running on the same stack, resulting in various kinds of memory corruption. (This does not just affect "recursively oopsing" tasks; it is enough to oops once during task exit, for example in a file_operations::release handler) Fixes: 7f80a2fd7db9 ("exit: Stop poorly open coding do_task_dead in make_task_dead") Cc: stable@kernel.org Signed-off-by: Jann Horn Acked-by: Peter Zijlstra Signed-off-by: Linus Torvalds Signed-off-by: CKI Backport Bot diff --git a/kernel/exit.c b/kernel/exit.c index a310ea845726..4ccfdf5e2964 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -1048,6 +1048,7 @@ void __noreturn make_task_dead(int signr) futex_exit_recursive(tsk); tsk->exit_state = EXIT_DEAD; refcount_inc(&tsk->rcu_users); + preempt_disable(); do_task_dead(); } -- 2.50.1 (Apple Git-155)