Re: [PATCH V2] signal: Prevent exec() race
From: Oleg Nesterov
Date: Wed Sep 02 2026 - 06:53:18 EST
On 09/02, Oleg Nesterov wrote:
>
> On 09/01, Thomas Gleixner wrote:
> >
> > 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.
>
> If timer->sigq is queued on T->pending list, then T has a reference.
> Even if this timer is destroyed, it and its ->sigq can't go away until
> __sigqueue_free() -> posixtimer_sigqueue_putref(timer->sigq). Right?
>
> So, If we change posixtimer_send_sigqueue() to check PF_EXITING and
> return, then why do we need other changes?
Aaah. I am stupid. the PF_EXITING check in posixtimer_send_sigqueue()
is obviously not enough, posixtimer_get_target() can return the execing
thread which is alive and doesn't have PF_EXITING set...
> Ah, and I just noticed...
>
> > @@ -1990,6 +2004,9 @@ void posixtimer_send_sigqueue(struct k_i
> > if (!likely(lock_task_sighand(t, &flags)))
> > return;
> >
> > + if (unlikely(tmr->it_pid_type == PIDTYPE_PID && (t->flags & PF_EXITING)))
> > + return;
>
> this lacks unlock_sighand().
Oleg.