Skip to content

Commit 199b522

Browse files
committed
posix-cpu-timers: fix race between handle_posix_cpu_timers() and posix_cpu_timer_del()
jira VULN-136687 cve CVE-2025-38352 commit-author Oleg Nesterov <[email protected]> commit f90fff1 upstream-diff Applying to kernel/posix-cpu-timers.c instead of kernel/time/posix-cpu-timers.c in upstream. There were minor merge conflicts due to differences in surrounding code but the code added is the same. Also, the added comment has been tweaked to remove the reference to handle_posix_cpu_timers(). The logic that is in that upstream function is actually in the end of the run_posix_cpu_timers() function itself in this kernel. If an exiting non-autoreaping task has already passed exit_notify() and calls handle_posix_cpu_timers() from IRQ, it can be reaped by its parent or debugger right after unlock_task_sighand(). If a concurrent posix_cpu_timer_del() runs at that moment, it won't be able to detect timer->it.cpu.firing != 0: cpu_timer_task_rcu() and/or lock_task_sighand() will fail. Add the tsk->exit_state check into run_posix_cpu_timers() to fix this. This fix is not needed if CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y, because exit_task_work() is called before exit_notify(). But the check still makes sense, task_work_add(&tsk->posix_cputimers_work.work) will fail anyway in this case. Cc: [email protected] Reported-by: Benoît Sevens <[email protected]> Fixes: 0bdd2ed ("sched: run_posix_cpu_timers: Don't check ->exit_state, use lock_task_sighand()") Signed-off-by: Oleg Nesterov <[email protected]> Signed-off-by: Linus Torvalds <[email protected]> (cherry picked from commit f90fff1) Signed-off-by: Brett Mastbergen <[email protected]>
1 parent e6b5417 commit 199b522

File tree

1 file changed

+9
-0
lines changed

1 file changed

+9
-0
lines changed

kernel/posix-cpu-timers.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,15 @@ void run_posix_cpu_timers(struct task_struct *tsk)
13251325

13261326
BUG_ON(!irqs_disabled());
13271327

1328+
/*
1329+
* Ensure that release_task(tsk) can't happen while
1330+
* the end of this function is running. Otherwise, a concurrent
1331+
* posix_cpu_timer_del() may fail to lock_task_sighand(tsk) and
1332+
* miss timer->it.cpu.firing != 0.
1333+
*/
1334+
if (tsk->exit_state)
1335+
return;
1336+
13281337
/*
13291338
* The fast path checks that there are no expired thread or thread
13301339
* group timers. If that's so, just return.

0 commit comments

Comments
 (0)