The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/amd64/ia32/ia32_signal.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2003 Peter Wemm
    3  * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
    4  * All rights reserved.
    5  *
    6  * This code is derived from software contributed to Berkeley by
    7  * William Jolitz.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 4. Neither the name of the University nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD: releng/8.4/sys/amd64/ia32/ia32_signal.c 237009 2012-06-13 15:25:52Z jhb $");
   36 
   37 #include "opt_compat.h"
   38 
   39 #include <sys/param.h>
   40 #include <sys/exec.h>
   41 #include <sys/fcntl.h>
   42 #include <sys/imgact.h>
   43 #include <sys/kernel.h>
   44 #include <sys/lock.h>
   45 #include <sys/malloc.h>
   46 #include <sys/mutex.h>
   47 #include <sys/mman.h>
   48 #include <sys/namei.h>
   49 #include <sys/pioctl.h>
   50 #include <sys/proc.h>
   51 #include <sys/procfs.h>
   52 #include <sys/resourcevar.h>
   53 #include <sys/systm.h>
   54 #include <sys/signalvar.h>
   55 #include <sys/stat.h>
   56 #include <sys/sx.h>
   57 #include <sys/syscall.h>
   58 #include <sys/syscallsubr.h>
   59 #include <sys/sysctl.h>
   60 #include <sys/sysent.h>
   61 #include <sys/vnode.h>
   62 
   63 #include <vm/vm.h>
   64 #include <vm/vm_kern.h>
   65 #include <vm/vm_param.h>
   66 #include <vm/pmap.h>
   67 #include <vm/vm_map.h>
   68 #include <vm/vm_object.h>
   69 #include <vm/vm_extern.h>
   70 
   71 #include <compat/freebsd32/freebsd32_signal.h>
   72 #include <compat/freebsd32/freebsd32_util.h>
   73 #include <compat/freebsd32/freebsd32_proto.h>
   74 #include <compat/freebsd32/freebsd32.h>
   75 #include <compat/ia32/ia32_signal.h>
   76 #include <machine/psl.h>
   77 #include <machine/segments.h>
   78 #include <machine/specialreg.h>
   79 #include <machine/frame.h>
   80 #include <machine/md_var.h>
   81 #include <machine/pcb.h>
   82 #include <machine/cpufunc.h>
   83 
   84 #ifdef COMPAT_FREEBSD4
   85 static void freebsd4_ia32_sendsig(sig_t, ksiginfo_t *, sigset_t *);
   86 #endif
   87 
   88 #define CS_SECURE(cs)           (ISPL(cs) == SEL_UPL)
   89 #define EFL_SECURE(ef, oef)     ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
   90 
   91 static void
   92 ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp,
   93     char *xfpusave, size_t xfpusave_len)
   94 {
   95         size_t max_len, len;
   96 
   97         /*
   98          * XXX Format of 64bit and 32bit FXSAVE areas differs. FXSAVE
   99          * in 32bit mode saves %cs and %ds, while on 64bit it saves
  100          * 64bit instruction and data pointers. Ignore the difference
  101          * for now, it should be irrelevant for most applications.
  102          */
  103         mcp->mc_ownedfp = fpugetregs(td);
  104         bcopy(get_pcb_user_save_td(td), &mcp->mc_fpstate,
  105             sizeof(mcp->mc_fpstate));
  106         mcp->mc_fpformat = fpuformat();
  107         if (!use_xsave || xfpusave_len == 0)
  108                 return;
  109         max_len = cpu_max_ext_state_size - sizeof(struct savefpu);
  110         len = xfpusave_len;
  111         if (len > max_len) {
  112                 len = max_len;
  113                 bzero(xfpusave + max_len, len - max_len);
  114         }
  115         mcp->mc_flags |= _MC_HASFPXSTATE;
  116         mcp->mc_xfpustate_len = len;
  117         bcopy(get_pcb_user_save_td(td) + 1, xfpusave, len);
  118 }
  119 
  120 static int
  121 ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp,
  122     char *xfpustate, size_t xfpustate_len)
  123 {
  124         int error;
  125 
  126         if (mcp->mc_fpformat == _MC_FPFMT_NODEV)
  127                 return (0);
  128         else if (mcp->mc_fpformat != _MC_FPFMT_XMM)
  129                 return (EINVAL);
  130         else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) {
  131                 /* We don't care what state is left in the FPU or PCB. */
  132                 fpstate_drop(td);
  133                 error = 0;
  134         } else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
  135             mcp->mc_ownedfp == _MC_FPOWNED_PCB) {
  136                 error = fpusetregs(td, (struct savefpu *)&mcp->mc_fpstate,
  137                     xfpustate, xfpustate_len);
  138         } else
  139                 return (EINVAL);
  140         return (error);
  141 }
  142 
  143 /*
  144  * Get machine context.
  145  */
  146 static int
  147 ia32_get_mcontext(struct thread *td, struct ia32_mcontext *mcp, int flags)
  148 {
  149         struct pcb *pcb;
  150         struct trapframe *tp;
  151 
  152         pcb = td->td_pcb;
  153         tp = td->td_frame;
  154 
  155         PROC_LOCK(curthread->td_proc);
  156         mcp->mc_onstack = sigonstack(tp->tf_rsp);
  157         PROC_UNLOCK(curthread->td_proc);
  158         /* Entry into kernel always sets TF_HASSEGS */
  159         mcp->mc_gs = tp->tf_gs;
  160         mcp->mc_fs = tp->tf_fs;
  161         mcp->mc_es = tp->tf_es;
  162         mcp->mc_ds = tp->tf_ds;
  163         mcp->mc_edi = tp->tf_rdi;
  164         mcp->mc_esi = tp->tf_rsi;
  165         mcp->mc_ebp = tp->tf_rbp;
  166         mcp->mc_isp = tp->tf_rsp;
  167         mcp->mc_eflags = tp->tf_rflags;
  168         if (flags & GET_MC_CLEAR_RET) {
  169                 mcp->mc_eax = 0;
  170                 mcp->mc_edx = 0;
  171                 mcp->mc_eflags &= ~PSL_C;
  172         } else {
  173                 mcp->mc_eax = tp->tf_rax;
  174                 mcp->mc_edx = tp->tf_rdx;
  175         }
  176         mcp->mc_ebx = tp->tf_rbx;
  177         mcp->mc_ecx = tp->tf_rcx;
  178         mcp->mc_eip = tp->tf_rip;
  179         mcp->mc_cs = tp->tf_cs;
  180         mcp->mc_esp = tp->tf_rsp;
  181         mcp->mc_ss = tp->tf_ss;
  182         mcp->mc_len = sizeof(*mcp);
  183         mcp->mc_flags = tp->tf_flags;
  184         ia32_get_fpcontext(td, mcp, NULL, 0);
  185         mcp->mc_fsbase = pcb->pcb_fsbase;
  186         mcp->mc_gsbase = pcb->pcb_gsbase;
  187         mcp->mc_xfpustate = 0;
  188         mcp->mc_xfpustate_len = 0;
  189         bzero(mcp->mc_spare2, sizeof(mcp->mc_spare2));
  190         set_pcb_flags(pcb, PCB_FULL_IRET);
  191         return (0);
  192 }
  193 
  194 /*
  195  * Set machine context.
  196  *
  197  * However, we don't set any but the user modifiable flags, and we won't
  198  * touch the cs selector.
  199  */
  200 static int
  201 ia32_set_mcontext(struct thread *td, const struct ia32_mcontext *mcp)
  202 {
  203         struct trapframe *tp;
  204         char *xfpustate;
  205         long rflags;
  206         int ret;
  207 
  208         tp = td->td_frame;
  209         if (mcp->mc_len != sizeof(*mcp))
  210                 return (EINVAL);
  211         rflags = (mcp->mc_eflags & PSL_USERCHANGE) |
  212             (tp->tf_rflags & ~PSL_USERCHANGE);
  213         if (mcp->mc_flags & _MC_IA32_HASFPXSTATE) {
  214                 if (mcp->mc_xfpustate_len > cpu_max_ext_state_size -
  215                     sizeof(struct savefpu))
  216                         return (EINVAL);
  217                 xfpustate = __builtin_alloca(mcp->mc_xfpustate_len);
  218                 ret = copyin(PTRIN(mcp->mc_xfpustate), xfpustate,
  219                     mcp->mc_xfpustate_len);
  220                 if (ret != 0)
  221                         return (ret);
  222         } else
  223                 xfpustate = NULL;
  224         ret = ia32_set_fpcontext(td, mcp, xfpustate, mcp->mc_xfpustate_len);
  225         if (ret != 0)
  226                 return (ret);
  227         tp->tf_gs = mcp->mc_gs;
  228         tp->tf_fs = mcp->mc_fs;
  229         tp->tf_es = mcp->mc_es;
  230         tp->tf_ds = mcp->mc_ds;
  231         tp->tf_flags = TF_HASSEGS;
  232         tp->tf_rdi = mcp->mc_edi;
  233         tp->tf_rsi = mcp->mc_esi;
  234         tp->tf_rbp = mcp->mc_ebp;
  235         tp->tf_rbx = mcp->mc_ebx;
  236         tp->tf_rdx = mcp->mc_edx;
  237         tp->tf_rcx = mcp->mc_ecx;
  238         tp->tf_rax = mcp->mc_eax;
  239         /* trapno, err */
  240         tp->tf_rip = mcp->mc_eip;
  241         tp->tf_rflags = rflags;
  242         tp->tf_rsp = mcp->mc_esp;
  243         tp->tf_ss = mcp->mc_ss;
  244         set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
  245         return (0);
  246 }
  247 
  248 /*
  249  * The first two fields of a ucontext_t are the signal mask and
  250  * the machine context.  The next field is uc_link; we want to
  251  * avoid destroying the link when copying out contexts.
  252  */
  253 #define UC_COPY_SIZE    offsetof(struct ia32_ucontext, uc_link)
  254 
  255 int
  256 freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap)
  257 {
  258         struct ia32_ucontext uc;
  259         int ret;
  260 
  261         if (uap->ucp == NULL)
  262                 ret = EINVAL;
  263         else {
  264                 ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
  265                 PROC_LOCK(td->td_proc);
  266                 uc.uc_sigmask = td->td_sigmask;
  267                 PROC_UNLOCK(td->td_proc);
  268                 bzero(&uc.__spare__, sizeof(uc.__spare__));
  269                 ret = copyout(&uc, uap->ucp, UC_COPY_SIZE);
  270         }
  271         return (ret);
  272 }
  273 
  274 int
  275 freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap)
  276 {
  277         struct ia32_ucontext uc;
  278         int ret;        
  279 
  280         if (uap->ucp == NULL)
  281                 ret = EINVAL;
  282         else {
  283                 ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
  284                 if (ret == 0) {
  285                         ret = ia32_set_mcontext(td, &uc.uc_mcontext);
  286                         if (ret == 0) {
  287                                 kern_sigprocmask(td, SIG_SETMASK,
  288                                     &uc.uc_sigmask, NULL, 0);
  289                         }
  290                 }
  291         }
  292         return (ret == 0 ? EJUSTRETURN : ret);
  293 }
  294 
  295 int
  296 freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap)
  297 {
  298         struct ia32_ucontext uc;
  299         int ret;        
  300 
  301         if (uap->oucp == NULL || uap->ucp == NULL)
  302                 ret = EINVAL;
  303         else {
  304                 ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
  305                 PROC_LOCK(td->td_proc);
  306                 uc.uc_sigmask = td->td_sigmask;
  307                 PROC_UNLOCK(td->td_proc);
  308                 ret = copyout(&uc, uap->oucp, UC_COPY_SIZE);
  309                 if (ret == 0) {
  310                         ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
  311                         if (ret == 0) {
  312                                 ret = ia32_set_mcontext(td, &uc.uc_mcontext);
  313                                 if (ret == 0) {
  314                                         kern_sigprocmask(td, SIG_SETMASK,
  315                                             &uc.uc_sigmask, NULL, 0);
  316                                 }
  317                         }
  318                 }
  319         }
  320         return (ret == 0 ? EJUSTRETURN : ret);
  321 }
  322 
  323 /*
  324  * Send an interrupt to process.
  325  *
  326  * Stack is set up to allow sigcode stored
  327  * at top to call routine, followed by kcall
  328  * to sigreturn routine below.  After sigreturn
  329  * resets the signal mask, the stack, and the
  330  * frame pointer, it returns to the user
  331  * specified pc, psl.
  332  */
  333 #ifdef COMPAT_FREEBSD4
  334 static void
  335 freebsd4_ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
  336 {
  337         struct ia32_sigframe4 sf, *sfp;
  338         struct siginfo32 siginfo;
  339         struct proc *p;
  340         struct thread *td;
  341         struct sigacts *psp;
  342         struct trapframe *regs;
  343         int oonstack;
  344         int sig;
  345 
  346         td = curthread;
  347         p = td->td_proc;
  348         siginfo_to_siginfo32(&ksi->ksi_info, &siginfo);
  349 
  350         PROC_LOCK_ASSERT(p, MA_OWNED);
  351         sig = siginfo.si_signo;
  352         psp = p->p_sigacts;
  353         mtx_assert(&psp->ps_mtx, MA_OWNED);
  354         regs = td->td_frame;
  355         oonstack = sigonstack(regs->tf_rsp);
  356 
  357         /* Save user context. */
  358         bzero(&sf, sizeof(sf));
  359         sf.sf_uc.uc_sigmask = *mask;
  360         sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp;
  361         sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size;
  362         sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
  363             ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
  364         sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
  365         sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi;
  366         sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi;
  367         sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp;
  368         sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */
  369         sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx;
  370         sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx;
  371         sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx;
  372         sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax;
  373         sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno;
  374         sf.sf_uc.uc_mcontext.mc_err = regs->tf_err;
  375         sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip;
  376         sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs;
  377         sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags;
  378         sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp;
  379         sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss;
  380         sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds;
  381         sf.sf_uc.uc_mcontext.mc_es = regs->tf_es;
  382         sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs;
  383         sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs;
  384         bzero(sf.sf_uc.uc_mcontext.mc_fpregs,
  385             sizeof(sf.sf_uc.uc_mcontext.mc_fpregs));
  386         bzero(sf.sf_uc.uc_mcontext.__spare__,
  387             sizeof(sf.sf_uc.uc_mcontext.__spare__));
  388         bzero(sf.sf_uc.__spare__, sizeof(sf.sf_uc.__spare__));
  389 
  390         /* Allocate space for the signal handler context. */
  391         if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
  392             SIGISMEMBER(psp->ps_sigonstack, sig)) {
  393                 sfp = (struct ia32_sigframe4 *)(td->td_sigstk.ss_sp +
  394                     td->td_sigstk.ss_size - sizeof(sf));
  395         } else
  396                 sfp = (struct ia32_sigframe4 *)regs->tf_rsp - 1;
  397         PROC_UNLOCK(p);
  398 
  399         /* Translate the signal if appropriate. */
  400         if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
  401                 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
  402 
  403         /* Build the argument list for the signal handler. */
  404         sf.sf_signum = sig;
  405         sf.sf_ucontext = (register_t)&sfp->sf_uc;
  406         bzero(&sf.sf_si, sizeof(sf.sf_si));
  407         if (SIGISMEMBER(psp->ps_siginfo, sig)) {
  408                 /* Signal handler installed with SA_SIGINFO. */
  409                 sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si;
  410                 sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
  411 
  412                 /* Fill in POSIX parts */
  413                 sf.sf_si = siginfo;
  414                 sf.sf_si.si_signo = sig;
  415         } else {
  416                 /* Old FreeBSD-style arguments. */
  417                 sf.sf_siginfo = siginfo.si_code;
  418                 sf.sf_addr = (u_int32_t)siginfo.si_addr;
  419                 sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
  420         }
  421         mtx_unlock(&psp->ps_mtx);
  422 
  423         /*
  424          * Copy the sigframe out to the user's stack.
  425          */
  426         if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
  427 #ifdef DEBUG
  428                 printf("process %ld has trashed its stack\n", (long)p->p_pid);
  429 #endif
  430                 PROC_LOCK(p);
  431                 sigexit(td, SIGILL);
  432         }
  433 
  434         regs->tf_rsp = (uintptr_t)sfp;
  435         regs->tf_rip = p->p_sysent->sv_psstrings - sz_freebsd4_ia32_sigcode;
  436         regs->tf_rflags &= ~(PSL_T | PSL_D);
  437         regs->tf_cs = _ucode32sel;
  438         regs->tf_ss = _udatasel;
  439         regs->tf_ds = _udatasel;
  440         regs->tf_es = _udatasel;
  441         set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
  442         /* leave user %fs and %gs untouched */
  443         PROC_LOCK(p);
  444         mtx_lock(&psp->ps_mtx);
  445 }
  446 #endif  /* COMPAT_FREEBSD4 */
  447 
  448 void
  449 ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
  450 {
  451         struct ia32_sigframe sf, *sfp;
  452         struct siginfo32 siginfo;
  453         struct proc *p;
  454         struct thread *td;
  455         struct sigacts *psp;
  456         char *sp;
  457         struct trapframe *regs;
  458         char *xfpusave;
  459         size_t xfpusave_len;
  460         int oonstack;
  461         int sig;
  462 
  463         siginfo_to_siginfo32(&ksi->ksi_info, &siginfo);
  464         td = curthread;
  465         p = td->td_proc;
  466         PROC_LOCK_ASSERT(p, MA_OWNED);
  467         sig = siginfo.si_signo;
  468         psp = p->p_sigacts;
  469 #ifdef COMPAT_FREEBSD4
  470         if (SIGISMEMBER(psp->ps_freebsd4, sig)) {
  471                 freebsd4_ia32_sendsig(catcher, ksi, mask);
  472                 return;
  473         }
  474 #endif
  475         mtx_assert(&psp->ps_mtx, MA_OWNED);
  476         regs = td->td_frame;
  477         oonstack = sigonstack(regs->tf_rsp);
  478 
  479         if (cpu_max_ext_state_size > sizeof(struct savefpu) && use_xsave) {
  480                 xfpusave_len = cpu_max_ext_state_size - sizeof(struct savefpu);
  481                 xfpusave = __builtin_alloca(xfpusave_len);
  482         } else {
  483                 xfpusave_len = 0;
  484                 xfpusave = NULL;
  485         }
  486 
  487         /* Save user context. */
  488         bzero(&sf, sizeof(sf));
  489         sf.sf_uc.uc_sigmask = *mask;
  490         sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp;
  491         sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size;
  492         sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
  493             ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
  494         sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
  495         sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi;
  496         sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi;
  497         sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp;
  498         sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */
  499         sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx;
  500         sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx;
  501         sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx;
  502         sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax;
  503         sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno;
  504         sf.sf_uc.uc_mcontext.mc_err = regs->tf_err;
  505         sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip;
  506         sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs;
  507         sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags;
  508         sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp;
  509         sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss;
  510         sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds;
  511         sf.sf_uc.uc_mcontext.mc_es = regs->tf_es;
  512         sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs;
  513         sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs;
  514         sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */
  515         ia32_get_fpcontext(td, &sf.sf_uc.uc_mcontext, xfpusave, xfpusave_len);
  516         fpstate_drop(td);
  517         sf.sf_uc.uc_mcontext.mc_fsbase = td->td_pcb->pcb_fsbase;
  518         sf.sf_uc.uc_mcontext.mc_gsbase = td->td_pcb->pcb_gsbase;
  519         bzero(sf.sf_uc.__spare__, sizeof(sf.sf_uc.__spare__));
  520 
  521         /* Allocate space for the signal handler context. */
  522         if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
  523             SIGISMEMBER(psp->ps_sigonstack, sig))
  524                 sp = td->td_sigstk.ss_sp + td->td_sigstk.ss_size;
  525         else
  526                 sp = (char *)regs->tf_rsp;
  527         if (xfpusave != NULL) {
  528                 sp -= xfpusave_len;
  529                 sp = (char *)((unsigned long)sp & ~0x3Ful);
  530                 sf.sf_uc.uc_mcontext.mc_xfpustate = (register_t)sp;
  531         }
  532         sp -= sizeof(sf);
  533         /* Align to 16 bytes. */
  534         sfp = (struct ia32_sigframe *)((uintptr_t)sp & ~0xF);
  535         PROC_UNLOCK(p);
  536 
  537         /* Translate the signal if appropriate. */
  538         if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
  539                 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
  540 
  541         /* Build the argument list for the signal handler. */
  542         sf.sf_signum = sig;
  543         sf.sf_ucontext = (register_t)&sfp->sf_uc;
  544         bzero(&sf.sf_si, sizeof(sf.sf_si));
  545         if (SIGISMEMBER(psp->ps_siginfo, sig)) {
  546                 /* Signal handler installed with SA_SIGINFO. */
  547                 sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si;
  548                 sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
  549 
  550                 /* Fill in POSIX parts */
  551                 sf.sf_si = siginfo;
  552                 sf.sf_si.si_signo = sig;
  553         } else {
  554                 /* Old FreeBSD-style arguments. */
  555                 sf.sf_siginfo = siginfo.si_code;
  556                 sf.sf_addr = (u_int32_t)siginfo.si_addr;
  557                 sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
  558         }
  559         mtx_unlock(&psp->ps_mtx);
  560 
  561         /*
  562          * Copy the sigframe out to the user's stack.
  563          */
  564         if (copyout(&sf, sfp, sizeof(*sfp)) != 0 ||
  565             (xfpusave != NULL && copyout(xfpusave,
  566             PTRIN(sf.sf_uc.uc_mcontext.mc_xfpustate), xfpusave_len)
  567             != 0)) {
  568 #ifdef DEBUG
  569                 printf("process %ld has trashed its stack\n", (long)p->p_pid);
  570 #endif
  571                 PROC_LOCK(p);
  572                 sigexit(td, SIGILL);
  573         }
  574 
  575         regs->tf_rsp = (uintptr_t)sfp;
  576         regs->tf_rip = p->p_sysent->sv_psstrings - *(p->p_sysent->sv_szsigcode);
  577         regs->tf_rflags &= ~(PSL_T | PSL_D);
  578         regs->tf_cs = _ucode32sel;
  579         regs->tf_ss = _udatasel;
  580         regs->tf_ds = _udatasel;
  581         regs->tf_es = _udatasel;
  582         set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
  583         /* XXXKIB leave user %fs and %gs untouched */
  584         PROC_LOCK(p);
  585         mtx_lock(&psp->ps_mtx);
  586 }
  587 
  588 /*
  589  * System call to cleanup state after a signal
  590  * has been taken.  Reset signal mask and
  591  * stack state from context left by sendsig (above).
  592  * Return to previous pc and psl as specified by
  593  * context left by sendsig. Check carefully to
  594  * make sure that the user has not modified the
  595  * state to gain improper privileges.
  596  */
  597 #ifdef COMPAT_FREEBSD4
  598 /*
  599  * MPSAFE
  600  */
  601 int
  602 freebsd4_freebsd32_sigreturn(td, uap)
  603         struct thread *td;
  604         struct freebsd4_freebsd32_sigreturn_args /* {
  605                 const struct freebsd4_freebsd32_ucontext *sigcntxp;
  606         } */ *uap;
  607 {
  608         struct ia32_ucontext4 uc;
  609         struct trapframe *regs;
  610         struct ia32_ucontext4 *ucp;
  611         int cs, eflags, error;
  612         ksiginfo_t ksi;
  613 
  614         error = copyin(uap->sigcntxp, &uc, sizeof(uc));
  615         if (error != 0)
  616                 return (error);
  617         ucp = &uc;
  618         regs = td->td_frame;
  619         eflags = ucp->uc_mcontext.mc_eflags;
  620         /*
  621          * Don't allow users to change privileged or reserved flags.
  622          */
  623         /*
  624          * XXX do allow users to change the privileged flag PSL_RF.
  625          * The cpu sets PSL_RF in tf_eflags for faults.  Debuggers
  626          * should sometimes set it there too.  tf_eflags is kept in
  627          * the signal context during signal handling and there is no
  628          * other place to remember it, so the PSL_RF bit may be
  629          * corrupted by the signal handler without us knowing.
  630          * Corruption of the PSL_RF bit at worst causes one more or
  631          * one less debugger trap, so allowing it is fairly harmless.
  632          */
  633         if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) {
  634                 uprintf("pid %d (%s): freebsd4_freebsd32_sigreturn eflags = 0x%x\n",
  635                     td->td_proc->p_pid, td->td_name, eflags);
  636                 return (EINVAL);
  637         }
  638 
  639         /*
  640          * Don't allow users to load a valid privileged %cs.  Let the
  641          * hardware check for invalid selectors, excess privilege in
  642          * other selectors, invalid %eip's and invalid %esp's.
  643          */
  644         cs = ucp->uc_mcontext.mc_cs;
  645         if (!CS_SECURE(cs)) {
  646                 uprintf("pid %d (%s): freebsd4_sigreturn cs = 0x%x\n",
  647                     td->td_proc->p_pid, td->td_name, cs);
  648                 ksiginfo_init_trap(&ksi);
  649                 ksi.ksi_signo = SIGBUS;
  650                 ksi.ksi_code = BUS_OBJERR;
  651                 ksi.ksi_trapno = T_PROTFLT;
  652                 ksi.ksi_addr = (void *)regs->tf_rip;
  653                 trapsignal(td, &ksi);
  654                 return (EINVAL);
  655         }
  656 
  657         regs->tf_rdi = ucp->uc_mcontext.mc_edi;
  658         regs->tf_rsi = ucp->uc_mcontext.mc_esi;
  659         regs->tf_rbp = ucp->uc_mcontext.mc_ebp;
  660         regs->tf_rbx = ucp->uc_mcontext.mc_ebx;
  661         regs->tf_rdx = ucp->uc_mcontext.mc_edx;
  662         regs->tf_rcx = ucp->uc_mcontext.mc_ecx;
  663         regs->tf_rax = ucp->uc_mcontext.mc_eax;
  664         regs->tf_trapno = ucp->uc_mcontext.mc_trapno;
  665         regs->tf_err = ucp->uc_mcontext.mc_err;
  666         regs->tf_rip = ucp->uc_mcontext.mc_eip;
  667         regs->tf_cs = cs;
  668         regs->tf_rflags = ucp->uc_mcontext.mc_eflags;
  669         regs->tf_rsp = ucp->uc_mcontext.mc_esp;
  670         regs->tf_ss = ucp->uc_mcontext.mc_ss;
  671         regs->tf_ds = ucp->uc_mcontext.mc_ds;
  672         regs->tf_es = ucp->uc_mcontext.mc_es;
  673         regs->tf_fs = ucp->uc_mcontext.mc_fs;
  674         regs->tf_gs = ucp->uc_mcontext.mc_gs;
  675 
  676         kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0);
  677         set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
  678         return (EJUSTRETURN);
  679 }
  680 #endif  /* COMPAT_FREEBSD4 */
  681 
  682 /*
  683  * MPSAFE
  684  */
  685 int
  686 freebsd32_sigreturn(td, uap)
  687         struct thread *td;
  688         struct freebsd32_sigreturn_args /* {
  689                 const struct freebsd32_ucontext *sigcntxp;
  690         } */ *uap;
  691 {
  692         struct ia32_ucontext uc;
  693         struct trapframe *regs;
  694         struct ia32_ucontext *ucp;
  695         char *xfpustate;
  696         size_t xfpustate_len;
  697         int cs, eflags, error, ret;
  698         ksiginfo_t ksi;
  699 
  700         error = copyin(uap->sigcntxp, &uc, sizeof(uc));
  701         if (error != 0)
  702                 return (error);
  703         ucp = &uc;
  704         regs = td->td_frame;
  705         eflags = ucp->uc_mcontext.mc_eflags;
  706         /*
  707          * Don't allow users to change privileged or reserved flags.
  708          */
  709         /*
  710          * XXX do allow users to change the privileged flag PSL_RF.
  711          * The cpu sets PSL_RF in tf_eflags for faults.  Debuggers
  712          * should sometimes set it there too.  tf_eflags is kept in
  713          * the signal context during signal handling and there is no
  714          * other place to remember it, so the PSL_RF bit may be
  715          * corrupted by the signal handler without us knowing.
  716          * Corruption of the PSL_RF bit at worst causes one more or
  717          * one less debugger trap, so allowing it is fairly harmless.
  718          */
  719         if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) {
  720                 uprintf("pid %d (%s): freebsd32_sigreturn eflags = 0x%x\n",
  721                     td->td_proc->p_pid, td->td_name, eflags);
  722                 return (EINVAL);
  723         }
  724 
  725         /*
  726          * Don't allow users to load a valid privileged %cs.  Let the
  727          * hardware check for invalid selectors, excess privilege in
  728          * other selectors, invalid %eip's and invalid %esp's.
  729          */
  730         cs = ucp->uc_mcontext.mc_cs;
  731         if (!CS_SECURE(cs)) {
  732                 uprintf("pid %d (%s): sigreturn cs = 0x%x\n",
  733                     td->td_proc->p_pid, td->td_name, cs);
  734                 ksiginfo_init_trap(&ksi);
  735                 ksi.ksi_signo = SIGBUS;
  736                 ksi.ksi_code = BUS_OBJERR;
  737                 ksi.ksi_trapno = T_PROTFLT;
  738                 ksi.ksi_addr = (void *)regs->tf_rip;
  739                 trapsignal(td, &ksi);
  740                 return (EINVAL);
  741         }
  742 
  743         if ((ucp->uc_mcontext.mc_flags & _MC_HASFPXSTATE) != 0) {
  744                 xfpustate_len = uc.uc_mcontext.mc_xfpustate_len;
  745                 if (xfpustate_len > cpu_max_ext_state_size -
  746                     sizeof(struct savefpu)) {
  747                         uprintf("pid %d (%s): sigreturn xfpusave_len = 0x%zx\n",
  748                             td->td_proc->p_pid, td->td_name, xfpustate_len);
  749                         return (EINVAL);
  750                 }
  751                 xfpustate = __builtin_alloca(xfpustate_len);
  752                 error = copyin(PTRIN(ucp->uc_mcontext.mc_xfpustate),
  753                     xfpustate, xfpustate_len);
  754                 if (error != 0) {
  755                         uprintf(
  756         "pid %d (%s): sigreturn copying xfpustate failed\n",
  757                             td->td_proc->p_pid, td->td_name);
  758                         return (error);
  759                 }
  760         } else {
  761                 xfpustate = NULL;
  762                 xfpustate_len = 0;
  763         }
  764         ret = ia32_set_fpcontext(td, &ucp->uc_mcontext, xfpustate,
  765             xfpustate_len);
  766         if (ret != 0) {
  767                 uprintf("pid %d (%s): sigreturn set_fpcontext err %d\n",
  768                     td->td_proc->p_pid, td->td_name, ret);
  769                 return (ret);
  770         }
  771 
  772         regs->tf_rdi = ucp->uc_mcontext.mc_edi;
  773         regs->tf_rsi = ucp->uc_mcontext.mc_esi;
  774         regs->tf_rbp = ucp->uc_mcontext.mc_ebp;
  775         regs->tf_rbx = ucp->uc_mcontext.mc_ebx;
  776         regs->tf_rdx = ucp->uc_mcontext.mc_edx;
  777         regs->tf_rcx = ucp->uc_mcontext.mc_ecx;
  778         regs->tf_rax = ucp->uc_mcontext.mc_eax;
  779         regs->tf_trapno = ucp->uc_mcontext.mc_trapno;
  780         regs->tf_err = ucp->uc_mcontext.mc_err;
  781         regs->tf_rip = ucp->uc_mcontext.mc_eip;
  782         regs->tf_cs = cs;
  783         regs->tf_rflags = ucp->uc_mcontext.mc_eflags;
  784         regs->tf_rsp = ucp->uc_mcontext.mc_esp;
  785         regs->tf_ss = ucp->uc_mcontext.mc_ss;
  786         regs->tf_ds = ucp->uc_mcontext.mc_ds;
  787         regs->tf_es = ucp->uc_mcontext.mc_es;
  788         regs->tf_fs = ucp->uc_mcontext.mc_fs;
  789         regs->tf_gs = ucp->uc_mcontext.mc_gs;
  790         regs->tf_flags = TF_HASSEGS;
  791 
  792         kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0);
  793         set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
  794         return (EJUSTRETURN);
  795 }
  796 
  797 /*
  798  * Clear registers on exec
  799  */
  800 void
  801 ia32_setregs(td, entry, stack, ps_strings)
  802         struct thread *td;
  803         u_long entry;
  804         u_long stack;
  805         u_long ps_strings;
  806 {
  807         struct trapframe *regs = td->td_frame;
  808         struct pcb *pcb = td->td_pcb;
  809         
  810         mtx_lock(&dt_lock);
  811         if (td->td_proc->p_md.md_ldt != NULL)
  812                 user_ldt_free(td);
  813         else
  814                 mtx_unlock(&dt_lock);
  815 
  816         pcb->pcb_fsbase = 0;
  817         pcb->pcb_gsbase = 0;
  818         pcb->pcb_initial_fpucw = __INITIAL_FPUCW_I386__;
  819 
  820         bzero((char *)regs, sizeof(struct trapframe));
  821         regs->tf_rip = entry;
  822         regs->tf_rsp = stack;
  823         regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T);
  824         regs->tf_ss = _udatasel;
  825         regs->tf_cs = _ucode32sel;
  826         regs->tf_rbx = ps_strings;
  827         regs->tf_ds = _udatasel;
  828         regs->tf_es = _udatasel;
  829         regs->tf_fs = _ufssel;
  830         regs->tf_gs = _ugssel;
  831         regs->tf_flags = TF_HASSEGS;
  832 
  833         fpstate_drop(td);
  834 
  835         /* Return via doreti so that we can change to a different %cs */
  836         set_pcb_flags(pcb, PCB_32BIT | PCB_FULL_IRET);
  837         clear_pcb_flags(pcb, PCB_GS32BIT);
  838         td->td_retval[1] = 0;
  839 }

Cache object: 965df09611cbc6b058c02beb8375e6f4


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.