diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | sysdeps/mach/hurd/i386/sigreturn.c | 68 |
2 files changed, 47 insertions, 26 deletions
diff --git a/ChangeLog b/ChangeLog index 98a86369d5..12d183dbc3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -24,6 +24,11 @@ * sysdeps/mach/hurd/mmap.c (__mmap): Remove optimizing anonymous maps as __vm_allocate. + * sysdeps/mach/hurd/i386/sigreturn.c (__sigreturn2): New function, + unlocks SS and returns to the saved PC. + (__sigreturn): Do not unlock SS, and "return" into __sigreturn2 on the + thread stack instead of the saved PC. + 2019-08-30 Richard Braun <rbraun@sceen.net> * hurd/hurdselect.c (_hurd_select): Always call __io_select with no diff --git a/sysdeps/mach/hurd/i386/sigreturn.c b/sysdeps/mach/hurd/i386/sigreturn.c index be7153e202..c9eaf96f7d 100644 --- a/sysdeps/mach/hurd/i386/sigreturn.c +++ b/sysdeps/mach/hurd/i386/sigreturn.c @@ -24,6 +24,36 @@ register int *sp asm ("%esp"); #include <stdlib.h> #include <string.h> +/* This is run on the thread stack after restoring it, to be able to + unlock SS off sigstack. */ +static void +__sigreturn2 (int *usp) +{ + struct hurd_sigstate *ss = _hurd_self_sigstate (); + __spin_unlock (ss); + + sp = usp; +#define A(line) asm volatile (#line) + /* The members in the sigcontext are arranged in this order + so we can pop them easily. */ + + /* Pop the segment registers (except %cs and %ss, done last). */ + A (popl %gs); + A (popl %fs); + A (popl %es); + A (popl %ds); + /* Pop the general registers. */ + A (popa); + /* Pop the processor flags. */ + A (popf); + /* Return to the saved PC. */ + A (ret); + + /* Firewall. */ + A (hlt); +#undef A +} + int __sigreturn (struct sigcontext *scp) { @@ -67,13 +97,7 @@ __sigreturn (struct sigcontext *scp) } if (scp->sc_onstack) - { - ss->sigaltstack.ss_flags &= ~SS_ONSTACK; - /* XXX cannot unlock until off sigstack */ - abort (); - } - else - __spin_unlock (&ss->lock); + ss->sigaltstack.ss_flags &= ~SS_ONSTACK; /* Destroy the MiG reply port used by the signal handler, and restore the reply port in use by the thread when interrupted. */ @@ -108,27 +132,19 @@ __sigreturn (struct sigcontext *scp) *--usp = scp->sc_efl; memcpy (usp -= 12, &scp->sc_i386_thread_state, 12 * sizeof (int)); - sp = usp; - -#define A(line) asm volatile (#line) - /* The members in the sigcontext are arranged in this order - so we can pop them easily. */ - - /* Pop the segment registers (except %cs and %ss, done last). */ - A (popl %gs); - A (popl %fs); - A (popl %es); - A (popl %ds); - /* Pop the general registers. */ - A (popa); - /* Pop the processor flags. */ - A (popf); - /* Return to the saved PC. */ - A (ret); + /* Pass usp to __sigreturn2 so it can unwind itself easily. */ + *(usp-1) = (int) usp; + --usp; + /* Bogus return address for __sigreturn2 */ + *--usp = 0; + *--usp = (int) __sigreturn2; + /* Restore thread stack */ + sp = usp; + /* Return into __sigreturn2. */ + asm volatile ("ret"); /* Firewall. */ - A (hlt); -#undef A + asm volatile ("hlt"); } /* NOTREACHED */ |