]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (c) 2000-2017 Apple 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 | * 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. | |
33 | */ | |
34 | ||
35 | #include <sys/param.h> | |
36 | ||
37 | #include <mach/boolean.h> | |
38 | #include <mach/exception.h> | |
39 | #include <mach/kern_return.h> | |
40 | ||
41 | #include <sys/proc.h> | |
42 | #include <sys/user.h> | |
43 | #include <sys/systm.h> | |
44 | #include <sys/vmparam.h> /* MAXSSIZ */ | |
45 | ||
46 | #include <sys/ux_exception.h> | |
47 | ||
48 | /* | |
49 | * Translate Mach exceptions to UNIX signals. | |
50 | * | |
51 | * ux_exception translates a mach exception, code and subcode to | |
52 | * a signal. Calls machine_exception (machine dependent) | |
53 | * to attempt translation first. | |
54 | */ | |
55 | static int | |
56 | ux_exception(int exception, | |
57 | mach_exception_code_t code, | |
58 | mach_exception_subcode_t subcode) | |
59 | { | |
60 | int machine_signal = 0; | |
61 | ||
62 | /* Try machine-dependent translation first. */ | |
63 | if ((machine_signal = machine_exception(exception, code, subcode)) != 0) { | |
64 | return machine_signal; | |
65 | } | |
66 | ||
67 | switch (exception) { | |
68 | case EXC_BAD_ACCESS: | |
69 | if (code == KERN_INVALID_ADDRESS) { | |
70 | return SIGSEGV; | |
71 | } else { | |
72 | return SIGBUS; | |
73 | } | |
74 | ||
75 | case EXC_BAD_INSTRUCTION: | |
76 | return SIGILL; | |
77 | ||
78 | case EXC_ARITHMETIC: | |
79 | return SIGFPE; | |
80 | ||
81 | case EXC_EMULATION: | |
82 | return SIGEMT; | |
83 | ||
84 | case EXC_SOFTWARE: | |
85 | switch (code) { | |
86 | case EXC_UNIX_BAD_SYSCALL: | |
87 | return SIGSYS; | |
88 | case EXC_UNIX_BAD_PIPE: | |
89 | return SIGPIPE; | |
90 | case EXC_UNIX_ABORT: | |
91 | return SIGABRT; | |
92 | case EXC_SOFT_SIGNAL: | |
93 | return SIGKILL; | |
94 | } | |
95 | break; | |
96 | ||
97 | case EXC_BREAKPOINT: | |
98 | return SIGTRAP; | |
99 | } | |
100 | ||
101 | return 0; | |
102 | } | |
103 | ||
104 | /* | |
105 | * Sends the corresponding UNIX signal to a thread that has triggered a Mach exception. | |
106 | */ | |
107 | kern_return_t | |
108 | handle_ux_exception(thread_t thread, | |
109 | int exception, | |
110 | mach_exception_code_t code, | |
111 | mach_exception_subcode_t subcode) | |
112 | { | |
113 | /* Returns +1 proc reference */ | |
114 | proc_t p = proc_findthread(thread); | |
115 | ||
116 | /* Can't deliver a signal without a bsd process reference */ | |
117 | if (p == NULL) { | |
118 | return KERN_FAILURE; | |
119 | } | |
120 | ||
121 | /* Translate exception and code to signal type */ | |
122 | int ux_signal = ux_exception(exception, code, subcode); | |
123 | ||
124 | uthread_t ut = get_bsdthread_info(thread); | |
125 | ||
126 | /* | |
127 | * Stack overflow should result in a SIGSEGV signal | |
128 | * on the alternate stack. | |
129 | * but we have one or more guard pages after the | |
130 | * stack top, so we would get a KERN_PROTECTION_FAILURE | |
131 | * exception instead of KERN_INVALID_ADDRESS, resulting in | |
132 | * a SIGBUS signal. | |
133 | * Detect that situation and select the correct signal. | |
134 | */ | |
135 | if (code == KERN_PROTECTION_FAILURE && | |
136 | ux_signal == SIGBUS) { | |
137 | user_addr_t sp = subcode; | |
138 | ||
139 | user_addr_t stack_max = p->user_stack; | |
140 | user_addr_t stack_min = p->user_stack - MAXSSIZ; | |
141 | if (sp >= stack_min && sp < stack_max) { | |
142 | /* | |
143 | * This is indeed a stack overflow. Deliver a | |
144 | * SIGSEGV signal. | |
145 | */ | |
146 | ux_signal = SIGSEGV; | |
147 | ||
148 | /* | |
149 | * If the thread/process is not ready to handle | |
150 | * SIGSEGV on an alternate stack, force-deliver | |
151 | * SIGSEGV with a SIG_DFL handler. | |
152 | */ | |
153 | int mask = sigmask(ux_signal); | |
154 | struct sigacts *ps = p->p_sigacts; | |
155 | if ((p->p_sigignore & mask) || | |
156 | (ut->uu_sigwait & mask) || | |
157 | (ut->uu_sigmask & mask) || | |
158 | (ps->ps_sigact[SIGSEGV] == SIG_IGN) || | |
159 | (!(ps->ps_sigonstack & mask))) { | |
160 | p->p_sigignore &= ~mask; | |
161 | p->p_sigcatch &= ~mask; | |
162 | ps->ps_sigact[SIGSEGV] = SIG_DFL; | |
163 | ut->uu_sigwait &= ~mask; | |
164 | ut->uu_sigmask &= ~mask; | |
165 | } | |
166 | } | |
167 | } | |
168 | ||
169 | /* Send signal to thread */ | |
170 | if (ux_signal != 0) { | |
171 | ut->uu_exception = exception; | |
172 | //ut->uu_code = code; // filled in by threadsignal | |
173 | ut->uu_subcode = subcode; | |
174 | threadsignal(thread, ux_signal, code, TRUE); | |
175 | } | |
176 | ||
177 | proc_rele(p); | |
178 | ||
179 | return KERN_SUCCESS; | |
180 | } |