2  * Copyright (c) 2000-2017 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   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. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  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. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  29  * Mach Operating System 
  30  * Copyright (c) 1987 Carnegie-Mellon University 
  31  * All rights reserved.  The CMU software License Agreement specifies 
  32  * the terms and conditions for use and redistribution. 
  35 #include <sys/param.h> 
  37 #include <mach/boolean.h> 
  38 #include <mach/exception.h> 
  39 #include <mach/kern_return.h> 
  43 #include <sys/systm.h> 
  44 #include <sys/vmparam.h>        /* MAXSSIZ */ 
  46 #include <sys/ux_exception.h> 
  49  * Translate Mach exceptions to UNIX signals. 
  51  * ux_exception translates a mach exception, code and subcode to 
  52  * a signal.  Calls machine_exception (machine dependent) 
  53  * to attempt translation first. 
  56 ux_exception(int                        exception
, 
  57              mach_exception_code_t      code
, 
  58              mach_exception_subcode_t   subcode
) 
  60         int machine_signal 
= 0; 
  62         /* Try machine-dependent translation first. */ 
  63         if ((machine_signal 
= machine_exception(exception
, code
, subcode
)) != 0) 
  64                 return machine_signal
; 
  68                         if (code 
== KERN_INVALID_ADDRESS
) 
  73                 case EXC_BAD_INSTRUCTION
: 
  84                                 case EXC_UNIX_BAD_SYSCALL
: 
  86                                 case EXC_UNIX_BAD_PIPE
: 
 103  * Sends the corresponding UNIX signal to a thread that has triggered a Mach exception. 
 106 handle_ux_exception(thread_t                    thread
, 
 108                     mach_exception_code_t       code
, 
 109                     mach_exception_subcode_t    subcode
) 
 111         /* Returns +1 proc reference */ 
 112         proc_t p 
= proc_findthread(thread
); 
 114         /* Can't deliver a signal without a bsd process reference */ 
 118         /* Translate exception and code to signal type */ 
 119         int ux_signal 
= ux_exception(exception
, code
, subcode
); 
 121         uthread_t ut 
= get_bsdthread_info(thread
); 
 124          * Stack overflow should result in a SIGSEGV signal 
 125          * on the alternate stack. 
 126          * but we have one or more guard pages after the 
 127          * stack top, so we would get a KERN_PROTECTION_FAILURE 
 128          * exception instead of KERN_INVALID_ADDRESS, resulting in 
 130          * Detect that situation and select the correct signal. 
 132         if (code 
== KERN_PROTECTION_FAILURE 
&& 
 133             ux_signal 
== SIGBUS
) { 
 134                 user_addr_t sp 
= subcode
; 
 136                 user_addr_t stack_max 
= p
->user_stack
; 
 137                 user_addr_t stack_min 
= p
->user_stack 
- MAXSSIZ
; 
 138                 if (sp 
>= stack_min 
&& sp 
< stack_max
) { 
 140                          * This is indeed a stack overflow.  Deliver a 
 146                          * If the thread/process is not ready to handle 
 147                          * SIGSEGV on an alternate stack, force-deliver 
 148                          * SIGSEGV with a SIG_DFL handler. 
 150                         int mask 
= sigmask(ux_signal
); 
 151                         struct sigacts 
*ps 
= p
->p_sigacts
; 
 152                         if ((p
->p_sigignore 
& mask
) || 
 153                             (ut
->uu_sigwait 
& mask
) || 
 154                             (ut
->uu_sigmask 
& mask
) || 
 155                             (ps
->ps_sigact
[SIGSEGV
] == SIG_IGN
) || 
 156                             (! (ps
->ps_sigonstack 
& mask
))) { 
 157                                 p
->p_sigignore 
&= ~mask
; 
 158                                 p
->p_sigcatch 
&= ~mask
; 
 159                                 ps
->ps_sigact
[SIGSEGV
] = SIG_DFL
; 
 160                                 ut
->uu_sigwait 
&= ~mask
; 
 161                                 ut
->uu_sigmask 
&= ~mask
; 
 166         /* Send signal to thread */ 
 167         if (ux_signal 
!= 0) { 
 168                 ut
->uu_exception 
= exception
; 
 169                 //ut->uu_code = code; // filled in by threadsignal 
 170                 ut
->uu_subcode 
= subcode
; 
 171                 threadsignal(thread
, ux_signal
, code
, TRUE
);