Hello,

[email protected], le mar. 03 mars 2026 04:08:15 +0000, a ecrit:
> #### S-2: `sigtimedwait` leaks preemptor on timeout (CRITICAL)
> 
> **File**: `sysdeps/mach/hurd/sigtimedwait.c`
> 
> When `__sigtimedwait` times out, the timeout path (lines 144-148) falls 
> through
> to `all_done` without removing the signal preemptor from `ss->preemptors`.
> The preemptor is a stack-local variable, so after the function returns,
> `ss->preemptors` contains a dangling pointer. Subsequent signal delivery will
> dereference freed stack memory.
> 
> Additionally, the timeout path never restores `ss->blocked` (saved at line 
> 128,
> modified at line 129), so temporarily unblocked signals remain unblocked. It 
> also
> calls `_hurd_sigstate_unlock` at `all_done` without holding the lock 
> (released at
> line 131), which is undefined behavior.

Indeed, I guess this was never actually tested.

> #### S-2 Proposed Fix: Clean up preemptor and blocked mask on timeout
> 
> The timeout path (lines 144-148, inside the `if (!setjmp (buf))` block after
> `mach_msg` returns) needs to re-lock sigstate, remove the preemptor, and
> restore the blocked mask. Replace lines 144-148:
> 
> ```c
>       if (!(option & MACH_RCV_TIMEOUT))
>         abort ();
> 
>       /* Timed out.  */
>       signo = __hurd_fail (EAGAIN);
> ```
> 
> with:
> 
> ```c
>       if (!(option & MACH_RCV_TIMEOUT))
>         abort ();
> 
>       /* Timed out.  Clean up the preemptor and restore blocked mask.  */
>       _hurd_sigstate_lock (ss);
>       assert (ss->preemptors == &preemptor);
>       ss->preemptors = preemptor.next;
>       ss->blocked = blocked;
>       signo = __hurd_fail (EAGAIN);
> ```
> 
> All three paths through the function (already-pending, signal delivery via
> `longjmp`, and timeout) now reach `all_done` holding `ss->lock`, so the
> existing `_hurd_sigstate_unlock` at `all_done` handles all of them correctly.

I have rather simply let both codepaths use the same cleanup code.

I have also added some test, which was indeed crashing before the fix.

Thanks!
Samuel

Reply via email to