Re: [PATCH V2] signal: Prevent exec() race

From: Oleg Nesterov

Date: Wed Sep 02 2026 - 06:35:11 EST


As I said many times in this thread I am all confused ;)
And of course I don't understand posix-timers.c enough.

So let me ask the stupid question...

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?

Perhaps they make sense, but why do we need them to fix this particular
problem?

I am sure I missed something obvious, please help me to understand.

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.