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/bsd/dev/i386/unix_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) 2000-2006 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
    5  * 
    6  * This file contains Original Code and/or Modifications of Original Code
    7  * as defined in and that are subject to the Apple Public Source License
    8  * Version 2.0 (the 'License'). You may not use this file except in
    9  * compliance with the License. The rights granted to you under the License
   10  * may not be used to create, or enable the creation or redistribution of,
   11  * unlawful or unlicensed copies of an Apple operating system, or to
   12  * circumvent, violate, or enable the circumvention or violation of, any
   13  * terms of an Apple operating system software license agreement.
   14  * 
   15  * Please obtain a copy of the License at
   16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
   17  * 
   18  * The Original Code and all software distributed under the License are
   19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   23  * Please see the License for the specific language governing rights and
   24  * limitations under the License.
   25  * 
   26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
   27  */
   28 /* 
   29  * Copyright (c) 1992 NeXT, Inc.
   30  *
   31  * HISTORY
   32  * 13 May 1992 ? at NeXT
   33  *      Created.
   34  */
   35 
   36 #include <mach/mach_types.h>
   37 #include <mach/exception.h>
   38 
   39 #include <kern/thread.h>
   40 
   41 #include <sys/systm.h>
   42 #include <sys/param.h>
   43 #include <sys/proc_internal.h>
   44 #include <sys/user.h>
   45 #include <sys/sysproto.h>
   46 #include <sys/sysent.h>
   47 #include <sys/ucontext.h>
   48 #include <sys/wait.h>
   49 #include <mach/thread_act.h>    /* for thread_abort_safely */
   50 #include <mach/thread_status.h> 
   51 #include <i386/machine_routines.h>
   52 
   53 #include <i386/eflags.h>
   54 #include <i386/psl.h>
   55 #include <i386/seg.h>
   56 
   57 #include <sys/kdebug.h>
   58 
   59 #include <sys/sdt.h>
   60 
   61 /* Forward: */
   62 extern boolean_t machine_exception(int, mach_exception_code_t, 
   63                 mach_exception_subcode_t, int *, mach_exception_subcode_t *);
   64 extern kern_return_t thread_getstatus(register thread_t act, int flavor,
   65                         thread_state_t tstate, mach_msg_type_number_t *count);
   66 extern kern_return_t thread_setstatus(thread_t thread, int flavor,
   67                         thread_state_t tstate, mach_msg_type_number_t count);
   68 
   69 /* Signal handler flavors supported */
   70 /* These defns should match the Libc implmn */
   71 #define UC_TRAD                 1
   72 #define UC_FLAVOR               30
   73 #define UC_SET_ALT_STACK        0x40000000
   74 #define UC_RESET_ALT_STACK      0x80000000
   75 
   76 #define C_32_STK_ALIGN          16
   77 #define C_64_STK_ALIGN          16
   78 #define C_64_REDZONE_LEN        128
   79 #define TRUNC_DOWN32(a,c)       ((((uint32_t)a)-(c)) & ((uint32_t)(-(c))))
   80 #define TRUNC_DOWN64(a,c)       ((((uint64_t)a)-(c)) & ((uint64_t)(-(c))))
   81 
   82 /*
   83  * Send an interrupt to process.
   84  *
   85  * Stack is set up to allow sigcode stored
   86  * in u. to call routine, followed by chmk
   87  * to sigreturn routine below.  After sigreturn
   88  * resets the signal mask, the stack, the frame 
   89  * pointer, and the argument pointer, it returns
   90  * to the user specified pc, psl.
   91  */
   92 struct sigframe32 {
   93         int               retaddr;
   94         sig_t             catcher;
   95         int               sigstyle;
   96         int               sig;
   97         siginfo_t       * sinfo;
   98         struct ucontext * uctx;
   99 };
  100 
  101 
  102 
  103 void
  104 sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused u_long code)
  105 {
  106         union {
  107             struct mcontext32   mctx32;
  108             struct mcontext64   mctx64;
  109         } mctx;
  110         user_addr_t     ua_sp;
  111         user_addr_t     ua_fp;
  112         user_addr_t     ua_cr2;
  113         user_addr_t     ua_sip;
  114         user_addr_t     ua_uctxp;
  115         user_addr_t     ua_mctxp;
  116         user_siginfo_t  sinfo64;
  117 
  118         struct sigacts *ps = p->p_sigacts;
  119         int oonstack, flavor; 
  120         void * state;
  121         mach_msg_type_number_t state_count;
  122 
  123         thread_t thread;
  124         struct uthread * ut;
  125         int stack_size = 0;
  126         int infostyle = UC_TRAD;
  127     
  128         thread = current_thread();
  129         ut = get_bsdthread_info(thread);
  130 
  131         if (p->p_sigacts->ps_siginfo & sigmask(sig))
  132                 infostyle = UC_FLAVOR;
  133 
  134         oonstack = ut->uu_sigstk.ss_flags & SA_ONSTACK;
  135 
  136         /*
  137          * init siginfo
  138          */
  139         proc_unlock(p);
  140 
  141         bzero((caddr_t)&sinfo64, sizeof(user_siginfo_t));
  142         sinfo64.si_signo = sig;
  143                 
  144 
  145         if (proc_is64bit(p)) {
  146                 x86_thread_state64_t    *tstate64;
  147                 struct user_ucontext64  uctx64;
  148 
  149                 flavor = x86_THREAD_STATE64;
  150                 state_count = x86_THREAD_STATE64_COUNT;
  151                 state = (void *)&mctx.mctx64.ss;
  152                 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
  153                         goto bad;
  154 
  155                 flavor = x86_FLOAT_STATE64;
  156                 state_count = x86_FLOAT_STATE64_COUNT;
  157                 state = (void *)&mctx.mctx64.fs;
  158                 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
  159                         goto bad;
  160 
  161                 flavor = x86_EXCEPTION_STATE64;
  162                 state_count = x86_EXCEPTION_STATE64_COUNT;
  163                 state = (void *)&mctx.mctx64.es;
  164                 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
  165                         goto bad;
  166 
  167                 tstate64 = &mctx.mctx64.ss;
  168 
  169                 /* figure out where our new stack lives */
  170                 if ((ut->uu_flag & UT_ALTSTACK) && !oonstack &&
  171                     (ps->ps_sigonstack & sigmask(sig))) {
  172                         ua_sp = ut->uu_sigstk.ss_sp;
  173                         stack_size = ut->uu_sigstk.ss_size;
  174                         ua_sp += stack_size;
  175                         ut->uu_sigstk.ss_flags |= SA_ONSTACK;
  176                 } else {
  177                         ua_sp = tstate64->rsp;
  178                 }
  179                 ua_cr2 = mctx.mctx64.es.faultvaddr;
  180 
  181                 /* The x86_64 ABI defines a 128-byte red zone. */
  182                 ua_sp -= C_64_REDZONE_LEN;
  183 
  184                 ua_sp -= sizeof (struct user_ucontext64);
  185                 ua_uctxp = ua_sp;                        // someone tramples the first word!
  186 
  187                 ua_sp -= sizeof (user_siginfo_t);
  188                 ua_sip = ua_sp;
  189 
  190                 ua_sp -= sizeof (struct mcontext64);
  191                 ua_mctxp = ua_sp;
  192 
  193                 /*
  194                  * Align the frame and stack pointers to 16 bytes for SSE.
  195                  * (Note that we use 'ua_fp' as the base of the stack going forward)
  196                  */
  197                 ua_fp = TRUNC_DOWN64(ua_sp, C_64_STK_ALIGN);
  198 
  199                 /*
  200                  * But we need to account for the return address so the alignment is
  201                  * truly "correct" at _sigtramp
  202                  */
  203                 ua_fp -= sizeof(user_addr_t);
  204 
  205                 /*
  206                  * Build the signal context to be used by sigreturn.
  207                  */
  208                 bzero(&uctx64, sizeof(uctx64));
  209 
  210                 uctx64.uc_onstack = oonstack;
  211                 uctx64.uc_sigmask = mask;
  212                 uctx64.uc_stack.ss_sp = ua_fp;
  213                 uctx64.uc_stack.ss_size = stack_size;
  214 
  215                 if (oonstack)
  216                         uctx64.uc_stack.ss_flags |= SS_ONSTACK; 
  217                 uctx64.uc_link = 0;
  218 
  219                 uctx64.uc_mcsize = sizeof(struct mcontext64);
  220                 uctx64.uc_mcontext64 = ua_mctxp;
  221                 
  222                 if (copyout((caddr_t)&uctx64, ua_uctxp, sizeof (uctx64))) 
  223                         goto bad;
  224 
  225                 if (copyout((caddr_t)&mctx.mctx64, ua_mctxp, sizeof (struct mcontext64))) 
  226                         goto bad;
  227 
  228                 sinfo64.pad[0]  = tstate64->rsp;
  229                 sinfo64.si_addr = tstate64->rip;
  230 
  231                 tstate64->rip = ps->ps_trampact[sig];
  232                 tstate64->rsp = ua_fp;
  233                 tstate64->rflags = get_eflags_exportmask();
  234                 /*
  235                  * JOE - might not need to set these
  236                  */
  237                 tstate64->cs = USER64_CS;
  238                 tstate64->fs = NULL_SEG;
  239                 tstate64->gs = USER_CTHREAD;
  240 
  241                 /* 
  242                  * Build the argument list for the signal handler.
  243                  * Handler should call sigreturn to get out of it
  244                  */
  245                 tstate64->rdi = ua_catcher;
  246                 tstate64->rsi = infostyle;
  247                 tstate64->rdx = sig;
  248                 tstate64->rcx = ua_sip;
  249                 tstate64->r8  = ua_uctxp;
  250 
  251         } else {
  252                 x86_thread_state32_t    *tstate32;
  253                 struct ucontext         uctx32;
  254                 struct sigframe32       frame32;
  255 
  256                 flavor = x86_THREAD_STATE32;
  257                 state_count = x86_THREAD_STATE32_COUNT;
  258                 state = (void *)&mctx.mctx32.ss;
  259                 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
  260                         goto bad;
  261 
  262                 flavor = x86_FLOAT_STATE32;
  263                 state_count = x86_FLOAT_STATE32_COUNT;
  264                 state = (void *)&mctx.mctx32.fs;
  265                 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
  266                         goto bad;
  267 
  268                 flavor = x86_EXCEPTION_STATE32;
  269                 state_count = x86_EXCEPTION_STATE32_COUNT;
  270                 state = (void *)&mctx.mctx32.es;
  271                 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
  272                         goto bad;
  273 
  274                 tstate32 = &mctx.mctx32.ss;
  275 
  276                 /* figure out where our new stack lives */
  277                 if ((ut->uu_flag & UT_ALTSTACK) && !oonstack &&
  278                     (ps->ps_sigonstack & sigmask(sig))) {
  279                         ua_sp = ut->uu_sigstk.ss_sp;
  280                         stack_size = ut->uu_sigstk.ss_size;
  281                         ua_sp += stack_size;
  282                         ut->uu_sigstk.ss_flags |= SA_ONSTACK;
  283                 } else {
  284                         ua_sp = tstate32->esp;
  285                 }
  286                 ua_cr2 = mctx.mctx32.es.faultvaddr;
  287 
  288                 ua_sp -= sizeof (struct ucontext);
  289                 ua_uctxp = ua_sp;                        // someone tramples the first word!
  290 
  291                 ua_sp -= sizeof (siginfo_t);
  292                 ua_sip = ua_sp;
  293 
  294                 ua_sp -= sizeof (struct mcontext32);
  295                 ua_mctxp = ua_sp;
  296 
  297                 ua_sp -= sizeof (struct sigframe32);
  298                 ua_fp = ua_sp;
  299 
  300                 /*
  301                  * Align the frame and stack pointers to 16 bytes for SSE.
  302                  * (Note that we use 'fp' as the base of the stack going forward)
  303                  */
  304                 ua_fp = TRUNC_DOWN32(ua_fp, C_32_STK_ALIGN);
  305 
  306                 /*
  307                  * But we need to account for the return address so the alignment is
  308                  * truly "correct" at _sigtramp
  309                  */
  310                 ua_fp -= sizeof(frame32.retaddr);
  311 
  312                 /* 
  313                  * Build the argument list for the signal handler.
  314                  * Handler should call sigreturn to get out of it
  315                  */
  316                 frame32.retaddr = -1;   
  317                 frame32.sigstyle = infostyle;
  318                 frame32.sig = sig;
  319                 frame32.catcher = CAST_DOWN(sig_t, ua_catcher);
  320                 frame32.sinfo = CAST_DOWN(siginfo_t *, ua_sip);
  321                 frame32.uctx = CAST_DOWN(struct ucontext *, ua_uctxp);
  322 
  323                 if (copyout((caddr_t)&frame32, ua_fp, sizeof (frame32))) 
  324                         goto bad;
  325 
  326                 /*
  327                  * Build the signal context to be used by sigreturn.
  328                  */
  329                 bzero(&uctx32, sizeof(uctx32));
  330 
  331                 uctx32.uc_onstack = oonstack;
  332                 uctx32.uc_sigmask = mask;
  333                 uctx32.uc_stack.ss_sp = CAST_DOWN(char *, ua_fp);
  334                 uctx32.uc_stack.ss_size = stack_size;
  335 
  336                 if (oonstack)
  337                         uctx32.uc_stack.ss_flags |= SS_ONSTACK; 
  338                 uctx32.uc_link = 0;
  339 
  340                 uctx32.uc_mcsize = sizeof(struct mcontext32);
  341 
  342                 uctx32.uc_mcontext = CAST_DOWN(_STRUCT_MCONTEXT32 *, ua_mctxp);
  343                 
  344                 if (copyout((caddr_t)&uctx32, ua_uctxp, sizeof (uctx32))) 
  345                         goto bad;
  346 
  347                 if (copyout((caddr_t)&mctx.mctx32, ua_mctxp, sizeof (struct mcontext32))) 
  348                         goto bad;
  349 
  350                 sinfo64.pad[0]  = tstate32->esp;
  351                 sinfo64.si_addr = tstate32->eip;
  352         }
  353 
  354         switch (sig) {
  355                 case SIGILL:
  356                         switch (ut->uu_code) {
  357                                 case EXC_I386_INVOP:
  358                                         sinfo64.si_code = ILL_ILLOPC;
  359                                         break;
  360                                 default:
  361                                         printf("unknown SIGILL code %ld\n", (long) ut->uu_code);
  362                                         sinfo64.si_code = ILL_NOOP;
  363                         }
  364                         break;
  365                 case SIGFPE:
  366 #define FP_IE 0 /* Invalid operation */
  367 #define FP_DE 1 /* Denormalized operand */
  368 #define FP_ZE 2 /* Zero divide */
  369 #define FP_OE 3 /* overflow */
  370 #define FP_UE 4 /* underflow */
  371 #define FP_PE 5 /* precision */
  372                         if (ut->uu_subcode & (1 << FP_ZE)) {
  373                                 sinfo64.si_code = FPE_FLTDIV;
  374                         } else if (ut->uu_subcode & (1 << FP_OE)) {
  375                                 sinfo64.si_code = FPE_FLTOVF;
  376                         } else if (ut->uu_subcode & (1 << FP_UE)) {
  377                                 sinfo64.si_code = FPE_FLTUND;
  378                         } else if (ut->uu_subcode & (1 << FP_PE)) {
  379                                 sinfo64.si_code = FPE_FLTRES;
  380                         } else if (ut->uu_subcode & (1 << FP_IE)) {
  381                                 sinfo64.si_code = FPE_FLTINV;
  382                         } else {
  383                                 printf("unknown SIGFPE code %ld, subcode %lx\n",
  384                                        (long) ut->uu_code, (long) ut->uu_subcode);
  385                                 sinfo64.si_code = FPE_NOOP;
  386                         }
  387                         break;
  388                 case SIGBUS:
  389                         sinfo64.si_code = BUS_ADRERR;
  390                         sinfo64.si_addr = ua_cr2;
  391                         break;
  392                 case SIGTRAP:
  393                         sinfo64.si_code = TRAP_BRKPT;
  394                         break;
  395                 case SIGSEGV:
  396                         sinfo64.si_addr = ua_cr2;
  397 
  398                         switch (ut->uu_code) {
  399                                 case EXC_I386_GPFLT:
  400                                         /* CR2 is meaningless after GP fault */
  401                                         /* XXX namespace clash! */
  402                                         sinfo64.si_addr = 0ULL;
  403                                         sinfo64.si_code = 0;
  404                                         break;
  405                                 case KERN_PROTECTION_FAILURE:
  406                                         sinfo64.si_code = SEGV_ACCERR;
  407                                         break;
  408                                 case KERN_INVALID_ADDRESS:
  409                                         sinfo64.si_code = SEGV_MAPERR;
  410                                         break;
  411                                 default:
  412                                         printf("unknown SIGSEGV code %ld\n", (long) ut->uu_code);
  413                                         sinfo64.si_code = FPE_NOOP;
  414                         }
  415                                 break;
  416                 default:
  417                 {
  418                         int status_and_exitcode;
  419 
  420                         /*
  421                          * All other signals need to fill out a minimum set of
  422                          * information for the siginfo structure passed into
  423                          * the signal handler, if SA_SIGINFO was specified.
  424                          *
  425                          * p->si_status actually contains both the status and
  426                          * the exit code; we save it off in its own variable
  427                          * for later breakdown.
  428                          */
  429                         proc_lock(p);
  430                         sinfo64.si_pid = p->si_pid;
  431                         p->si_pid =0;
  432                         status_and_exitcode = p->si_status;
  433                         p->si_status = 0;
  434                         sinfo64.si_uid = p->si_uid;
  435                         p->si_uid =0;
  436                         sinfo64.si_code = p->si_code;
  437                         p->si_code = 0;
  438                         proc_unlock(p);
  439                         if (sinfo64.si_code == CLD_EXITED) {
  440                                 if (WIFEXITED(status_and_exitcode)) 
  441                                         sinfo64.si_code = CLD_EXITED;
  442                                 else if (WIFSIGNALED(status_and_exitcode)) {
  443                                         if (WCOREDUMP(status_and_exitcode)) {
  444                                                 sinfo64.si_code = CLD_DUMPED;
  445                                                 status_and_exitcode = W_EXITCODE(status_and_exitcode,status_and_exitcode);
  446                                         } else {
  447                                                 sinfo64.si_code = CLD_KILLED;
  448                                                 status_and_exitcode = W_EXITCODE(status_and_exitcode,status_and_exitcode);
  449                                         }
  450                                 }
  451                         }
  452                         /*
  453                          * The recorded status contains the exit code and the
  454                          * signal information, but the information to be passed
  455                          * in the siginfo to the handler is supposed to only
  456                          * contain the status, so we have to shift it out.
  457                          */
  458                         sinfo64.si_status = WEXITSTATUS(status_and_exitcode);
  459                         break;
  460                 }
  461         }
  462         if (proc_is64bit(p)) {
  463 
  464                 /* XXX truncates catcher address to uintptr_t */
  465                 DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &sinfo64,
  466                         void (*)(void), CAST_DOWN(sig_t, ua_catcher));
  467 
  468                 if (copyout((caddr_t)&sinfo64, ua_sip, sizeof (sinfo64))) 
  469                         goto bad;
  470 
  471                 flavor = x86_THREAD_STATE64;
  472                 state_count = x86_THREAD_STATE64_COUNT;
  473                 state = (void *)&mctx.mctx64.ss;
  474         } else {
  475                 x86_thread_state32_t    *tstate32;
  476                 siginfo_t               sinfo32;
  477 
  478                 bzero((caddr_t)&sinfo32, sizeof(siginfo_t));
  479 
  480                 sinfo32.si_signo  = sinfo64.si_signo;
  481                 sinfo32.si_code   = sinfo64.si_code;
  482                 sinfo32.si_pid    = sinfo64.si_pid;
  483                 sinfo32.si_uid    = sinfo64.si_uid;
  484                 sinfo32.si_status = sinfo64.si_status;
  485                 sinfo32.si_addr   = CAST_DOWN(void *, sinfo64.si_addr);
  486                 sinfo32.__pad[0]    = sinfo64.pad[0];
  487 
  488                 DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &sinfo32,
  489                         void (*)(void), CAST_DOWN(sig_t, ua_catcher));
  490 
  491                 if (copyout((caddr_t)&sinfo32, ua_sip, sizeof (sinfo32))) 
  492                         goto bad;
  493         
  494                 tstate32 = &mctx.mctx32.ss;
  495                 tstate32->eip = CAST_DOWN(unsigned int, ps->ps_trampact[sig]);
  496                 tstate32->esp = CAST_DOWN(unsigned int, ua_fp);
  497                 
  498                 tstate32->eflags = get_eflags_exportmask();
  499 
  500                 tstate32->cs = USER_CS;
  501                 tstate32->ss = USER_DS;
  502                 tstate32->ds = USER_DS;
  503                 tstate32->es = USER_DS;
  504                 tstate32->fs = NULL_SEG;
  505                 tstate32->gs = USER_CTHREAD;
  506 
  507                 flavor = x86_THREAD_STATE32;
  508                 state_count = x86_THREAD_STATE32_COUNT;
  509                 state = (void *)tstate32;
  510         }
  511         if (thread_setstatus(thread, flavor, (thread_state_t)state, state_count) != KERN_SUCCESS)
  512                 goto bad;
  513         ml_fp_setvalid(FALSE);
  514 
  515         proc_lock(p);
  516 
  517         return;
  518 
  519 bad:
  520         proc_lock(p);
  521         SIGACTION(p, SIGILL) = SIG_DFL;
  522         sig = sigmask(SIGILL);
  523         p->p_sigignore &= ~sig;
  524         p->p_sigcatch &= ~sig;
  525         ut->uu_sigmask &= ~sig;
  526         /* sendsig is called with signal lock held */
  527         proc_unlock(p);
  528         psignal_locked(p, SIGILL);
  529         proc_lock(p);
  530         return;
  531 }
  532 
  533 /*
  534  * System call to cleanup state after a signal
  535  * has been taken.  Reset signal mask and
  536  * stack state from context left by sendsig (above).
  537  * Return to previous pc and psl as specified by
  538  * context left by sendsig. Check carefully to
  539  * make sure that the user has not modified the
  540  * psl to gain improper priviledges or to cause
  541  * a machine fault.
  542  */
  543 
  544 int
  545 sigreturn(struct proc *p, struct sigreturn_args *uap, __unused int *retval)
  546 {
  547         union {
  548             struct mcontext32   mctx32;
  549             struct mcontext64   mctx64;
  550         } mctx;
  551         thread_t thread = current_thread();
  552         struct uthread * ut;
  553         int     error;
  554         int     onstack = 0;
  555 
  556         mach_msg_type_number_t ts_count;
  557         unsigned int           ts_flavor;
  558         void                *  ts;
  559         mach_msg_type_number_t fs_count;
  560         unsigned int           fs_flavor;
  561         void                *  fs;
  562 
  563         ut = (struct uthread *)get_bsdthread_info(thread);
  564 
  565         /*
  566          * If we are being asked to change the altstack flag on the thread, we
  567          * just set/reset it and return (the uap->uctx is not used).
  568          */
  569         if ((unsigned int)uap->infostyle == UC_SET_ALT_STACK) {
  570                 ut->uu_sigstk.ss_flags |= SA_ONSTACK;
  571                 return (0);
  572         } else if ((unsigned int)uap->infostyle == UC_RESET_ALT_STACK) {
  573                 ut->uu_sigstk.ss_flags &= ~SA_ONSTACK;
  574                 return (0);
  575         }
  576 
  577         if (proc_is64bit(p)) {
  578                 struct user_ucontext64  uctx64;
  579 
  580                 if ((error = copyin(uap->uctx, (void *)&uctx64, sizeof (uctx64))))
  581                         return(error);
  582 
  583                 if ((error = copyin(uctx64.uc_mcontext64, (void *)&mctx.mctx64, sizeof (struct mcontext64))))
  584                         return(error);
  585 
  586                 onstack = uctx64.uc_onstack & 01;
  587                 ut->uu_sigmask = uctx64.uc_sigmask & ~sigcantmask;
  588 
  589                 ts_flavor = x86_THREAD_STATE64;
  590                 ts_count  = x86_THREAD_STATE64_COUNT;
  591                 ts = (void *)&mctx.mctx64.ss;
  592 
  593                 fs_flavor = x86_FLOAT_STATE64;
  594                 fs_count  = x86_FLOAT_STATE64_COUNT;
  595                 fs = (void *)&mctx.mctx64.fs;
  596 
  597       } else {
  598                 struct ucontext         uctx32;
  599 
  600                 if ((error = copyin(uap->uctx, (void *)&uctx32, sizeof (uctx32)))) 
  601                         return(error);
  602 
  603                 if ((error = copyin(CAST_USER_ADDR_T(uctx32.uc_mcontext), (void *)&mctx.mctx32, sizeof (struct mcontext32)))) 
  604                         return(error);
  605 
  606                 onstack = uctx32.uc_onstack & 01;
  607                 ut->uu_sigmask = uctx32.uc_sigmask & ~sigcantmask;
  608 
  609                 ts_flavor = x86_THREAD_STATE32;
  610                 ts_count  = x86_THREAD_STATE32_COUNT;
  611                 ts = (void *)&mctx.mctx32.ss;
  612 
  613                 fs_flavor = x86_FLOAT_STATE32;
  614                 fs_count  = x86_FLOAT_STATE32_COUNT;
  615                 fs = (void *)&mctx.mctx32.fs;
  616         }
  617 
  618         if (onstack)
  619                 ut->uu_sigstk.ss_flags |= SA_ONSTACK;
  620         else
  621                 ut->uu_sigstk.ss_flags &= ~SA_ONSTACK;
  622 
  623         if (ut->uu_siglist & ~ut->uu_sigmask)
  624                 signal_setast(thread);
  625 
  626         /*
  627          * thread_set_state() does all the needed checks for the passed in
  628          * content
  629          */
  630         if (thread_setstatus(thread, ts_flavor, ts, ts_count) != KERN_SUCCESS)
  631                 return(EINVAL);
  632 
  633         ml_fp_setvalid(TRUE);
  634 
  635         if (thread_setstatus(thread, fs_flavor, fs, fs_count)  != KERN_SUCCESS)
  636                 return(EINVAL);
  637 
  638         return (EJUSTRETURN);
  639 }
  640 
  641 
  642 /*
  643  * machine_exception() performs MD translation
  644  * of a mach exception to a unix signal and code.
  645  */
  646 
  647 boolean_t
  648 machine_exception(
  649         int                             exception,
  650         mach_exception_code_t           code,
  651         __unused mach_exception_subcode_t subcode,
  652         int                             *unix_signal,
  653         mach_exception_code_t           *unix_code)
  654 {
  655 
  656         switch(exception) {
  657 
  658         case EXC_BAD_ACCESS:
  659                 /* Map GP fault to SIGSEGV, otherwise defer to caller */
  660                 if (code == EXC_I386_GPFLT) {
  661                         *unix_signal = SIGSEGV;
  662                         *unix_code = code;
  663                         break;
  664                 }
  665                 return(FALSE);
  666 
  667         case EXC_BAD_INSTRUCTION:
  668                 *unix_signal = SIGILL;
  669                 *unix_code = code;
  670                 break;
  671 
  672         case EXC_ARITHMETIC:
  673                 *unix_signal = SIGFPE;
  674                 *unix_code = code;
  675                 break;
  676 
  677         case EXC_SOFTWARE:
  678                 if (code == EXC_I386_BOUND) {
  679                         /*
  680                          * Map #BR, the Bound Range Exceeded exception, to
  681                          * SIGTRAP.
  682                          */
  683                         *unix_signal = SIGTRAP;
  684                         *unix_code = code;
  685                         break;
  686                 }
  687 
  688         default:
  689                 return(FALSE);
  690         }
  691    
  692         return(TRUE);
  693 }
  694 

Cache object: 1323b67708e6ec8523ea335d572a3c7b


[ 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.