From nobody Sat Sep 26 04:36:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3F74746D57E; Fri, 4 Sep 2026 11:22:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788520946; cv=none; b=PoGI1iIT6xKiEArVkucq8UGpZfzmvqGsVUjyCM/IBlDIhNrsFh6YoBjceWH4BVqVgI8dB9o8sQQnt1cHFI2fRwJlbzPbo7wo4dvPDAKAqMyad7bd0JN40pM1X538aA1l5DNuMkRvTHIL1OXqqneoSKF38DsxlVgPZwj6+5ZZs8w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788520946; c=relaxed/simple; bh=DBD88NPBKa1eHyUI9/ku6JQg426oJ9JALatwrKiBy0c=; h=Date:Message-ID:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=C/OeeX92C1+g0rxk9SAj5xPdaoAafiBInJorszIAZoelL5OR3JrkNAP5R6Sop3ul9BmRi/4PA/66p7RFQI6bP4BmaG/Z/Pzkpu9wCjOL04UuKZxBb5bxOO7GBli9nAxS70K8SUwfrjIGEtzmj/W84bDuG9YBZQTVRHT7X32lU3U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=iarcqinh; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="iarcqinh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0B6A61F00A3E; Fri, 4 Sep 2026 11:22:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788520944; bh=UV16AEp4MZLBqaziSqQftlyE5I6vzktNI6c9B+ZX7Xg=; h=Date:From:To:Cc:Subject:References; b=iarcqinhO8crdZVjcGIekjwQadodBe0TGdu+fy7GEDhB+79w1dSYpaZpL0+3rD989 gpQXB1s8rN9dh4WbKsDEHyAnm3PH47QN9zZe7WXeOp6cVFPvr0LcV4x/MLWECWfOCL NbzJpzHmNvmgviMF300qii7QqCLnPinOqhnkxKn2L2B7IGZ/9DrkKcLyKOM7xqgmIc opAxqJIXjIE2LM4/4XrdFthwQftNAgUE9YWyTCCYpJ+j4LoD+OS9YINPny+glGPFcE s3BvfvPGPgbYCRmdsOgNnRcB8qQTo6rzkHYaq/7nri+bOUCetOghCg6B914rFAfl4i B5DxRAhtPjBow== Date: Fri, 04 Sep 2026 13:22:22 +0200 Message-ID: <20260904112202.074391651@kernel.org> User-Agent: quilt/0.69 From: Thomas Gleixner To: LKML Cc: Hyunwoo Kim , Oleg Nesterov , Frederic Weisbecker , Christian Brauner , Peter Zijlstra , John Stultz , Ingo Molnar , Alexander Viro , "Eric W. Biederman" , stable@vger.kernel.org Subject: [patch 1/8] signal: Prevent exec() race References: <20260904112100.683893401@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Hyunwoo debugged the following KASAN UAF splat: BUG: KASAN: slab-use-after-free in __send_signal_locked+0xb27/0xba0 Write of size 8 at addr ffff888007ed80c8 by task poc/79 ... Call Trace: __send_signal_locked+0xb27/0xba0 do_send_sig_info+0xa7/0x160 do_send_specific+0x76/0xa0 __x64_sys_tgkill+0x193/0x270 ... Allocated by task 80: do_timer_create+0x1a4/0x1030 __x64_sys_timer_create+0x145/0x190 ... Freed by task 12: kmem_cache_free_bulk+0x1f8/0x4a0 kvfree_rcu_bulk+0x14f/0x1c0 kfree_rcu_work+0x128/0x1a0 ... Last potentially related work creation: kvfree_call_rcu+0x39/0x390 __flush_itimer_signals+0x211/0x320 flush_itimer_signals+0x47/0x90 begin_new_exec+0xa6b/0x28c0 It turned out that this happens with a non-leader exec() as Hyunwoo explained: de_thread() calls exchange_tids() before release_task(leader), so the struct pid held by a SIGEV_THREAD_ID timer created against the leader's tid now points to the thread which called execve(). pid_task() returns that thread and lock_task_sighand() on it succeeds. If the timer signal is blocked, its sigqueue stays queued on the leader's task::pending. The next expiry of that timer can then run while release_task() flushes the queue. posixtimer_send_sigqueue() checks whether the sigqueue is already queued with a plain list_empty(), which only reads list_head::next. list_del_init() is not atomic and INIT_LIST_HEAD() stores list_head::next before list_head::prev, so the check can pass in between. list_add_tail() queues the entry on the task::pending of the live thread, and the list_head::prev store from the flush then overwrites the list_head::prev link that list_add_tail() has just set. __flush_itimer_signals() does not undo that either. With list_head::prev pointing at the entry itself, its list_del_init() only stores the same values again, so the entry is not removed from the list. It is still there after the last reference is dropped and the timer is freed by RCU, and the list_add_tail() of a later tgkill() follows that list_head::prev into the freed timer. This problem surfaced with the recent commit which moved the sigqueue flush out of the sighand lock held region. Hyonwoo proposed to fix this by using list_del_init_careful(), but that just papers over the problem. After some disucssions and various attempts to solve it, Eric pointed out that there is no reason to flush task::pending late in release_task() and it should be done in exit_signals() already. As nothing can collect and deliver signals which are queued in a dying task's pending queue, there is no reason to delay it further. But it has to be ensured that no signals can be queued into it after that point. exit_signals() sets PF_EXITING in task::flags, which can be used as an indicator for this. Cure it by: - Preventing signal queueing for task private signals (PIDTYPE_PID) when the task has PF_EXITING set in __send_signal_locked() and in posixtimer_send_sigqueue(). - Protecting the unlocked setting of PF_EXITING in exit_signals() for the task group empty and the group exit case with sighand lock - Flushing task::pending signals right there. Optimize that by moving the whole pending list to an on-stack list head under sighand lock and free the signals without the lock held. Fixes: fb3bbcfe344e ("exit: change the release_task() paths to call flush_s= igqueue() lockless") Reported-by: Hyunwoo Kim Debugged-by: Hyunwoo Kim Suggested-by: "Eric W. Biederman" Signed-off-by: Thomas Gleixner Cc: stable@vger.kernel.org Closes: https://patch.msgid.link/aok1rdkBgZsynHZB@v4bel --- V3: Restructure code and fix the missing unlock - Oleg V2: Don't flush w/o sighand lock held - Oleg Move the while pending list under the lock and free it lockless --- kernel/exit.c | 11 ++++---- kernel/signal.c | 70 ++++++++++++++++++++++++++++++++-------------------= ----- 2 files changed, 47 insertions(+), 34 deletions(-) --- a/kernel/exit.c +++ b/kernel/exit.c @@ -299,12 +299,13 @@ void release_task(struct task_struct *p) free_pids(post.pids); release_thread(p); /* - * This task was already removed from the process/thread/pid lists - * and lock_task_sighand(p) can't succeed. Nobody else can touch - * ->pending or, if group dead, signal->shared_pending. We can call - * flush_sigqueue() lockless. + * This task was already removed from the process/thread/pid lists and + * lock_task_sighand(p) can't succeed. If it's the group leader then + * flush tsk->signal->shared_pending. tsk->pending has been flushed + * already in exit_signals(). Nothing else can touch + * signal->shared_pending anymore, so flush_sigqueue() can be invoked + * lockless. */ - flush_sigqueue(&p->pending); if (thread_group_leader(p)) flush_sigqueue(&p->signal->shared_pending); =20 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -457,18 +457,28 @@ static void __sigqueue_free(struct sigqu kmem_cache_free(sigqueue_cachep, q); } =20 -void flush_sigqueue(struct sigpending *queue) +static void flush_sigqueue_list(struct list_head *head) { - struct sigqueue *q; + struct sigqueue *q, *tmp; =20 - sigemptyset(&queue->signal); - while (!list_empty(&queue->list)) { - q =3D list_entry(queue->list.next, struct sigqueue , list); + list_for_each_entry_safe(q, tmp, head, list) { list_del_init(&q->list); __sigqueue_free(q); } } =20 +void flush_sigqueue(struct sigpending *queue) +{ + sigemptyset(&queue->signal); + flush_sigqueue_list(&queue->list); +} + +static void sigqueue_dequeue_pending(struct sigpending *queue, struct list= _head *head) +{ + sigemptyset(&queue->signal); + list_splice_init(&queue->list, head); +} + /* * Flush all pending signals for this kthread. */ @@ -1030,6 +1040,10 @@ static int __send_signal_locked(int sig, lockdep_assert_held(&t->sighand->siglock); =20 result =3D TRACE_SIGNAL_IGNORED; + + if (unlikely(type =3D=3D PIDTYPE_PID && (t->flags & PF_EXITING))) + goto ret; + if (!prepare_signal(sig, t, force)) goto ret; =20 @@ -1990,6 +2004,9 @@ void posixtimer_send_sigqueue(struct k_i if (!likely(lock_task_sighand(t, &flags))) return; =20 + if (unlikely(tmr->it_pid_type =3D=3D PIDTYPE_PID && (t->flags & PF_EXITIN= G))) + goto unlock; + /* * Update @tmr::sigqueue_seq for posix timer signals with sighand * locked to prevent a race against dequeue_signal(). @@ -2081,6 +2098,7 @@ void posixtimer_send_sigqueue(struct k_i result =3D TRACE_SIGNAL_DELIVERED; out: trace_signal_generate(sig, &q->info, t, tmr->it_pid_type !=3D PIDTYPE_PID= , result); +unlock: unlock_task_sighand(t, &flags); } =20 @@ -3120,42 +3138,36 @@ static void retarget_shared_pending(stru =20 void exit_signals(struct task_struct *tsk) { + LIST_HEAD(sigq_list); int group_stop =3D 0; - sigset_t unblocked; =20 /* * @tsk is about to have PF_EXITING set - lock out users which - * expect stable threadgroup. + * expect a stable threadgroup. */ cgroup_threadgroup_change_begin(tsk); =20 - if (thread_group_empty(tsk) || (tsk->signal->flags & SIGNAL_GROUP_EXIT)) { + scoped_guard(spinlock_irq, &tsk->sighand->siglock) { tsk->flags |=3D PF_EXITING; - cgroup_threadgroup_change_end(tsk); - return; - } =20 - spin_lock_irq(&tsk->sighand->siglock); - /* - * From now this task is not visible for group-wide signals, - * see wants_signal(), do_signal_stop(). - */ - tsk->flags |=3D PF_EXITING; + sigqueue_dequeue_pending(&tsk->pending, &sigq_list); =20 - cgroup_threadgroup_change_end(tsk); + if (task_sigpending(tsk) && !thread_group_empty(tsk) && + !(tsk->signal->flags & SIGNAL_GROUP_EXIT)) { + sigset_t unblocked =3D tsk->blocked; + + signotset(&unblocked); + retarget_shared_pending(tsk, &unblocked); + + if (unlikely(tsk->jobctl & JOBCTL_STOP_PENDING) && + task_participate_group_stop(tsk)) + group_stop =3D CLD_STOPPED; + } + } =20 - if (!task_sigpending(tsk)) - goto out; + cgroup_threadgroup_change_end(tsk); =20 - unblocked =3D tsk->blocked; - signotset(&unblocked); - retarget_shared_pending(tsk, &unblocked); - - if (unlikely(tsk->jobctl & JOBCTL_STOP_PENDING) && - task_participate_group_stop(tsk)) - group_stop =3D CLD_STOPPED; -out: - spin_unlock_irq(&tsk->sighand->siglock); + flush_sigqueue_list(&sigq_list); =20 /* * If group stop has completed, deliver the notification. This From nobody Sat Sep 26 04:36:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DBCA44734CF; Fri, 4 Sep 2026 11:22:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788520951; cv=none; b=fjm63Yq5Bdb8xWoBL7ma+7ywhNHIKRCzBhirOzDMITeDmc4w8gu7btiKo8uiUsCFg3sJ1b/fZocD0NxegtDcY2xPAxWpSalGXL9qgIL0E3V72xSEk2efx3eNGn6+tI4byPxb+U6iEOroV4L6BsO4vTkBvdfFMr1MhTzVRAeFPeU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788520951; c=relaxed/simple; bh=c6LKdjCRtX9r7BkpBqhHl3YDIF7wMKwHPOCCdDBstSs=; h=Date:Message-ID:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=hpPD3zvrFULw6lFUpUdTZ17cdnwXw8bSYdJp30AZ6n7iGwUZEtxDpQU2LFK4w9u3jwBEO3lobgQx1XPtnhpzKiHUFvGqm42c0DbM75qmYZlez7ediQRwKHHcOBOlQH0ibrgSbbosxRKM8oN5Vnmh6j57KBDoR4pvhXHQ+1Bf32Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hBnkU74I; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hBnkU74I" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B98361F00A3E; Fri, 4 Sep 2026 11:22:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788520949; bh=/MjvIu2eMcDyB476Ez37rVlvnO35eZxH5+YssIQfLa8=; h=Date:From:To:Cc:Subject:References; b=hBnkU74I3TP8Z6ELqV8PmhBwn3sZ+74wmbRjNTGlhsCzAV9686nKBr2wqOa8wAbSr 5As/v5CNR1vokggX3aPjFYZRwNAL++foP23zxITyNuTDqmttVFGiT+F3pEt5f/feVz izDRxechzOORanTN0YK6euKRx52zGjYIGnjyHcKo5Ri/QY1T3sUgWH07BV9VSdmDve ucxXZSaVtQH/Lp6+datI+UCZVWdlP6Ye794dEhQWKOnRAlHWTRuTbnA3geeurDXt2u cdtsVVg/bvdFK8dChV/Tw4zwgJao85UFhiBqwIjr/3C7Rhe7FirBGBFV0ZHoGpG0io Qk6pAGlfC3dWw== Date: Fri, 04 Sep 2026 13:22:26 +0200 Message-ID: <20260904112202.131242426@kernel.org> User-Agent: quilt/0.69 From: Thomas Gleixner To: LKML Cc: Hyunwoo Kim , Oleg Nesterov , Frederic Weisbecker , Christian Brauner , Peter Zijlstra , John Stultz , Ingo Molnar , Alexander Viro , "Eric W. Biederman" , stable@vger.kernel.org Subject: [patch 2/8] exec: Cleanup POSIX timers right after de_thread() References: <20260904112100.683893401@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Hyunwoo Kim A per-thread CPU timer holds a reference to the PID of the thread it is attached to and, while it is armed, its node is queued in that thread's posix_cputimers. The task is looked up by that PID. When a non-leader thread exec()s, de_thread() changes which task owns that PID. pid_task(timer->it.cpu.pid, PIDTYPE_PID) then returns NULL, but the node is still queued on tsk, which is alive. timer_lock_sighand() takes a failed lookup to mean that the node is already dequeued, so it has nothing to undo. begin_new_exec() calls posix_cpu_timers_exit(me) right after exec_task_namespaces() and that removes the leftover node, so the state normally stays invisible. But bprm->point_of_no_return is set before de_thread(), so if unshare_files(), set_mm_exe_file(), exec_mmap() or exec_task_namespaces() fails, the task dies before it gets there. exit_itimers() then frees the k_itimer while its node is still queued, and reaping tsk later erases that freed node from the rbtree. In short: the non-leader thread B the parent timer_create(CLOCK_THREAD_CPUTIME_ID) timer_settime() arm_timer() // the node is queued on B execve() de_thread(B) exchange_tids(B, leader) // B's PID now belongs to the leader release_task(leader) __exit_signal(leader) posix_cpu_timers_exit(leader) // cleans leader's queue, not B's __unhash_process(leader) // that PID has no task anymore exec_mmap() mmap_read_lock_killable(old_mm) kill(B, SIGKILL) // -EINTR get_signal() do_exit() exit_itimers() posix_timer_delete() posix_cpu_timer_del() posix_timer_unhash_and_free() // freed while still queued wait4() release_task(B) posix_cpu_timers_exit(B) cleanup_timerqueue() timerqueue_del() // use-after-free Move the POSIX timer cleanup right after de_thread() before any of the later failure conditions brings the task into do_exit(). [ tglx: Move the cleanup right after de_thread() ] Fixes: 55e8c8eb2c7b ("posix-cpu-timers: Store a reference to a pid not a ta= sk") Signed-off-by: Hyunwoo Kim Signed-off-by: Thomas Gleixner Cc: stable@vger.kernel.org Link: https://patch.msgid.link/ao7Q8miiuLAPVnWv@v4bel --- Changes in v3: Move the cleanup right after de_thread() - Oleg Rework change log Changes in v2: - Add the trigger sequence and the KASAN log to the commit message. - v1: https://lore.kernel.org/all/anfgrsPlUdwBhdrp@v4bel/ --- fs/exec.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) --- a/fs/exec.c +++ b/fs/exec.c @@ -1115,6 +1115,17 @@ static struct file *bprm_identity_file(c return bprm->file; } =20 +static void posixtimer_exec(struct task_struct *me) +{ +#ifdef CONFIG_POSIX_TIMERS + spin_lock_irq(&me->sighand->siglock); + posix_cpu_timers_exit(me); + spin_unlock_irq(&me->sighand->siglock); + exit_itimers(me); + flush_itimer_signals(); +#endif +} + /* * Calling this is the point of no return. None of the failures will be * seen by userspace since either the process is already taking a fatal @@ -1152,6 +1163,16 @@ int begin_new_exec(struct linux_binprm * retval =3D de_thread(me); if (retval) goto out; + + /* + * This must be done here to ensure that POSIX CPU timers which were + * armed on the current task are dequeued from me::posix_cputimers. + * That ensures that in case of a TID switch the deletion of the related + * POSIX timer will not free an enqueued timer because the TID lookup + * failed as the original target TID was the old leader. + */ + posixtimer_exec(me); + /* see the comment in check_unsafe_exec() */ current->fs->in_exec =3D 0; /* @@ -1192,14 +1213,6 @@ int begin_new_exec(struct linux_binprm * if (retval) goto out_unlock; =20 -#ifdef CONFIG_POSIX_TIMERS - spin_lock_irq(&me->sighand->siglock); - posix_cpu_timers_exit(me); - spin_unlock_irq(&me->sighand->siglock); - exit_itimers(me); - flush_itimer_signals(); -#endif - /* * Make the signal table private. */ From nobody Sat Sep 26 04:36:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5038A47668A for ; Fri, 4 Sep 2026 11:22:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788520955; cv=none; b=IgMajBugiwyPIntV1Zr+7OlWS+3i9VqfGgWina0zzTS6LuM9tO4a/ACEhh4Mkm7q0MjaHw0xHKzSRQtJE2Sq73o3fdcmAQikwvHr13+jurh+UOEiqcOOejvvLL63a9DMVXW10d29YJOMSXslOe5iv3AWNW7riHrTbe7yy6Mp24g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788520955; c=relaxed/simple; bh=RqDfYCiwlgyuPLoyc4f8FZMqURar5mmcP86OJFNPr/Q=; h=Date:Message-ID:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=dnTtNM3JuXMSBpKDbHr56cmjjdrXB8WlO/lcWryNQCpAN6OneZSAUtgfbdb7JE6Fr5cvnuAGfCmlf1pqGgPtam1jsymWY4ZtrSla8KCnCYNphHLiorCwWI5vr0jghN664GceSBkph2tokQhIVx5ILL40Ymj9fpa5T1dtrAkkzKs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ZV99/zwB; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ZV99/zwB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5A7D71F00ACA; Fri, 4 Sep 2026 11:22:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788520954; bh=eNxFTH4JlmV+mK5Fga9mVimS/lpVLPz1WN5SlwLP+BM=; h=Date:From:To:Cc:Subject:References; b=ZV99/zwBqkTQD6F4tyzL0U1D/ji74Gsl8agcUH4AlRn0mokiJc/VJy379I66rSiwd l2QPeakGfPs9umtbK+4c/jAF0bvkWQS2kwgtCGYI1haHUI9Yq1c9pmBTTHl6dqbLD4 /7/wlqWjhvwE0pdY718XX4n5wRmcjrAkLv+A/4fPaVjoWBNBcVAFEUkjOHKEODVWZ9 4MWukSFt8jazuJfSoBDUxp1ukZHQ/ADC84n/q/fjz+7noCdTNBJoEpzN94m8uzNrAV O3tI8KkXkZ9A+f+0TJHmDnWqHgfZUCoMBh+m1dLbAUTO6SjlXbMqjDGdaFxpKjaH01 ML2dBbf/EG/dg== Date: Fri, 04 Sep 2026 13:22:31 +0200 Message-ID: <20260904112202.182757867@kernel.org> User-Agent: quilt/0.69 From: Thomas Gleixner To: LKML Cc: Hyunwoo Kim , Oleg Nesterov , Frederic Weisbecker , Christian Brauner , Peter Zijlstra , John Stultz , Ingo Molnar , Alexander Viro , "Eric W. Biederman" Subject: [patch 3/8] posix-timers: Move posixtimer_exec_cleanup() out of exec.c References: <20260904112100.683893401@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Move it to the POSIX timer code and provide a proper stub when POSIX timers are disabled in Kconfig. No functional change. Signed-off-by: Thomas Gleixner --- fs/exec.c | 13 +------------ include/linux/posix-timers.h | 3 +++ kernel/time/posix-timers.c | 9 +++++++++ 3 files changed, 13 insertions(+), 12 deletions(-) --- a/fs/exec.c +++ b/fs/exec.c @@ -1115,17 +1115,6 @@ static struct file *bprm_identity_file(c return bprm->file; } =20 -static void posixtimer_exec(struct task_struct *me) -{ -#ifdef CONFIG_POSIX_TIMERS - spin_lock_irq(&me->sighand->siglock); - posix_cpu_timers_exit(me); - spin_unlock_irq(&me->sighand->siglock); - exit_itimers(me); - flush_itimer_signals(); -#endif -} - /* * Calling this is the point of no return. None of the failures will be * seen by userspace since either the process is already taking a fatal @@ -1171,7 +1160,7 @@ int begin_new_exec(struct linux_binprm * * POSIX timer will not free an enqueued timer because the TID lookup * failed as the original target TID was the old leader. */ - posixtimer_exec(me); + posixtimer_exec(); =20 /* see the comment in check_unsafe_exec() */ current->fs->in_exec =3D 0; --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -232,6 +232,8 @@ void set_process_cpu_timer(struct task_s int update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new); =20 #ifdef CONFIG_POSIX_TIMERS +void posixtimer_exec(void); + static inline void posixtimer_putref(struct k_itimer *tmr) { if (rcuref_put(&tmr->rcuref)) @@ -259,6 +261,7 @@ static inline bool posixtimer_valid(cons return !(val & 0x1UL); } #else /* CONFIG_POSIX_TIMERS */ +static inline void posixtimer_exec(void) { } static inline void posixtimer_sigqueue_getref(struct sigqueue *q) { } static inline void posixtimer_sigqueue_putref(struct sigqueue *q) { } #endif /* !CONFIG_POSIX_TIMERS */ --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -1120,6 +1120,15 @@ void exit_itimers(struct task_struct *ts } } =20 +void posixtimer_exec(void) +{ + scoped_guard(spinlock_irq, ¤t->sighand->siglock) + posix_cpu_timers_exit(current); + + exit_itimers(current); + flush_itimer_signals(); +} + SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, const struct __kernel_timespec __user *, tp) { From nobody Sat Sep 26 04:36:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E04E5473C84 for ; Fri, 4 Sep 2026 11:22:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788520960; cv=none; b=i9qD2N0eBc0dbv24Epwnx7a+dH5PLFWtiy4E+vW4kHpeBtgG0+uBYnSyIA1KdMpGQxm7P9BFsSRBsunAWtvZ5g33dsPi6G58SwDIxEN6E5u+HfdwTg3+YQ8Cyp9cm6T2cr9ngWgqhm4N3V/fkhEo3d88CD1KW32hpMa+kGn0VRk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788520960; c=relaxed/simple; bh=5eedEYn8Z68QDtxB6uO/1ARiw+HAA6+XsotMn7WIIp0=; h=Date:Message-ID:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=gin/B7UQr72jLBicfsotkibwzPys3lbz31HcxTbglX3kulRprObz11Xye15i0XddROWz2prZjUE/Oz49SDO5lK+5X+ahlqh08IujYLVvtX+9LH/rAu3qbfvjmDsLWVtQQjEFHgkcQ26pa/zJWv2miKq3/SEJCF7i9WVSIwcBcBg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jooppa48; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="jooppa48" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B9F591F00A3E; Fri, 4 Sep 2026 11:22:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788520958; bh=2kUc2gyunyVdJuieYMrU6cHtPZKVp3xH/1+8tPD2gtI=; h=Date:From:To:Cc:Subject:References; b=jooppa48LF+Z4+XU/TWWNflDFj8hezsiH2fZX76PwDEbZ7jmsjNWBZqtRvXvKHuZR zCiqWTJsyzdPko8rLVpVcGSIr6gYBLyhRzlngNoxueDc1HkmDE3vjXO1YxrI91RG7k J8WX4n9d7QG4RmeAxVknIZiFa/7Tj+mzgUHFTnkBdUxOXFwKvSokXpyVp12Hl72BD8 gR+0hX7nc5SIaWkqkM/GmlCmYaHn1m8KGSFp2NYNzh7IDxGrsyEX77JXU27P1/dDas kphsYECRii9XLOL4ltOm2kv0LRQNj3AOUplchfDthUqkFNAKxhAnUFBBsv6rQA/xDq s+ZorPJ9VzRUQ== Date: Fri, 04 Sep 2026 13:22:35 +0200 Message-ID: <20260904112202.239196705@kernel.org> User-Agent: quilt/0.69 From: Thomas Gleixner To: LKML Cc: Hyunwoo Kim , Oleg Nesterov , Frederic Weisbecker , Christian Brauner , Peter Zijlstra , John Stultz , Ingo Molnar , Alexander Viro , "Eric W. Biederman" Subject: [patch 4/8] posix-timers: Move POSIX timer group exit related code out of do_exit() References: <20260904112100.683893401@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Move the POSIX timer group exit handling into the posix timer code and provide a proper stub when POSIX timers are disabled in Kconfig. No functional change. Signed-off-by: Thomas Gleixner --- include/linux/posix-timers.h | 2 ++ include/linux/sched/task.h | 1 - kernel/exit.c | 7 +++---- kernel/time/posix-timers.c | 16 +++++++++------- 4 files changed, 14 insertions(+), 12 deletions(-) --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -233,6 +233,7 @@ int update_rlimit_cpu(struct task_struct =20 #ifdef CONFIG_POSIX_TIMERS void posixtimer_exec(void); +void posixtimer_exit(void); =20 static inline void posixtimer_putref(struct k_itimer *tmr) { @@ -262,6 +263,7 @@ static inline bool posixtimer_valid(cons } #else /* CONFIG_POSIX_TIMERS */ static inline void posixtimer_exec(void) { } +static inline void posixtimer_exit(void) { } static inline void posixtimer_sigqueue_getref(struct sigqueue *q) { } static inline void posixtimer_sigqueue_putref(struct sigqueue *q) { } #endif /* !CONFIG_POSIX_TIMERS */ --- a/include/linux/sched/task.h +++ b/include/linux/sched/task.h @@ -94,7 +94,6 @@ static inline void exit_thread(struct ta extern __noreturn void do_group_exit(int); =20 extern void exit_files(struct task_struct *); -extern void exit_itimers(struct task_struct *); =20 extern pid_t kernel_clone(struct kernel_clone_args *kargs); struct task_struct *copy_process(struct pid *pid, int trace, int node, --- a/kernel/exit.c +++ b/kernel/exit.c @@ -963,13 +963,12 @@ void __noreturn do_exit(long code) panic("Attempted to kill init! exitcode=3D0x%08x\n", tsk->signal->group_exit_code ?: (int)code); =20 -#ifdef CONFIG_POSIX_TIMERS - hrtimer_cancel(&tsk->signal->real_timer); - exit_itimers(tsk); -#endif + posixtimer_exit(); + if (tsk->mm) setmax_mm_hiwater_rss(&tsk->signal->maxrss, tsk->mm); } + acct_collect(code, group_dead); if (group_dead) tty_audit_exit(); --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -1077,13 +1077,9 @@ SYSCALL_DEFINE1(timer_delete, timer_t, t return 0; } =20 -/* - * Invoked from do_exit() when the last thread of a thread group exits. - * At that point no other task can access the timers of the dying - * task anymore. - */ -void exit_itimers(struct task_struct *tsk) +static void posixtimer_delete_timers(void) { + struct task_struct *tsk =3D current; struct hlist_head timers; struct hlist_node *next; struct k_itimer *timer; @@ -1120,12 +1116,18 @@ void exit_itimers(struct task_struct *ts } } =20 +void posixtimer_exit(void) +{ + hrtimer_cancel(¤t->signal->real_timer); + posixtimer_delete_timers(); +} + void posixtimer_exec(void) { scoped_guard(spinlock_irq, ¤t->sighand->siglock) posix_cpu_timers_exit(current); =20 - exit_itimers(current); + posixtimer_delete_timers(); flush_itimer_signals(); } From nobody Sat Sep 26 04:36:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8714246D579 for ; Fri, 4 Sep 2026 11:22:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788520964; cv=none; b=Vz+FATqediz+98kwp3NEuBenYtkWedX4E6YMrj2xTDhi7AbaTWbtuYtfCa54RWmZCNpG14R0S8/XjuUKZfwRbJhEypjHpiamtRndLaMj5G0vHQ/GCLykreUCL5rsKmCvTXlQzQPBTzlLccbq6GNs9XJW1Km2px1ZX+TNAdT94mo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788520964; c=relaxed/simple; bh=W725Erh20uSzqoVnH8TC3MWTcLXMTI6gq1pvobwiT2Q=; h=Date:Message-ID:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=UwhTyOvlELrdiZv5cJG+BvcXkocGlSR2qJkW2HRqICgBi0o3/J7J2TJE/tjhdPYxjRFQ8v8cueeZ9CHHLzDnNK0t1fVwshHj0xFGQ4sxmd2xIuf+qmhihV1dsL6zLSOgO1MJ2ahU364dLFDqT8zAc4CvntGoZq2GaSRJvpgkMlk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=acHx8TAw; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="acHx8TAw" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5E2A91F00A3D; Fri, 4 Sep 2026 11:22:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788520963; bh=YJCZME/594Xy8B8jVu6Smq4mlzmi2kmZv8iQg1LGClI=; h=Date:From:To:Cc:Subject:References; b=acHx8TAwq3Uec8APqro0iawU8qHMQ40z7WyUSpgksTnbPGjWw7xQT/7FpEsFEO64D cLhcja5D03qwg8XAEcFAVn+lf9DsKwq6gW0sGboefoFsacuQ6Vfns8N1TqMsefFkSy YilRvSrC5Eer+vuFN6SHXvE9bcrQJybG4A/wVz0DW+TsfeudKVMVu0CT82+KuBJsCy yqu+2zcS8VWBxuCyo85Y0K6+89eCDIuQO7Cy5E5vF6EmHzRmuir0XP2RGyl51qmAWS NR7pnZ40lGinE2r4gQmh0bvuch9PshfnEcxFf9euof0bElaTaCKFhItk1teqCDyFAv CotoJuekn8m3g== Date: Fri, 04 Sep 2026 13:22:40 +0200 Message-ID: <20260904112202.297869969@kernel.org> User-Agent: quilt/0.69 From: Thomas Gleixner To: LKML Cc: Hyunwoo Kim , Oleg Nesterov , Frederic Weisbecker , Christian Brauner , Peter Zijlstra , John Stultz , Ingo Molnar , Alexander Viro , "Eric W. Biederman" Subject: [patch 5/8] posix-cpu-timers: Move inlines out of public header References: <20260904112100.683893401@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" They are only used in the POSIX CPU timer code. No point in exposing them globally and parsing them for nothing. Signed-off-by: Thomas Gleixner --- include/linux/posix-timers.h | 32 -------------------------------- kernel/time/posix-cpu-timers.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 32 deletions(-) --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -66,38 +66,6 @@ struct cpu_timer { struct task_struct __rcu *handling; }; =20 -static inline bool cpu_timer_enqueue(struct timerqueue_head *head, - struct cpu_timer *ctmr) -{ - ctmr->head =3D head; - return timerqueue_add(head, &ctmr->node); -} - -static inline bool cpu_timer_queued(struct cpu_timer *ctmr) -{ - return !!ctmr->head; -} - -static inline bool cpu_timer_dequeue(struct cpu_timer *ctmr) -{ - if (cpu_timer_queued(ctmr)) { - timerqueue_del(ctmr->head, &ctmr->node); - ctmr->head =3D NULL; - return true; - } - return false; -} - -static inline u64 cpu_timer_getexpires(struct cpu_timer *ctmr) -{ - return ctmr->node.expires; -} - -static inline void cpu_timer_setexpires(struct cpu_timer *ctmr, u64 exp) -{ - ctmr->node.expires =3D exp; -} - static inline void posix_cputimers_init(struct posix_cputimers *pct) { memset(pct, 0, sizeof(*pct)); --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c @@ -438,6 +438,38 @@ static void trigger_base_recalc_expires( base->nextevt =3D 0; } =20 +static inline bool cpu_timer_enqueue(struct timerqueue_head *head, + struct cpu_timer *ctmr) +{ + ctmr->head =3D head; + return timerqueue_add(head, &ctmr->node); +} + +static inline bool cpu_timer_queued(struct cpu_timer *ctmr) +{ + return !!ctmr->head; +} + +static inline bool cpu_timer_dequeue(struct cpu_timer *ctmr) +{ + if (cpu_timer_queued(ctmr)) { + timerqueue_del(ctmr->head, &ctmr->node); + ctmr->head =3D NULL; + return true; + } + return false; +} + +static inline u64 cpu_timer_getexpires(struct cpu_timer *ctmr) +{ + return ctmr->node.expires; +} + +static inline void cpu_timer_setexpires(struct cpu_timer *ctmr, u64 exp) +{ + ctmr->node.expires =3D exp; +} + /* * Dequeue the timer and reset the base if it was its earliest expiration. * It makes sure the next tick recalculates the base next expiration so we From nobody Sat Sep 26 04:36:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B7CD846D579 for ; Fri, 4 Sep 2026 11:22:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788520968; cv=none; b=jvzDbfisG6i/bJDwI7uoERWURd66c1h3P1ewND5flIMgvxdLceYoLyD+maLUKTlZp0we7Xi09fvlFgIn3Rn1fsZuUoJGrRodjQShGR04hTxC9etzGluoo++cnfp+oye+bHyATaD8N/Rm+D3w7Qo/U4hTAyZebxT5k9euSChBtPY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788520968; c=relaxed/simple; bh=uBWdguZhKLwWAGj+MT+ns1Y+NwJ1sgUA3lnnzSWT8ik=; h=Date:Message-ID:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=bkCaNqxTi/Ih6vfkt6h1c0xx71b6aDo/WUddmLOqP+0EN7Xm8UNLjIiEgX4viQHIiXHf8Sz3G/4pJ6CCAuQT0CPvunRuJUJ9yeRT3oDyOHNDPjDDV2uUQ1MPa+VqTmS2kCDQ/clEgHkZOAR3hNVGp0oIHyYwerDganNFucLTKTI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FmLykmem; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FmLykmem" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BD6A21F00A3D; Fri, 4 Sep 2026 11:22:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788520967; bh=XCJDub5utZU3Jv9WsWOzQRSnYRJS9t/LC5211PDv630=; h=Date:From:To:Cc:Subject:References; b=FmLykmembCGqCpQwM/uWGAOpk1Foj8dojuRirZbQ9CfDRqgO0d01RVQFwTuEwImSW jNoctT0bbMDHAkoMTShufhXoLTcaSpxeD/LoDeUhvnklz8Wj13hd2vRA9SGBVwf6zx /h5YZh4V/HxI2h8vEzroo7T+6Siv0y4xG5NSTDv+lAD9n5txRjlgbmP8lKy12lQ9Wy 873utP5okMPbR4xyaP2FawiozhseEp3GMPHPkilkhu9KLt9BXSCaCOCgwfGxldNifQ MGfju06M6izjzzVyaFEFMdAnwGbCi2RC5z0mamS+XN6zsKHjqaiTKAcWRvbggLjV6D 2csJLRTwVwZeg== Date: Fri, 04 Sep 2026 13:22:44 +0200 Message-ID: <20260904112202.348410055@kernel.org> User-Agent: quilt/0.69 From: Thomas Gleixner To: LKML Cc: Hyunwoo Kim , Oleg Nesterov , Frederic Weisbecker , Christian Brauner , Peter Zijlstra , John Stultz , Ingo Molnar , Alexander Viro , "Eric W. Biederman" Subject: [patch 6/8] posix-cpu-timers: Use PF_EXITING to indicate exit References: <20260904112100.683893401@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Right now POSIX CPU timers use task::exit_state to check whether a task is exiting. That works correctly, but exit_state is set later in do_exit() and too late for allowing to cleanup POSIX timers earlier. It does not matter in case of exit whether the cutoff is a bit earlier. Signed-off-by: Thomas Gleixner --- kernel/time/posix-cpu-timers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c @@ -1505,7 +1505,7 @@ void run_posix_cpu_timers(void) * posix_cpu_timer_del() may fail to lock_task_sighand(tsk) and * miss timer->it.cpu.firing !=3D 0. */ - if (tsk->exit_state) + if (tsk->flags & PF_EXITING) return; =20 /* From nobody Sat Sep 26 04:36:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2E223472F72 for ; Fri, 4 Sep 2026 11:22:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788520973; cv=none; b=dqbrAcw3Tfe1NlKaIdaKMgUBBBvrTIKtItvHDpidFEZWERgz3VI2ohTUJUw7a7/d35LySoQK+GqBKVaGOU6YshOBdxac4/BT9uTeu83bC1XefJeIO8cNvOHJn0x8gEXByM8uWoIPXzd+UZFGVNlan2X6EppvNyAbd7yVZ2uoifM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788520973; c=relaxed/simple; bh=knIRTAe2apaT7WsKjn236Vs8mYaHILNE7HiMwSnPr40=; h=Date:Message-ID:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=GC/KZYAIgX1zacu/zA7Oft9LDisKFU9RYtq755Shme9TiJyao8mt86mayjCgninfsZbzpDmxFzK6X3xr2KYgxEBDZwx9zft+qdKCNCJ3trziDWFxVFfy+iUOm3H2641tZh2rGwD+I6xif7nOWvWXBhwtA4bNvAnijPkSZuQVtlU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RDkHCvqP; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RDkHCvqP" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 10E961F00A3D; Fri, 4 Sep 2026 11:22:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788520971; bh=xFD3aGiuhZc+pCkwkvbcraGTuUDOKB9doW8Ry6Um8pQ=; h=Date:From:To:Cc:Subject:References; b=RDkHCvqPxxhlrzTpIfmThu5P+JbhL6UehHoFN3qgmDSBB75FH1lxlpj1wtM95BExK nHkJlw2vjI5tBMVc1JOsGGlo62VuXCNo6nZJ1MTbUYmPPr+GoN2XSybVoljeP1Kq4R fnhZZrEyl1sl32hOvOiKn3bPh1DBLLBznQKDW8mB2FkDKkmojt8oMCdM0INo0yVmwU SoSUYpVljCFirHwytNf4cdbGzcWcZioFmqG14Of+PM20pSx7wCycwfj+u2/SxhfAN2 KvQf8L9Sz303BZkNOToksFxmOQV5adxq6jfVQJvlP5rZVboD3d2DOasoI5u3p+NqDD v2bYzWyjoDl0w== Date: Fri, 04 Sep 2026 13:22:49 +0200 Message-ID: <20260904112202.400768514@kernel.org> User-Agent: quilt/0.69 From: Thomas Gleixner To: LKML Cc: Hyunwoo Kim , Oleg Nesterov , Frederic Weisbecker , Christian Brauner , Peter Zijlstra , John Stultz , Ingo Molnar , Alexander Viro , "Eric W. Biederman" Subject: [patch 7/8] posix-cpu-timers: Prevent enqueueing when PF_EXITING is set References: <20260904112100.683893401@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" To prepare for cleaning up POSIX CPU timers in do_exit(), prevent enqueueing POSIX CPU timers on a task which has PF_EXITING set. Queueing a timer on such a task is pointless because the task won't expire the timer anymore. Pretending that the timer is armed allows to keep the POSIX timer mechanism "working" so that the timer stays accessible up to the point where a task is unhashed. Signed-off-by: Thomas Gleixner --- kernel/time/posix-cpu-timers.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c @@ -628,6 +628,7 @@ static int posix_cpu_timer_del(struct k_ } =20 if (!ret) { + WARN_ON_ONCE(cpu_timer_queued(&timer->it.cpu)); put_pid(timer->it.cpu.pid); timer->it_status =3D POSIX_TIMER_DISARMED; } @@ -674,6 +675,15 @@ void posix_cpu_timers_exit_group(struct cleanup_timers(&tsk->signal->posix_cputimers); } =20 +static inline bool task_can_enqueue(struct k_itimer *timer, struct task_st= ruct *p) +{ + if (likely(!(p->flags & PF_EXITING))) + return true; + + /* Allow TGID type unless the last thread is on the way out. */ + return clock_pid_type(timer->it_clock) =3D=3D PIDTYPE_TGID && atomic_read= (&p->signal->live); +} + /* * Insert the timer on the appropriate list before any timers that * expire later. This must be called with the sighand lock held. @@ -684,7 +694,24 @@ static void arm_timer(struct k_itimer *t struct cpu_timer *ctmr =3D &timer->it.cpu; u64 newexp =3D cpu_timer_getexpires(ctmr); =20 + lockdep_assert_held(&p->sighand->siglock); + timer->it_status =3D POSIX_TIMER_ARMED; + + /* + * Don't enqueue timers when the task or the group is exiting. That + * ensures that timer operations are still succeeding as long as the + * tasks are visible, but won't enqueue the timers on the task or + * process. They won't expire anyway because run_posix_cpu_timers() + * exits early when PF_EXITING is set. + * + * Enqueue is skipped if PF_EXITING is set when the timer is per task + * and when the last thread decremented p::signal::live to zero also for + * per process timers. + */ + if (unlikely(!task_can_enqueue(timer, p))) + return; + if (!cpu_timer_enqueue(&base->tqhead, ctmr)) return; From nobody Sat Sep 26 04:36:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D6F8C46DFF1 for ; Fri, 4 Sep 2026 11:22:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788520978; cv=none; b=DDffi81fr2XS1zBEjXEdlUOHUM21x9STT2WaFQ5Uy8QhVjPlsr9H9sYidxxDkUyz04tXlQjwbWk/WHYmNLof+t4kAFRKiUg1e4OUrmvRmo4xV0BK/NNZ9Sol5aSydUKxHzgP7Gf2iZZhGjPf8ba8f1myZNRD9EzRN71lsxdfm/M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788520978; c=relaxed/simple; bh=JSI9AccuNCUNfnVqUCUUG6x93n+rzkRG/xslGnsph/I=; h=Date:Message-ID:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=n3xA18HgL2OIvdFC1+FDouTzcfSBIJclLfzLYm0Xpj3zS9FrleXo7dWIzwYnS6z8IO/s8F32fZCPvqIaZD7IGMkR5uFfg0WgTX/ro7JAZ5soI0D7LWDbsWCh25InZnIbh9IPagjOlvx8GvBkkI0DzKpkaqSCoQaMSBZGtYGzbbA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=c/cp+K4a; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="c/cp+K4a" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BEDD31F00A3D; Fri, 4 Sep 2026 11:22:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788520976; bh=ni4vkoyk/WLmObCznYLfKvARCXRcIOlzhdoAoUGWpeQ=; h=Date:From:To:Cc:Subject:References; b=c/cp+K4aWmEqK6tgqssPY86VsOW0RsJncv48ryrH55lZShLakU7HMkT2rR41hGJX0 gsJmvZieRfeinZcr3AH0MaUQgNvrHAWoHX7JWu9hK+SfHgq2dmRvv2BaAl5vn/Wqbj MH6nvQmIGDmkNNRHIW2XYmoZzV+OB06FcnFKk48TYEF2cFdlJ3eJZ1Qmi5MIC62IhQ wccK7k4d7JAEBBYAjWUXpMBnqHZAI5PL4nG20V46+kH4AWc7H4l0J+jKoE+P5M4Z65 r0ohutYRQhXgoNsCAf4ZQJrvvmhUMEaZobuQb83sC5ZcSpZgdWsaQfP2ywk7qdAbzF vU77/rnicxPtQ== Date: Fri, 04 Sep 2026 13:22:53 +0200 Message-ID: <20260904112202.454774247@kernel.org> User-Agent: quilt/0.69 From: Thomas Gleixner To: LKML Cc: Hyunwoo Kim , Oleg Nesterov , Frederic Weisbecker , Christian Brauner , Peter Zijlstra , John Stultz , Ingo Molnar , Alexander Viro , "Eric W. Biederman" Subject: [patch 8/8] posix-timers: Handle exit in do_exit() completely References: <20260904112100.683893401@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Now that POSIX CPU timers cannot be enqueued on a task after PF_EXITING is set and process wide timers cannot be enqueued when PF_EXITING is set and the last thread in the group is exiting, it is possible to mop up POSIX timers in do_exit() completely. This requires to cancel an eventually pending POSIX CPU timer task work right there because do_exit() invokes exit_task_work() later, which would be acting on torn down data. Signed-off-by: Thomas Gleixner --- include/linux/posix-timers.h | 6 ++---- kernel/exit.c | 10 ++-------- kernel/time/posix-cpu-timers.c | 38 +++++++++++++++++++++++++++++++-----= -- kernel/time/posix-timers.c | 15 +++++++++------ kernel/time/posix-timers.h | 3 +++ 5 files changed, 47 insertions(+), 25 deletions(-) --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -192,8 +192,6 @@ struct k_itimer { } ____cacheline_aligned_in_smp; =20 void run_posix_cpu_timers(void); -void posix_cpu_timers_exit(struct task_struct *task); -void posix_cpu_timers_exit_group(struct task_struct *task); void set_process_cpu_timer(struct task_struct *task, unsigned int clock_id= x, u64 *newval, u64 *oldval); =20 @@ -201,7 +199,7 @@ int update_rlimit_cpu(struct task_struct =20 #ifdef CONFIG_POSIX_TIMERS void posixtimer_exec(void); -void posixtimer_exit(void); +void posixtimer_exit(bool group_dead); =20 static inline void posixtimer_putref(struct k_itimer *tmr) { @@ -231,7 +229,7 @@ static inline bool posixtimer_valid(cons } #else /* CONFIG_POSIX_TIMERS */ static inline void posixtimer_exec(void) { } -static inline void posixtimer_exit(void) { } +static inline void posixtimer_exit(bool group_dead) { } static inline void posixtimer_sigqueue_getref(struct sigqueue *q) { } static inline void posixtimer_sigqueue_putref(struct sigqueue *q) { } #endif /* !CONFIG_POSIX_TIMERS */ --- a/kernel/exit.c +++ b/kernel/exit.c @@ -167,12 +167,6 @@ static void __exit_signal(struct release lockdep_tasklist_lock_is_held()); spin_lock(&sighand->siglock); =20 -#ifdef CONFIG_POSIX_TIMERS - posix_cpu_timers_exit(tsk); - if (group_dead) - posix_cpu_timers_exit_group(tsk); -#endif - if (group_dead) { tty =3D sig->tty; sig->tty =3D NULL; @@ -963,12 +957,12 @@ void __noreturn do_exit(long code) panic("Attempted to kill init! exitcode=3D0x%08x\n", tsk->signal->group_exit_code ?: (int)code); =20 - posixtimer_exit(); - if (tsk->mm) setmax_mm_hiwater_rss(&tsk->signal->maxrss, tsk->mm); } =20 + posixtimer_exit(group_dead); + acct_collect(code, group_dead); if (group_dead) tty_audit_exit(); --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c @@ -661,18 +661,29 @@ static void cleanup_timers(struct posix_ cleanup_timerqueue(&pct->bases[CPUCLOCK_SCHED].tqhead); } =20 +static inline void posix_cpu_timers_exit_work(void); + /* - * These are both called with the siglock held, when the current thread - * is being reaped. When the final (leader) thread in the group is reaped, - * posix_cpu_timers_exit_group will be called after posix_cpu_timers_exit. + * Invoked from posixtimer_exit_task() after PF_EXITING was set in tsk::fl= ags or + * from posixtimer_exec_cleanup(). */ -void posix_cpu_timers_exit(struct task_struct *tsk) +void posix_cpu_timers_exit_task(void) { - cleanup_timers(&tsk->posix_cputimers); + posix_cpu_timers_exit_work(); + + guard(spinlock_irq)(¤t->sighand->siglock); + cleanup_timers(¤t->posix_cputimers); } -void posix_cpu_timers_exit_group(struct task_struct *tsk) + +/* + * Invoked from posixtimer_exit_group() after PF_EXITING was set in tsk::f= lags. + */ +void posix_cpu_timers_exit_group(void) { - cleanup_timers(&tsk->signal->posix_cputimers); + posix_cpu_timers_exit_task(); + + guard(spinlock_irq)(¤t->sighand->siglock); + cleanup_timers(¤t->signal->posix_cputimers); } =20 static inline bool task_can_enqueue(struct k_itimer *timer, struct task_st= ruct *p) @@ -1256,6 +1267,17 @@ static void posix_cpu_timers_work(struct mutex_unlock(&cw->mutex); } =20 +static inline void posix_cpu_timers_exit_work(void) +{ + /* + * current->flags has PF_EXITING set so this can be done lockless and + * with interrupts enabled as PF_EXITING prevents the interrupt from + * scheduling the work. + */ + if (current->posix_cputimers_work.scheduled) + task_work_cancel(current, ¤t->posix_cputimers_work.work); +} + /* * Invoked from the posix-timer core when a cancel operation failed because * the timer is marked firing. The caller holds rcu_read_lock(), which @@ -1386,6 +1408,8 @@ static inline void __run_posix_cpu_timer lockdep_posixtimer_exit(); } =20 +static inline void posix_cpu_timers_exit_work(void) { } + static void posix_cpu_timer_wait_running(struct k_itimer *timr) { cpu_relax(); --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -1116,17 +1116,20 @@ static void posixtimer_delete_timers(voi } } =20 -void posixtimer_exit(void) +void posixtimer_exit(bool group_dead) { - hrtimer_cancel(¤t->signal->real_timer); - posixtimer_delete_timers(); + if (group_dead) { + hrtimer_cancel(¤t->signal->real_timer); + posix_cpu_timers_exit_group(); + posixtimer_delete_timers(); + } else { + posix_cpu_timers_exit_task(); + } } =20 void posixtimer_exec(void) { - scoped_guard(spinlock_irq, ¤t->sighand->siglock) - posix_cpu_timers_exit(current); - + posix_cpu_timers_exit_task(); posixtimer_delete_timers(); flush_itimer_signals(); } --- a/kernel/time/posix-timers.h +++ b/kernel/time/posix-timers.h @@ -51,3 +51,6 @@ int common_timer_set(struct k_itimer *ti struct itimerspec64 *old_setting); void posix_timer_set_common(struct k_itimer *timer, struct itimerspec64 *n= ew_setting); int common_timer_del(struct k_itimer *timer); + +void posix_cpu_timers_exit_task(void); +void posix_cpu_timers_exit_group(void);