hurd: catch SIGSEGV on returning from signal handler

On stack overflow typically, we may not actually have room on the stack to
trampoline back from the signal handler.  We have to detect this before
locking the ss, otherwise the signal thread will be stuck on taking the
ss lock while trying to post SIGSEGV.
This commit is contained in:
Samuel Thibault 2025-09-21 23:45:40 +02:00
parent 8aa99c592b
commit c9cc047e9f
2 changed files with 23 additions and 2 deletions

View File

@ -89,10 +89,21 @@ __sigreturn (struct sigcontext *scp)
{
struct hurd_sigstate *ss;
struct hurd_userlink *link = (void *) &scp[1];
int *usp;
/* Stack usage while trampolining back:
* register dump, parameters, and rough estimation of usage in __sigreturn2
* before unlocking ss. */
size_t tramp_usage = 18 * sizeof (uintptr_t) + 32;
if (__glibc_unlikely (scp == NULL || (scp->sc_mask & _SIG_CANT_MASK)))
return __hurd_fail (EINVAL);
usp = (int *) scp->sc_uesp;
/* If we are to segfault, do it now before locking the ss. */
memset ((void*) usp - tramp_usage, 0, tramp_usage);
ss = _hurd_self_sigstate ();
_hurd_sigstate_lock (ss);
@ -160,7 +171,7 @@ __sigreturn (struct sigcontext *scp)
copy the registers onto the user's stack, switch there, pop and
return. */
int usp_arg, *usp = (int *) scp->sc_uesp;
int usp_arg;
*--usp = scp->sc_eip;
*--usp = scp->sc_efl;

View File

@ -83,9 +83,20 @@ __sigreturn (struct sigcontext *scp)
uintptr_t *usp;
mach_port_t sc_reply_port;
/* Stack usage while trampolining back:
* register dump, 16B round-up, and rough estimation of usage in __sigreturn2
* before unlocking ss. */
size_t tramp_usage = 17 * sizeof (uintptr_t) + 16 + 64;
if (__glibc_unlikely (scp == NULL || (scp->sc_mask & _SIG_CANT_MASK)))
return __hurd_fail (EINVAL);
/* Respect the redzone. */
usp = (uintptr_t *) (scp->sc_ursp - 128);
/* If we are to segfault, do it now before locking the ss. */
memset ((void*) usp - tramp_usage, 0, tramp_usage);
ss = _hurd_self_sigstate ();
_hurd_sigstate_lock (ss);
@ -160,7 +171,6 @@ __sigreturn (struct sigcontext *scp)
located at a larger address than the sigcontext. */
sc_reply_port = scp->sc_reply_port;
usp = (uintptr_t *) (scp->sc_ursp - 128);
*--usp = scp->sc_rip;
*--usp = scp->sc_rfl;