1  /* Set thread_state for sighandler, and sigcontext to recover.  x86 version.
       2     Copyright (C) 1994-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <hurd/signal.h>
      20  #include <hurd/userlink.h>
      21  #include <thread_state.h>
      22  #include <mach/exception.h>
      23  #include <mach/machine/eflags.h>
      24  #include <assert.h>
      25  #include <errno.h>
      26  #include "hurdfault.h"
      27  #include <intr-msg.h>
      28  #include <sys/ucontext.h>
      29  
      30  
      31  /* Fill in a siginfo_t structure for SA_SIGINFO-enabled handlers.  */
      32  static void fill_siginfo (siginfo_t *si, int signo,
      33  			  const struct hurd_signal_detail *detail,
      34  			  const struct machine_thread_all_state *state)
      35  {
      36    si->si_signo = signo;
      37    si->si_errno = detail->error;
      38    si->si_code = detail->code;
      39  
      40    /* XXX We would need a protocol change for sig_post to include
      41     * this information.  */
      42    si->si_pid = -1;
      43    si->si_uid = -1;
      44  
      45    /* Address of the faulting instruction or memory access.  */
      46    if (detail->exc == EXC_BAD_ACCESS)
      47      si->si_addr = (void *) detail->exc_subcode;
      48    else
      49      {
      50  #ifdef __x86_64__
      51        si->si_addr = (void *) state->basic.rip;
      52  #else
      53        si->si_addr = (void *) state->basic.eip;
      54  #endif
      55      }
      56  
      57    /* XXX On SIGCHLD, this should be the exit status of the child
      58     * process.  We would need a protocol change for the proc server
      59     * to send this information along with the signal.  */
      60    si->si_status = 0;
      61  
      62    si->si_band = 0;              /* SIGPOLL is not supported yet.  */
      63    si->si_value.sival_int = 0;   /* sigqueue() is not supported yet.  */
      64  }
      65  
      66  /* Fill in a ucontext_t structure SA_SIGINFO-enabled handlers.  */
      67  static void fill_ucontext (ucontext_t *uc, const struct sigcontext *sc)
      68  {
      69    uc->uc_flags = 0;
      70    uc->uc_link = NULL;
      71    uc->uc_sigmask = sc->sc_mask;
      72  #ifdef __x86_64__
      73    uc->uc_stack.ss_sp = (__ptr_t) sc->sc_ursp;
      74  #else
      75    uc->uc_stack.ss_sp = (__ptr_t) sc->sc_uesp;
      76  #endif
      77    uc->uc_stack.ss_size = 0;
      78    uc->uc_stack.ss_flags = 0;
      79  
      80    /* Registers.  */
      81  #ifdef __x86_64__
      82    memcpy (&uc->uc_mcontext.gregs[REG_GSFS], &sc->sc_gs,
      83            (REG_ERR - REG_GSFS) * sizeof (long));
      84  #else
      85    memcpy (&uc->uc_mcontext.gregs[REG_GS], &sc->sc_gs,
      86            (REG_TRAPNO - REG_GS) * sizeof (int));
      87    memcpy (&uc->uc_mcontext.gregs[REG_EIP], &sc->sc_eip,
      88  	  (NGREG - REG_EIP) * sizeof (int));
      89  #endif
      90    uc->uc_mcontext.gregs[REG_TRAPNO] = 0;
      91    uc->uc_mcontext.gregs[REG_ERR] = 0;
      92  
      93    /* XXX FPU state.  */
      94    memset (&uc->uc_mcontext.fpregs, 0, sizeof (fpregset_t));
      95  }
      96  
      97  struct sigcontext *
      98  _hurd_setup_sighandler (struct hurd_sigstate *ss, const struct sigaction *action,
      99  			__sighandler_t handler,
     100  			int signo, struct hurd_signal_detail *detail,
     101  			int rpc_wait,
     102  			struct machine_thread_all_state *state)
     103  {
     104    void trampoline (void);
     105    void rpc_wait_trampoline (void);
     106    void firewall (void);
     107    void *sigsp;
     108    struct sigcontext *scp;
     109    struct
     110      {
     111        union
     112          {
     113            int signo;
     114            /* Make sure signo takes up a pointer-sized slot on the stack.
     115               (This should already be the case considering the siginfop
     116               pointer below, but better be explicit.)  */
     117            void *_pointer_sized;
     118          };
     119        union
     120  	{
     121  	  /* Extra arguments for traditional signal handlers */
     122  	  struct
     123  	    {
     124  	      long int sigcode;
     125  	      struct sigcontext *scp;       /* Points to ctx, below.  */
     126  	    } legacy;
     127  
     128  	  /* Extra arguments for SA_SIGINFO handlers */
     129  	  struct
     130  	    {
     131  	      siginfo_t *siginfop;          /* Points to siginfo, below.  */
     132  	      ucontext_t *uctxp;            /* Points to uctx, below.  */
     133  	    } posix;
     134  	};
     135  
     136  #ifdef __x86_64__
     137        void *_pad;
     138  #endif
     139        void *sigreturn_addr;
     140        void *sigreturn_returns_here;
     141        struct sigcontext *return_scp; /* Same; arg to sigreturn.  */
     142  
     143        /* NB: sigreturn assumes link is next to ctx.  */
     144        struct sigcontext ctx;
     145        struct hurd_userlink link;
     146        ucontext_t ucontext;
     147        siginfo_t siginfo;
     148      } *stackframe;
     149  
     150  #ifdef __x86_64__
     151    _Static_assert (offsetof (typeof (*stackframe), sigreturn_addr) % 16 == 0,
     152                    "sigreturn_addr must be 16-byte aligned");
     153  #endif
     154  
     155    if (ss->context)
     156      {
     157        /* We have a previous sigcontext that sigreturn was about
     158  	 to restore when another signal arrived.  We will just base
     159  	 our setup on that.  */
     160        if (! _hurdsig_catch_memory_fault (ss->context))
     161  	{
     162  	  memcpy (&state->basic, &ss->context->sc_i386_thread_state,
     163  		  sizeof (state->basic));
     164  	  memcpy (&state->fpu, &ss->context->sc_i386_float_state,
     165  		  sizeof (state->fpu));
     166  	  state->set |= (1 << i386_REGS_SEGS_STATE) | (1 << i386_FLOAT_STATE);
     167  	}
     168      }
     169  
     170    if (! machine_get_basic_state (ss->thread, state))
     171      return NULL;
     172  
     173    /* Save the original SP in the gratuitous `esp' slot.
     174       We may need to reset the SP (the `uesp' slot) to avoid clobbering an
     175       interrupted RPC frame.  */
     176  #ifdef __x86_64__
     177    state->basic.rsp = state->basic.ursp;
     178  #else
     179    state->basic.esp = state->basic.uesp;
     180  #endif
     181  
     182    if ((action->sa_flags & SA_ONSTACK)
     183        && !(ss->sigaltstack.ss_flags & (SS_DISABLE|SS_ONSTACK)))
     184      {
     185        sigsp = ss->sigaltstack.ss_sp + ss->sigaltstack.ss_size;
     186        ss->sigaltstack.ss_flags |= SS_ONSTACK;
     187      }
     188    else
     189      {
     190  #ifdef __x86_64__
     191        /* Per the ABI, we're not supposed to clobber 128 bytes below
     192           SP -- the red zone.  */
     193        sigsp = (char *) state->basic.ursp - 128;
     194  #else
     195        sigsp = (char *) state->basic.uesp;
     196  #endif
     197      }
     198  
     199    /* Push the arguments to call `trampoline' on the stack.  */
     200    sigsp -= sizeof (*stackframe);
     201  #ifdef __x86_64__
     202    /* Align SP at 16 bytes.  Coupled with the fact that sigreturn_addr is
     203       16-byte aligned within the stackframe struct, this ensures that it ends
     204       up on a 16-byte aligned address, as required by the ABI.  */
     205    sigsp = (void *) ((uintptr_t) sigsp & ~15UL);
     206  #endif
     207    stackframe = sigsp;
     208  
     209    if (_hurdsig_catch_memory_fault (stackframe))
     210      {
     211        /* We got a fault trying to write the stack frame.
     212  	 We cannot set up the signal handler.
     213  	 Returning NULL tells our caller, who will nuke us with a SIGILL.  */
     214        return NULL;
     215      }
     216    else
     217      {
     218        int ok;
     219  
     220        extern void _hurdsig_longjmp_from_handler (void *, jmp_buf, int);
     221  
     222        /* Add a link to the thread's active-resources list.  We mark this as
     223  	 the only user of the "resource", so the cleanup function will be
     224  	 called by any longjmp which is unwinding past the signal frame.
     225  	 The cleanup function (in sigunwind.c) will make sure that all the
     226  	 appropriate cleanups done by sigreturn are taken care of.  */
     227        stackframe->link.cleanup = &_hurdsig_longjmp_from_handler;
     228        stackframe->link.cleanup_data = &stackframe->ctx;
     229        stackframe->link.resource.next = NULL;
     230        stackframe->link.resource.prevp = NULL;
     231        stackframe->link.thread.next = ss->active_resources;
     232        stackframe->link.thread.prevp = &ss->active_resources;
     233        if (stackframe->link.thread.next)
     234  	stackframe->link.thread.next->thread.prevp
     235  	  = &stackframe->link.thread.next;
     236        ss->active_resources = &stackframe->link;
     237  
     238        /* Set up the sigcontext from the current state of the thread.  */
     239  
     240        scp = &stackframe->ctx;
     241        scp->sc_onstack = ss->sigaltstack.ss_flags & SS_ONSTACK ? 1 : 0;
     242  
     243        /* struct sigcontext is laid out so that starting at sc_gs mimics a
     244  	 struct i386_thread_state.  */
     245        _Static_assert (offsetof (struct sigcontext, sc_i386_thread_state)
     246  		      % __alignof__ (struct i386_thread_state) == 0,
     247  		      "sc_i386_thread_state layout mismatch");
     248        memcpy (&scp->sc_i386_thread_state,
     249  	      &state->basic, sizeof (state->basic));
     250  
     251        /* struct sigcontext is laid out so that starting at sc_fpkind mimics
     252  	 a struct i386_float_state.  */
     253        _Static_assert (offsetof (struct sigcontext, sc_i386_float_state)
     254  		      % __alignof__ (struct i386_float_state) == 0,
     255  		      "sc_i386_float_state layout mismatch");
     256        ok = machine_get_state (ss->thread, state, i386_FLOAT_STATE,
     257  			      &state->fpu, &scp->sc_i386_float_state,
     258  			      sizeof (state->fpu));
     259  
     260        /* Set up the arguments for the signal handler.  */
     261        stackframe->signo = signo;
     262        if (action->sa_flags & SA_SIGINFO)
     263  	{
     264  	  stackframe->posix.siginfop = &stackframe->siginfo;
     265  	  stackframe->posix.uctxp = &stackframe->ucontext;
     266  	  fill_siginfo (&stackframe->siginfo, signo, detail, state);
     267  	  fill_ucontext (&stackframe->ucontext, scp);
     268  	}
     269        else
     270  	{
     271  	  if (detail->exc)
     272  	    {
     273  	      int nsigno;
     274  	      _hurd_exception2signal_legacy (detail, &nsigno);
     275  	      assert (nsigno == signo);
     276  	    }
     277  	  else
     278  	    detail->code = 0;
     279  
     280  	  stackframe->legacy.sigcode = detail->code;
     281  	  stackframe->legacy.scp = &stackframe->ctx;
     282  	}
     283  
     284        /* Set up the bottom of the stack.  */
     285        stackframe->sigreturn_addr = &__sigreturn;
     286        stackframe->sigreturn_returns_here = firewall; /* Crash on return.  */
     287        stackframe->return_scp = &stackframe->ctx;
     288  
     289        _hurdsig_end_catch_fault ();
     290  
     291        if (! ok)
     292  	return NULL;
     293      }
     294  
     295    /* Modify the thread state to call the trampoline code on the new stack.  */
     296  #ifdef __x86_64__
     297    if (rpc_wait)
     298      {
     299        /* The signalee thread was blocked in a mach_msg_trap system call,
     300           still waiting for a reply.  We will have it run the special
     301           trampoline code which retries the message receive before running
     302           the signal handler.
     303  
     304           To do this we change the OPTION argument (in rsi) to enable only
     305           message reception, since the request message has already been
     306           sent.  */
     307  
     308        assert (state->basic.rsi & MACH_RCV_MSG);
     309        /* Disable the message-send, since it has already completed.  The
     310           calls we retry need only wait to receive the reply message.  */
     311        state->basic.rsi &= ~MACH_SEND_MSG;
     312  
     313        /* Limit the time to receive the reply message, in case the server
     314           claimed that `interrupt_operation' succeeded but in fact the RPC
     315           is hung.  */
     316        state->basic.rsi |= MACH_RCV_TIMEOUT;
     317        state->basic.r9 = _hurd_interrupted_rpc_timeout;
     318  
     319        state->basic.rip = (uintptr_t) rpc_wait_trampoline;
     320        /* The reply-receiving trampoline code runs initially on the original
     321           user stack.  We pass it the signal stack pointer in %rbx.  */
     322        state->basic.rbx = (uintptr_t) sigsp;
     323        /* After doing the message receive, the trampoline code will need to
     324           update the %rax value to be restored by sigreturn.  To simplify
     325           the assembly code, we pass the address of its slot in SCP to the
     326           trampoline code in %r12.  */
     327        state->basic.r12 = (uintptr_t) &scp->sc_rax;
     328      }
     329    else
     330      {
     331        state->basic.rip = (uintptr_t) trampoline;
     332        state->basic.ursp = (uintptr_t) sigsp;
     333      }
     334    /* We pass the handler function to the trampoline code in %r13.  */
     335    state->basic.r13 = (uintptr_t) handler;
     336  
     337    /* The x86 ABI says the DF bit is clear on entry to any function.  */
     338    state->basic.rfl &= ~EFL_DF;
     339  
     340  #else
     341  
     342    if (rpc_wait)
     343      {
     344        /* The signalee thread was blocked in a mach_msg_trap system call,
     345  	 still waiting for a reply.  We will have it run the special
     346  	 trampoline code which retries the message receive before running
     347  	 the signal handler.
     348  
     349  	 To do this we change the OPTION argument on its stack to enable only
     350  	 message reception, since the request message has already been
     351  	 sent.  */
     352  
     353        struct mach_msg_trap_args *args = (void *) state->basic.esp;
     354  
     355        if (_hurdsig_catch_memory_fault (args))
     356  	{
     357  	  /* Faulted accessing ARGS.  Bomb.  */
     358  	  return NULL;
     359  	}
     360  
     361        assert (args->option & MACH_RCV_MSG);
     362        /* Disable the message-send, since it has already completed.  The
     363  	 calls we retry need only wait to receive the reply message.  */
     364        args->option &= ~MACH_SEND_MSG;
     365  
     366        /* Limit the time to receive the reply message, in case the server
     367  	 claimed that `interrupt_operation' succeeded but in fact the RPC
     368  	 is hung.  */
     369        args->option |= MACH_RCV_TIMEOUT;
     370        args->timeout = _hurd_interrupted_rpc_timeout;
     371  
     372        _hurdsig_end_catch_fault ();
     373  
     374        state->basic.eip = (uintptr_t) rpc_wait_trampoline;
     375        /* The reply-receiving trampoline code runs initially on the original
     376  	 user stack.  We pass it the signal stack pointer in %ebx.  */
     377        state->basic.ebx = (uintptr_t) sigsp;
     378        /* After doing the message receive, the trampoline code will need to
     379  	 update the %eax value to be restored by sigreturn.  To simplify
     380  	 the assembly code, we pass the address of its slot in SCP to the
     381  	 trampoline code in %ecx.  */
     382        state->basic.ecx = (uintptr_t) &scp->sc_eax;
     383      }
     384    else
     385      {
     386        state->basic.eip = (uintptr_t) trampoline;
     387        state->basic.uesp = (uintptr_t) sigsp;
     388      }
     389    /* We pass the handler function to the trampoline code in %edx.  */
     390    state->basic.edx = (uintptr_t) handler;
     391  
     392    /* The x86 ABI says the DF bit is clear on entry to any function.  */
     393    state->basic.efl &= ~EFL_DF;
     394  #endif
     395  
     396    return scp;
     397  }
     398  
     399  /* The trampoline code follows.  This used to be located inside
     400     _hurd_setup_sighandler, but was optimized away by gcc 2.95.
     401  
     402     If you modify this, update
     403     - in gcc: libgcc/config/i386/gnu-unwind.h x86_gnu_fallback_frame_state,
     404     - in gdb: gdb/i386-gnu-tdep.c gnu_sigtramp_code.  */
     405  
     406  #ifdef __x86_64__
     407  asm ("rpc_wait_trampoline:\n"
     408    /* This is the entry point when we have an RPC reply message to receive
     409       before running the handler.  The MACH_MSG_SEND bit has already been
     410       cleared in the OPTION argument in our %rsi.  The interrupted user
     411       stack pointer has not been changed, so the system call can find its
     412       arguments; the signal stack pointer is in %rbx.  For our convenience,
     413       %r12 points to the sc_rax member of the sigcontext.  */
     414       "movq $-25, %rax\n"	/* mach_msg_trap */
     415       "syscall\n"
     416       /* When the sigcontext was saved, %rax was MACH_RCV_INTERRUPTED.  But
     417          now the message receive has completed and the original caller of
     418          the RPC (i.e. the code running when the signal arrived) needs to
     419          see the final return value of the message receive in %rax.  So
     420          store the new %rax value into the sc_rax member of the sigcontext
     421          (whose address is in %r12 to make this code simpler).  */
     422       "movq %rax, (%r12)\n"
     423       /* Switch to the signal stack.  */
     424       "movq %rbx, %rsp\n"
     425  
     426       "trampoline:\n"
     427       /* Entry point for running the handler normally.  The arguments to the
     428          handler function are on the top of the stack, same as in the i386
     429          version:
     430  
     431          0(%rsp)  SIGNO
     432          8(%rsp)  SIGCODE
     433          16(%rsp) SCP
     434  
     435          Pop them off to the registers, to pass as arguments to the handler.
     436       */
     437       "popq %rdi\n"
     438       "popq %rsi\n"
     439       "popq %rdx\n"
     440       /* Pop the _pad member to make the stack 16-byte aligned, as per the
     441          ABI.  */
     442       "addq $8, %rsp\n"
     443       "call *%r13\n"		/* Call the handler function.  */
     444       /* The word at the top of stack is &__sigreturn; following are a dummy
     445          word to fill the slot for the address for __sigreturn to return to,
     446          and a copy of SCP for __sigreturn's argument.  Load the SCP as for a
     447          call, and "return" to calling __sigreturn (SCP); this call never
     448          returns.  */
     449       "movq 16(%rsp), %rdi\n"
     450       "ret");
     451  #else
     452  asm ("rpc_wait_trampoline:\n");
     453    /* This is the entry point when we have an RPC reply message to receive
     454       before running the handler.  The MACH_MSG_SEND bit has already been
     455       cleared in the OPTION argument on our stack.  The interrupted user
     456       stack pointer has not been changed, so the system call can find its
     457       arguments; the signal stack pointer is in %ebx.  For our convenience,
     458       %ecx points to the sc_eax member of the sigcontext.  */
     459  asm (/* Retry the interrupted mach_msg system call.  */
     460       "movl $-25, %eax\n"	/* mach_msg_trap */
     461       "lcall $7, $0\n"
     462       /* When the sigcontext was saved, %eax was MACH_RCV_INTERRUPTED.  But
     463  	now the message receive has completed and the original caller of
     464  	the RPC (i.e. the code running when the signal arrived) needs to
     465  	see the final return value of the message receive in %eax.  So
     466  	store the new %eax value into the sc_eax member of the sigcontext
     467  	(whose address is in %ecx to make this code simpler).  */
     468       "movl %eax, (%ecx)\n"
     469       /* Switch to the signal stack.  */
     470       "movl %ebx, %esp\n");
     471  
     472   asm ("trampoline:\n");
     473    /* Entry point for running the handler normally.  The arguments to the
     474       handler function are already on the top of the stack:
     475  
     476         0(%esp)	SIGNO
     477         4(%esp)	SIGCODE
     478         8(%esp)	SCP
     479       */
     480  asm ("call *%edx\n"		/* Call the handler function.  */
     481       "addl $12, %esp\n"		/* Pop its args.  */
     482       /* The word at the top of stack is &__sigreturn; following are a dummy
     483  	word to fill the slot for the address for __sigreturn to return to,
     484  	and a copy of SCP for __sigreturn's argument.  "Return" to calling
     485  	__sigreturn (SCP); this call never returns.  */
     486       "ret");
     487  #endif
     488  
     489  asm ("firewall:\n"
     490       "hlt");