]> git.saurik.com Git - apple/xnu.git/blame - bsd/dev/i386/unix_signal.c
xnu-4903.241.1.tar.gz
[apple/xnu.git] / bsd / dev / i386 / unix_signal.c
CommitLineData
1c79356b 1/*
0c530ab8 2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
5d5c5d0d 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
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.
8f6c56a5 14 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
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>
1c79356b 40
91447636 41#include <sys/systm.h>
1c79356b 42#include <sys/param.h>
91447636 43#include <sys/proc_internal.h>
1c79356b 44#include <sys/user.h>
91447636
A
45#include <sys/sysproto.h>
46#include <sys/sysent.h>
0c530ab8
A
47#include <sys/ucontext.h>
48#include <sys/wait.h>
d9a64523
A
49
50#include <sys/ux_exception.h>
51
91447636 52#include <mach/thread_act.h> /* for thread_abort_safely */
0c530ab8 53#include <mach/thread_status.h>
1c79356b 54
0c530ab8 55#include <i386/eflags.h>
1c79356b 56#include <i386/psl.h>
b0d623f7 57#include <i386/machine_routines.h>
91447636 58#include <i386/seg.h>
5ba3f43e 59#include <i386/fpu.h>
1c79356b 60
6d2010ae 61#include <machine/pal_routines.h>
1c79356b 62
6d2010ae 63#include <sys/kdebug.h>
2d21ac55
A
64#include <sys/sdt.h>
65
b0d623f7 66
91447636 67/* Forward: */
39037602 68extern kern_return_t thread_getstatus(thread_t act, int flavor,
0c530ab8
A
69 thread_state_t tstate, mach_msg_type_number_t *count);
70extern kern_return_t thread_setstatus(thread_t thread, int flavor,
71 thread_state_t tstate, mach_msg_type_number_t count);
1c79356b 72
55e303ae
A
73/* Signal handler flavors supported */
74/* These defns should match the Libc implmn */
75#define UC_TRAD 1
0c530ab8 76#define UC_FLAVOR 30
2d21ac55
A
77#define UC_SET_ALT_STACK 0x40000000
78#define UC_RESET_ALT_STACK 0x80000000
0c530ab8
A
79
80#define C_32_STK_ALIGN 16
81#define C_64_STK_ALIGN 16
82#define C_64_REDZONE_LEN 128
83#define TRUNC_DOWN32(a,c) ((((uint32_t)a)-(c)) & ((uint32_t)(-(c))))
84#define TRUNC_DOWN64(a,c) ((((uint64_t)a)-(c)) & ((uint64_t)(-(c))))
55e303ae 85
1c79356b
A
86/*
87 * Send an interrupt to process.
88 *
89 * Stack is set up to allow sigcode stored
90 * in u. to call routine, followed by chmk
91 * to sigreturn routine below. After sigreturn
92 * resets the signal mask, the stack, the frame
93 * pointer, and the argument pointer, it returns
94 * to the user specified pc, psl.
95 */
0c530ab8 96struct sigframe32 {
b0d623f7
A
97 int retaddr;
98 user32_addr_t catcher; /* sig_t */
99 int sigstyle;
100 int sig;
101 user32_addr_t sinfo; /* siginfo32_t* */
102 user32_addr_t uctx; /* struct ucontext32 */
d9a64523 103 user32_addr_t token;
0c530ab8
A
104};
105
5ba3f43e
A
106/*
107 * Declare table of structure flavors and sizes for 64-bit and 32-bit processes
108 * for the cases of extended states (plain FP, or AVX):
109 */
110typedef struct {
111 int flavor; natural_t state_count; size_t mcontext_size;
112} xstate_info_t;
113static const xstate_info_t thread_state64[] = {
114 [FP] = { x86_FLOAT_STATE64, x86_FLOAT_STATE64_COUNT, sizeof(struct mcontext64) },
115 [AVX] = { x86_AVX_STATE64, x86_AVX_STATE64_COUNT, sizeof(struct mcontext_avx64) },
116#if !defined(RC_HIDE_XNU_J137)
117 [AVX512] = { x86_AVX512_STATE64, x86_AVX512_STATE64_COUNT, sizeof(struct mcontext_avx512_64) }
118#endif
119};
120static const xstate_info_t thread_state32[] = {
121 [FP] = { x86_FLOAT_STATE32, x86_FLOAT_STATE32_COUNT, sizeof(struct mcontext32) },
122 [AVX] = { x86_AVX_STATE32, x86_AVX_STATE32_COUNT, sizeof(struct mcontext_avx32) },
123#if !defined(RC_HIDE_XNU_J137)
124 [AVX512] = { x86_AVX512_STATE32, x86_AVX512_STATE32_COUNT, sizeof(struct mcontext_avx512_32) }
125#endif
126};
127
b0d623f7
A
128/*
129 * NOTE: Source and target may *NOT* overlap!
316670eb 130 * XXX: Unify with bsd/kern/kern_exit.c
b0d623f7
A
131 */
132static void
316670eb 133siginfo_user_to_user32_x86(user_siginfo_t *in, user32_siginfo_t *out)
b0d623f7
A
134{
135 out->si_signo = in->si_signo;
136 out->si_errno = in->si_errno;
137 out->si_code = in->si_code;
138 out->si_pid = in->si_pid;
139 out->si_uid = in->si_uid;
140 out->si_status = in->si_status;
141 out->si_addr = CAST_DOWN_EXPLICIT(user32_addr_t,in->si_addr);
142 /* following cast works for sival_int because of padding */
143 out->si_value.sival_ptr = CAST_DOWN_EXPLICIT(user32_addr_t,in->si_value.sival_ptr);
144 out->si_band = in->si_band; /* range reduction */
145 out->__pad[0] = in->pad[0]; /* mcontext.ss.r1 */
146}
0c530ab8 147
b0d623f7 148static void
316670eb 149siginfo_user_to_user64_x86(user_siginfo_t *in, user64_siginfo_t *out)
b0d623f7
A
150{
151 out->si_signo = in->si_signo;
152 out->si_errno = in->si_errno;
153 out->si_code = in->si_code;
154 out->si_pid = in->si_pid;
155 out->si_uid = in->si_uid;
156 out->si_status = in->si_status;
157 out->si_addr = in->si_addr;
158 out->si_value.sival_ptr = in->si_value.sival_ptr;
159 out->si_band = in->si_band; /* range reduction */
160 out->__pad[0] = in->pad[0]; /* mcontext.ss.r1 */
161}
0c530ab8 162
1c79356b 163void
b0d623f7 164sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused uint32_t code)
1c79356b 165{
060df5ea 166 union {
5ba3f43e
A
167 struct mcontext_avx32 mctx_avx32;
168 struct mcontext_avx64 mctx_avx64;
169#if !defined(RC_HIDE_XNU_J137)
170 struct mcontext_avx512_32 mctx_avx512_32;
171 struct mcontext_avx512_64 mctx_avx512_64;
172#endif
060df5ea
A
173 } mctx_store, *mctxp = &mctx_store;
174
0c530ab8
A
175 user_addr_t ua_sp;
176 user_addr_t ua_fp;
177 user_addr_t ua_cr2;
178 user_addr_t ua_sip;
179 user_addr_t ua_uctxp;
180 user_addr_t ua_mctxp;
181 user_siginfo_t sinfo64;
182
1c79356b 183 struct sigacts *ps = p->p_sigacts;
0c530ab8 184 int oonstack, flavor;
b0d623f7
A
185 user_addr_t trampact;
186 int sigonstack;
0c530ab8
A
187 void * state;
188 mach_msg_type_number_t state_count;
0c530ab8 189
2d21ac55 190 thread_t thread;
9bccf70c 191 struct uthread * ut;
0c530ab8
A
192 int stack_size = 0;
193 int infostyle = UC_TRAD;
5ba3f43e 194 xstate_t sig_xstate;
d9a64523
A
195 user_addr_t token_uctx;
196 kern_return_t kr;
060df5ea 197
2d21ac55
A
198 thread = current_thread();
199 ut = get_bsdthread_info(thread);
200
0c530ab8
A
201 if (p->p_sigacts->ps_siginfo & sigmask(sig))
202 infostyle = UC_FLAVOR;
203
2d21ac55 204 oonstack = ut->uu_sigstk.ss_flags & SA_ONSTACK;
b0d623f7
A
205 trampact = ps->ps_trampact[sig];
206 sigonstack = (ps->ps_sigonstack & sigmask(sig));
1c79356b 207
9bccf70c 208 /*
0c530ab8 209 * init siginfo
9bccf70c 210 */
2d21ac55
A
211 proc_unlock(p);
212
b0d623f7 213 bzero((caddr_t)&sinfo64, sizeof(sinfo64));
0c530ab8 214 sinfo64.si_signo = sig;
060df5ea
A
215
216 bzero(mctxp, sizeof(*mctxp));
5ba3f43e
A
217
218 sig_xstate = current_xstate();
2d21ac55 219
0c530ab8
A
220 if (proc_is64bit(p)) {
221 x86_thread_state64_t *tstate64;
222 struct user_ucontext64 uctx64;
d9a64523 223 user64_addr_t token;
0c530ab8
A
224
225 flavor = x86_THREAD_STATE64;
226 state_count = x86_THREAD_STATE64_COUNT;
060df5ea 227 state = (void *)&mctxp->mctx_avx64.ss;
0c530ab8
A
228 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
229 goto bad;
230
5ba3f43e
A
231 flavor = thread_state64[sig_xstate].flavor;
232 state_count = thread_state64[sig_xstate].state_count;
060df5ea 233 state = (void *)&mctxp->mctx_avx64.fs;
0c530ab8
A
234 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
235 goto bad;
236
237 flavor = x86_EXCEPTION_STATE64;
238 state_count = x86_EXCEPTION_STATE64_COUNT;
060df5ea 239 state = (void *)&mctxp->mctx_avx64.es;
0c530ab8
A
240 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
241 goto bad;
242
060df5ea 243 tstate64 = &mctxp->mctx_avx64.ss;
0c530ab8 244
2d21ac55
A
245 /* figure out where our new stack lives */
246 if ((ut->uu_flag & UT_ALTSTACK) && !oonstack &&
b0d623f7 247 (sigonstack)) {
2d21ac55
A
248 ua_sp = ut->uu_sigstk.ss_sp;
249 stack_size = ut->uu_sigstk.ss_size;
250 ua_sp += stack_size;
251 ut->uu_sigstk.ss_flags |= SA_ONSTACK;
252 } else {
0c530ab8 253 ua_sp = tstate64->rsp;
2d21ac55 254 }
060df5ea 255 ua_cr2 = mctxp->mctx_avx64.es.faultvaddr;
0c530ab8
A
256
257 /* The x86_64 ABI defines a 128-byte red zone. */
258 ua_sp -= C_64_REDZONE_LEN;
259
260 ua_sp -= sizeof (struct user_ucontext64);
261 ua_uctxp = ua_sp; // someone tramples the first word!
262
b0d623f7 263 ua_sp -= sizeof (user64_siginfo_t);
0c530ab8
A
264 ua_sip = ua_sp;
265
5ba3f43e 266 ua_sp -= thread_state64[sig_xstate].mcontext_size;
0c530ab8
A
267 ua_mctxp = ua_sp;
268
269 /*
270 * Align the frame and stack pointers to 16 bytes for SSE.
271 * (Note that we use 'ua_fp' as the base of the stack going forward)
272 */
273 ua_fp = TRUNC_DOWN64(ua_sp, C_64_STK_ALIGN);
274
275 /*
276 * But we need to account for the return address so the alignment is
277 * truly "correct" at _sigtramp
278 */
279 ua_fp -= sizeof(user_addr_t);
280
d9a64523
A
281 /*
282 * Generate the validation token for sigreturn
283 */
284 token_uctx = ua_uctxp;
285 kr = machine_thread_siguctx_pointer_convert_to_user(thread, &token_uctx);
286 assert(kr == KERN_SUCCESS);
287 token = (user64_addr_t)token_uctx ^ (user64_addr_t)ps->ps_sigreturn_token;
288
0c530ab8
A
289 /*
290 * Build the signal context to be used by sigreturn.
291 */
292 bzero(&uctx64, sizeof(uctx64));
293
294 uctx64.uc_onstack = oonstack;
295 uctx64.uc_sigmask = mask;
296 uctx64.uc_stack.ss_sp = ua_fp;
297 uctx64.uc_stack.ss_size = stack_size;
298
299 if (oonstack)
300 uctx64.uc_stack.ss_flags |= SS_ONSTACK;
301 uctx64.uc_link = 0;
302
5ba3f43e 303 uctx64.uc_mcsize = thread_state64[sig_xstate].mcontext_size;
0c530ab8
A
304 uctx64.uc_mcontext64 = ua_mctxp;
305
306 if (copyout((caddr_t)&uctx64, ua_uctxp, sizeof (uctx64)))
307 goto bad;
308
5ba3f43e 309 if (copyout((caddr_t)&mctx_store, ua_mctxp, thread_state64[sig_xstate].mcontext_size))
0c530ab8
A
310 goto bad;
311
312 sinfo64.pad[0] = tstate64->rsp;
313 sinfo64.si_addr = tstate64->rip;
314
b0d623f7 315 tstate64->rip = trampact;
0c530ab8
A
316 tstate64->rsp = ua_fp;
317 tstate64->rflags = get_eflags_exportmask();
318 /*
319 * JOE - might not need to set these
320 */
321 tstate64->cs = USER64_CS;
322 tstate64->fs = NULL_SEG;
323 tstate64->gs = USER_CTHREAD;
324
325 /*
326 * Build the argument list for the signal handler.
327 * Handler should call sigreturn to get out of it
328 */
329 tstate64->rdi = ua_catcher;
330 tstate64->rsi = infostyle;
331 tstate64->rdx = sig;
332 tstate64->rcx = ua_sip;
333 tstate64->r8 = ua_uctxp;
d9a64523 334 tstate64->r9 = token;
9bccf70c 335 } else {
0c530ab8 336 x86_thread_state32_t *tstate32;
b0d623f7 337 struct user_ucontext32 uctx32;
0c530ab8 338 struct sigframe32 frame32;
d9a64523 339 user32_addr_t token;
0c530ab8
A
340
341 flavor = x86_THREAD_STATE32;
342 state_count = x86_THREAD_STATE32_COUNT;
060df5ea 343 state = (void *)&mctxp->mctx_avx32.ss;
0c530ab8
A
344 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
345 goto bad;
346
5ba3f43e
A
347 flavor = thread_state32[sig_xstate].flavor;
348 state_count = thread_state32[sig_xstate].state_count;
060df5ea 349 state = (void *)&mctxp->mctx_avx32.fs;
0c530ab8
A
350 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
351 goto bad;
352
353 flavor = x86_EXCEPTION_STATE32;
354 state_count = x86_EXCEPTION_STATE32_COUNT;
060df5ea 355 state = (void *)&mctxp->mctx_avx32.es;
0c530ab8
A
356 if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS)
357 goto bad;
358
060df5ea 359 tstate32 = &mctxp->mctx_avx32.ss;
0c530ab8 360
2d21ac55
A
361 /* figure out where our new stack lives */
362 if ((ut->uu_flag & UT_ALTSTACK) && !oonstack &&
b0d623f7 363 (sigonstack)) {
2d21ac55
A
364 ua_sp = ut->uu_sigstk.ss_sp;
365 stack_size = ut->uu_sigstk.ss_size;
366 ua_sp += stack_size;
367 ut->uu_sigstk.ss_flags |= SA_ONSTACK;
368 } else {
0c530ab8 369 ua_sp = tstate32->esp;
2d21ac55 370 }
060df5ea 371 ua_cr2 = mctxp->mctx_avx32.es.faultvaddr;
0c530ab8 372
b0d623f7 373 ua_sp -= sizeof (struct user_ucontext32);
0c530ab8
A
374 ua_uctxp = ua_sp; // someone tramples the first word!
375
b0d623f7 376 ua_sp -= sizeof (user32_siginfo_t);
0c530ab8
A
377 ua_sip = ua_sp;
378
5ba3f43e 379 ua_sp -= thread_state32[sig_xstate].mcontext_size;
0c530ab8
A
380 ua_mctxp = ua_sp;
381
382 ua_sp -= sizeof (struct sigframe32);
383 ua_fp = ua_sp;
384
385 /*
386 * Align the frame and stack pointers to 16 bytes for SSE.
387 * (Note that we use 'fp' as the base of the stack going forward)
388 */
389 ua_fp = TRUNC_DOWN32(ua_fp, C_32_STK_ALIGN);
390
391 /*
392 * But we need to account for the return address so the alignment is
393 * truly "correct" at _sigtramp
394 */
395 ua_fp -= sizeof(frame32.retaddr);
396
d9a64523
A
397 /*
398 * Generate the validation token for sigreturn
399 */
400 token_uctx = ua_uctxp;
401 kr = machine_thread_siguctx_pointer_convert_to_user(thread, &token_uctx);
402 assert(kr == KERN_SUCCESS);
403 token = CAST_DOWN_EXPLICIT(user32_addr_t, token_uctx) ^
404 CAST_DOWN_EXPLICIT(user32_addr_t, ps->ps_sigreturn_token);
405
0c530ab8
A
406 /*
407 * Build the argument list for the signal handler.
408 * Handler should call sigreturn to get out of it
409 */
410 frame32.retaddr = -1;
411 frame32.sigstyle = infostyle;
412 frame32.sig = sig;
b0d623f7
A
413 frame32.catcher = CAST_DOWN_EXPLICIT(user32_addr_t, ua_catcher);
414 frame32.sinfo = CAST_DOWN_EXPLICIT(user32_addr_t, ua_sip);
415 frame32.uctx = CAST_DOWN_EXPLICIT(user32_addr_t, ua_uctxp);
d9a64523 416 frame32.token = token;
0c530ab8
A
417
418 if (copyout((caddr_t)&frame32, ua_fp, sizeof (frame32)))
419 goto bad;
420
421 /*
422 * Build the signal context to be used by sigreturn.
423 */
424 bzero(&uctx32, sizeof(uctx32));
425
426 uctx32.uc_onstack = oonstack;
427 uctx32.uc_sigmask = mask;
b0d623f7 428 uctx32.uc_stack.ss_sp = CAST_DOWN_EXPLICIT(user32_addr_t, ua_fp);
0c530ab8
A
429 uctx32.uc_stack.ss_size = stack_size;
430
431 if (oonstack)
432 uctx32.uc_stack.ss_flags |= SS_ONSTACK;
433 uctx32.uc_link = 0;
434
5ba3f43e 435 uctx32.uc_mcsize = thread_state64[sig_xstate].mcontext_size;
0c530ab8 436
b0d623f7 437 uctx32.uc_mcontext = CAST_DOWN_EXPLICIT(user32_addr_t, ua_mctxp);
0c530ab8
A
438
439 if (copyout((caddr_t)&uctx32, ua_uctxp, sizeof (uctx32)))
440 goto bad;
441
5ba3f43e 442 if (copyout((caddr_t)&mctx_store, ua_mctxp, thread_state32[sig_xstate].mcontext_size))
0c530ab8
A
443 goto bad;
444
445 sinfo64.pad[0] = tstate32->esp;
446 sinfo64.si_addr = tstate32->eip;
9bccf70c 447 }
9bccf70c 448
0c530ab8 449 switch (sig) {
0c530ab8
A
450 case SIGILL:
451 switch (ut->uu_code) {
452 case EXC_I386_INVOP:
453 sinfo64.si_code = ILL_ILLOPC;
454 break;
0c530ab8 455 default:
0c530ab8
A
456 sinfo64.si_code = ILL_NOOP;
457 }
458 break;
459 case SIGFPE:
460#define FP_IE 0 /* Invalid operation */
461#define FP_DE 1 /* Denormalized operand */
462#define FP_ZE 2 /* Zero divide */
463#define FP_OE 3 /* overflow */
464#define FP_UE 4 /* underflow */
465#define FP_PE 5 /* precision */
b0d623f7
A
466 if (ut->uu_code == EXC_I386_DIV) {
467 sinfo64.si_code = FPE_INTDIV;
468 }
469 else if (ut->uu_code == EXC_I386_INTO) {
470 sinfo64.si_code = FPE_INTOVF;
471 }
472 else if (ut->uu_subcode & (1 << FP_ZE)) {
0c530ab8
A
473 sinfo64.si_code = FPE_FLTDIV;
474 } else if (ut->uu_subcode & (1 << FP_OE)) {
475 sinfo64.si_code = FPE_FLTOVF;
476 } else if (ut->uu_subcode & (1 << FP_UE)) {
477 sinfo64.si_code = FPE_FLTUND;
478 } else if (ut->uu_subcode & (1 << FP_PE)) {
479 sinfo64.si_code = FPE_FLTRES;
480 } else if (ut->uu_subcode & (1 << FP_IE)) {
481 sinfo64.si_code = FPE_FLTINV;
482 } else {
0c530ab8
A
483 sinfo64.si_code = FPE_NOOP;
484 }
485 break;
486 case SIGBUS:
487 sinfo64.si_code = BUS_ADRERR;
488 sinfo64.si_addr = ua_cr2;
489 break;
490 case SIGTRAP:
491 sinfo64.si_code = TRAP_BRKPT;
492 break;
493 case SIGSEGV:
494 sinfo64.si_addr = ua_cr2;
495
496 switch (ut->uu_code) {
2d21ac55
A
497 case EXC_I386_GPFLT:
498 /* CR2 is meaningless after GP fault */
499 /* XXX namespace clash! */
500 sinfo64.si_addr = 0ULL;
501 sinfo64.si_code = 0;
502 break;
0c530ab8
A
503 case KERN_PROTECTION_FAILURE:
504 sinfo64.si_code = SEGV_ACCERR;
505 break;
506 case KERN_INVALID_ADDRESS:
507 sinfo64.si_code = SEGV_MAPERR;
508 break;
509 default:
0c530ab8
A
510 sinfo64.si_code = FPE_NOOP;
511 }
512 break;
513 default:
2d21ac55
A
514 {
515 int status_and_exitcode;
516
517 /*
518 * All other signals need to fill out a minimum set of
519 * information for the siginfo structure passed into
520 * the signal handler, if SA_SIGINFO was specified.
521 *
522 * p->si_status actually contains both the status and
523 * the exit code; we save it off in its own variable
524 * for later breakdown.
525 */
526 proc_lock(p);
527 sinfo64.si_pid = p->si_pid;
528 p->si_pid =0;
529 status_and_exitcode = p->si_status;
530 p->si_status = 0;
531 sinfo64.si_uid = p->si_uid;
532 p->si_uid =0;
533 sinfo64.si_code = p->si_code;
534 p->si_code = 0;
535 proc_unlock(p);
536 if (sinfo64.si_code == CLD_EXITED) {
537 if (WIFEXITED(status_and_exitcode))
538 sinfo64.si_code = CLD_EXITED;
539 else if (WIFSIGNALED(status_and_exitcode)) {
540 if (WCOREDUMP(status_and_exitcode)) {
541 sinfo64.si_code = CLD_DUMPED;
542 status_and_exitcode = W_EXITCODE(status_and_exitcode,status_and_exitcode);
543 } else {
544 sinfo64.si_code = CLD_KILLED;
545 status_and_exitcode = W_EXITCODE(status_and_exitcode,status_and_exitcode);
546 }
547 }
548 }
549 /*
550 * The recorded status contains the exit code and the
551 * signal information, but the information to be passed
552 * in the siginfo to the handler is supposed to only
553 * contain the status, so we have to shift it out.
554 */
5ba3f43e
A
555 sinfo64.si_status = (WEXITSTATUS(status_and_exitcode) & 0x00FFFFFF) | (((uint32_t)(p->p_xhighbits) << 24) & 0xFF000000);
556 p->p_xhighbits = 0;
0c530ab8 557 break;
2d21ac55 558 }
0c530ab8
A
559 }
560 if (proc_is64bit(p)) {
b0d623f7
A
561 user64_siginfo_t sinfo64_user64;
562
563 bzero((caddr_t)&sinfo64_user64, sizeof(sinfo64_user64));
564
316670eb 565 siginfo_user_to_user64_x86(&sinfo64,&sinfo64_user64);
b0d623f7
A
566
567#if CONFIG_DTRACE
568 bzero((caddr_t)&(ut->t_dtrace_siginfo), sizeof(ut->t_dtrace_siginfo));
569
570 ut->t_dtrace_siginfo.si_signo = sinfo64.si_signo;
571 ut->t_dtrace_siginfo.si_code = sinfo64.si_code;
572 ut->t_dtrace_siginfo.si_pid = sinfo64.si_pid;
573 ut->t_dtrace_siginfo.si_uid = sinfo64.si_uid;
574 ut->t_dtrace_siginfo.si_status = sinfo64.si_status;
575 /* XXX truncates faulting address to void * on K32 */
576 ut->t_dtrace_siginfo.si_addr = CAST_DOWN(void *, sinfo64.si_addr);
577
578 /* Fire DTrace proc:::fault probe when signal is generated by hardware. */
579 switch (sig) {
580 case SIGILL: case SIGBUS: case SIGSEGV: case SIGFPE: case SIGTRAP:
581 DTRACE_PROC2(fault, int, (int)(ut->uu_code), siginfo_t *, &(ut->t_dtrace_siginfo));
582 break;
583 default:
584 break;
585 }
2d21ac55
A
586
587 /* XXX truncates catcher address to uintptr_t */
b0d623f7 588 DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &(ut->t_dtrace_siginfo),
2d21ac55 589 void (*)(void), CAST_DOWN(sig_t, ua_catcher));
b0d623f7 590#endif /* CONFIG_DTRACE */
2d21ac55 591
b0d623f7
A
592 if (copyout((caddr_t)&sinfo64_user64, ua_sip, sizeof (sinfo64_user64)))
593 goto bad;
9bccf70c 594
0c530ab8
A
595 flavor = x86_THREAD_STATE64;
596 state_count = x86_THREAD_STATE64_COUNT;
060df5ea 597 state = (void *)&mctxp->mctx_avx64.ss;
0c530ab8 598 } else {
b0d623f7
A
599 x86_thread_state32_t *tstate32;
600 user32_siginfo_t sinfo32;
601
602 bzero((caddr_t)&sinfo32, sizeof(sinfo32));
0c530ab8 603
316670eb 604 siginfo_user_to_user32_x86(&sinfo64,&sinfo32);
0c530ab8 605
b0d623f7
A
606#if CONFIG_DTRACE
607 bzero((caddr_t)&(ut->t_dtrace_siginfo), sizeof(ut->t_dtrace_siginfo));
2d21ac55 608
b0d623f7
A
609 ut->t_dtrace_siginfo.si_signo = sinfo32.si_signo;
610 ut->t_dtrace_siginfo.si_code = sinfo32.si_code;
611 ut->t_dtrace_siginfo.si_pid = sinfo32.si_pid;
612 ut->t_dtrace_siginfo.si_uid = sinfo32.si_uid;
613 ut->t_dtrace_siginfo.si_status = sinfo32.si_status;
614 ut->t_dtrace_siginfo.si_addr = CAST_DOWN(void *, sinfo32.si_addr);
615
616 /* Fire DTrace proc:::fault probe when signal is generated by hardware. */
617 switch (sig) {
618 case SIGILL: case SIGBUS: case SIGSEGV: case SIGFPE: case SIGTRAP:
619 DTRACE_PROC2(fault, int, (int)(ut->uu_code), siginfo_t *, &(ut->t_dtrace_siginfo));
620 break;
621 default:
622 break;
623 }
624
625 DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &(ut->t_dtrace_siginfo),
2d21ac55 626 void (*)(void), CAST_DOWN(sig_t, ua_catcher));
b0d623f7 627#endif /* CONFIG_DTRACE */
0c530ab8 628
b0d623f7
A
629 if (copyout((caddr_t)&sinfo32, ua_sip, sizeof (sinfo32)))
630 goto bad;
0c530ab8 631
060df5ea 632 tstate32 = &mctxp->mctx_avx32.ss;
b0d623f7
A
633
634 tstate32->eip = CAST_DOWN_EXPLICIT(user32_addr_t, trampact);
635 tstate32->esp = CAST_DOWN_EXPLICIT(user32_addr_t, ua_fp);
636
0c530ab8
A
637 tstate32->eflags = get_eflags_exportmask();
638
639 tstate32->cs = USER_CS;
640 tstate32->ss = USER_DS;
641 tstate32->ds = USER_DS;
642 tstate32->es = USER_DS;
643 tstate32->fs = NULL_SEG;
644 tstate32->gs = USER_CTHREAD;
645
646 flavor = x86_THREAD_STATE32;
647 state_count = x86_THREAD_STATE32_COUNT;
648 state = (void *)tstate32;
649 }
650 if (thread_setstatus(thread, flavor, (thread_state_t)state, state_count) != KERN_SUCCESS)
651 goto bad;
652 ml_fp_setvalid(FALSE);
9bccf70c 653
6d2010ae
A
654 /* Tell the PAL layer about the signal */
655 pal_set_signal_delivery( thread );
b0d623f7 656
2d21ac55
A
657 proc_lock(p);
658
9bccf70c 659 return;
1c79356b
A
660
661bad:
060df5ea 662
2d21ac55 663 proc_lock(p);
1c79356b
A
664 SIGACTION(p, SIGILL) = SIG_DFL;
665 sig = sigmask(SIGILL);
666 p->p_sigignore &= ~sig;
667 p->p_sigcatch &= ~sig;
9bccf70c 668 ut->uu_sigmask &= ~sig;
1c79356b 669 /* sendsig is called with signal lock held */
2d21ac55
A
670 proc_unlock(p);
671 psignal_locked(p, SIGILL);
672 proc_lock(p);
1c79356b
A
673 return;
674}
675
676/*
677 * System call to cleanup state after a signal
678 * has been taken. Reset signal mask and
679 * stack state from context left by sendsig (above).
680 * Return to previous pc and psl as specified by
681 * context left by sendsig. Check carefully to
682 * make sure that the user has not modified the
683 * psl to gain improper priviledges or to cause
684 * a machine fault.
685 */
0c530ab8 686
1c79356b 687int
2d21ac55 688sigreturn(struct proc *p, struct sigreturn_args *uap, __unused int *retval)
1c79356b 689{
060df5ea 690 union {
5ba3f43e
A
691 struct mcontext_avx32 mctx_avx32;
692 struct mcontext_avx64 mctx_avx64;
693#if !defined(RC_HIDE_XNU_J137)
694 struct mcontext_avx512_32 mctx_avx512_32;
695 struct mcontext_avx512_64 mctx_avx512_64;
696#endif
060df5ea
A
697 } mctx_store, *mctxp = &mctx_store;
698
0c530ab8 699 thread_t thread = current_thread();
9bccf70c 700 struct uthread * ut;
d9a64523 701 struct sigacts *ps = p->p_sigacts;
0c530ab8 702 int error;
0c530ab8 703 int onstack = 0;
5d5c5d0d 704
0c530ab8
A
705 mach_msg_type_number_t ts_count;
706 unsigned int ts_flavor;
707 void * ts;
708 mach_msg_type_number_t fs_count;
709 unsigned int fs_flavor;
710 void * fs;
5ba3f43e
A
711 int rval = EJUSTRETURN;
712 xstate_t sig_xstate;
d9a64523
A
713 uint32_t sigreturn_validation;
714 user_addr_t token_uctx;
715 kern_return_t kr;
5d5c5d0d 716
0c530ab8 717 ut = (struct uthread *)get_bsdthread_info(thread);
2d21ac55
A
718
719 /*
720 * If we are being asked to change the altstack flag on the thread, we
721 * just set/reset it and return (the uap->uctx is not used).
722 */
723 if ((unsigned int)uap->infostyle == UC_SET_ALT_STACK) {
724 ut->uu_sigstk.ss_flags |= SA_ONSTACK;
725 return (0);
726 } else if ((unsigned int)uap->infostyle == UC_RESET_ALT_STACK) {
727 ut->uu_sigstk.ss_flags &= ~SA_ONSTACK;
728 return (0);
729 }
4452a7af 730
060df5ea 731 bzero(mctxp, sizeof(*mctxp));
5ba3f43e
A
732
733 sig_xstate = current_xstate();
060df5ea 734
d9a64523
A
735 sigreturn_validation = atomic_load_explicit(
736 &ps->ps_sigreturn_validation, memory_order_relaxed);
737 token_uctx = uap->uctx;
738 kr = machine_thread_siguctx_pointer_convert_to_user(thread, &token_uctx);
739 assert(kr == KERN_SUCCESS);
740
0c530ab8
A
741 if (proc_is64bit(p)) {
742 struct user_ucontext64 uctx64;
d9a64523 743 user64_addr_t token;
4452a7af 744
0c530ab8
A
745 if ((error = copyin(uap->uctx, (void *)&uctx64, sizeof (uctx64))))
746 return(error);
4452a7af 747
5ba3f43e 748 if ((error = copyin(uctx64.uc_mcontext64, (void *)mctxp, thread_state64[sig_xstate].mcontext_size)))
0c530ab8 749 return(error);
4452a7af 750
0c530ab8
A
751 onstack = uctx64.uc_onstack & 01;
752 ut->uu_sigmask = uctx64.uc_sigmask & ~sigcantmask;
89b3af67 753
060df5ea 754 ts_flavor = x86_THREAD_STATE64;
0c530ab8 755 ts_count = x86_THREAD_STATE64_COUNT;
060df5ea 756 ts = (void *)&mctxp->mctx_avx64.ss;
0c530ab8 757
5ba3f43e
A
758 fs_flavor = thread_state64[sig_xstate].flavor;
759 fs_count = thread_state64[sig_xstate].state_count;
060df5ea 760 fs = (void *)&mctxp->mctx_avx64.fs;
0c530ab8 761
d9a64523
A
762 token = (user64_addr_t)token_uctx ^ (user64_addr_t)ps->ps_sigreturn_token;
763 if ((user64_addr_t)uap->token != token) {
764#if DEVELOPMENT || DEBUG
765 printf("process %s[%d] sigreturn token mismatch: received 0x%llx expected 0x%llx\n",
766 p->p_comm, p->p_pid, (user64_addr_t)uap->token, token);
767#endif /* DEVELOPMENT || DEBUG */
768 if (sigreturn_validation != PS_SIGRETURN_VALIDATION_DISABLED) {
769 rval = EINVAL;
770 }
771 }
0c530ab8 772 } else {
b0d623f7 773 struct user_ucontext32 uctx32;
d9a64523 774 user32_addr_t token;
0c530ab8
A
775
776 if ((error = copyin(uap->uctx, (void *)&uctx32, sizeof (uctx32))))
777 return(error);
778
5ba3f43e 779 if ((error = copyin(CAST_USER_ADDR_T(uctx32.uc_mcontext), (void *)mctxp, thread_state32[sig_xstate].mcontext_size)))
0c530ab8
A
780 return(error);
781
782 onstack = uctx32.uc_onstack & 01;
783 ut->uu_sigmask = uctx32.uc_sigmask & ~sigcantmask;
4452a7af 784
0c530ab8
A
785 ts_flavor = x86_THREAD_STATE32;
786 ts_count = x86_THREAD_STATE32_COUNT;
060df5ea
A
787 ts = (void *)&mctxp->mctx_avx32.ss;
788
5ba3f43e
A
789 fs_flavor = thread_state32[sig_xstate].flavor;
790 fs_count = thread_state32[sig_xstate].state_count;
060df5ea 791 fs = (void *)&mctxp->mctx_avx32.fs;
d9a64523
A
792
793 token = CAST_DOWN_EXPLICIT(user32_addr_t, uap->uctx) ^
794 CAST_DOWN_EXPLICIT(user32_addr_t, ps->ps_sigreturn_token);
795 if ((user32_addr_t)uap->token != token) {
796#if DEVELOPMENT || DEBUG
797 printf("process %s[%d] sigreturn token mismatch: received 0x%x expected 0x%x\n",
798 p->p_comm, p->p_pid, (user32_addr_t)uap->token, token);
799#endif /* DEVELOPMENT || DEBUG */
800 if (sigreturn_validation != PS_SIGRETURN_VALIDATION_DISABLED) {
801 rval = EINVAL;
802 }
803 }
91447636 804 }
2d21ac55
A
805
806 if (onstack)
807 ut->uu_sigstk.ss_flags |= SA_ONSTACK;
808 else
809 ut->uu_sigstk.ss_flags &= ~SA_ONSTACK;
810
0c530ab8
A
811 if (ut->uu_siglist & ~ut->uu_sigmask)
812 signal_setast(thread);
d9a64523
A
813
814 if (rval == EINVAL) {
815 goto error_ret;
816 }
817
0c530ab8 818 /*
2d21ac55
A
819 * thread_set_state() does all the needed checks for the passed in
820 * content
0c530ab8 821 */
060df5ea
A
822 if (thread_setstatus(thread, ts_flavor, ts, ts_count) != KERN_SUCCESS) {
823 rval = EINVAL;
d9a64523
A
824#if DEVELOPMENT || DEBUG
825 printf("process %s[%d] sigreturn thread_setstatus error %d\n",
826 p->p_comm, p->p_pid, rval);
827#endif /* DEVELOPMENT || DEBUG */
060df5ea
A
828 goto error_ret;
829 }
830
0c530ab8
A
831 ml_fp_setvalid(TRUE);
832
060df5ea
A
833 if (thread_setstatus(thread, fs_flavor, fs, fs_count) != KERN_SUCCESS) {
834 rval = EINVAL;
d9a64523
A
835#if DEVELOPMENT || DEBUG
836 printf("process %s[%d] sigreturn thread_setstatus error %d\n",
837 p->p_comm, p->p_pid, rval);
838#endif /* DEVELOPMENT || DEBUG */
060df5ea 839 goto error_ret;
1c79356b 840
060df5ea
A
841 }
842error_ret:
843 return rval;
1c79356b
A
844}
845
0c530ab8 846
1c79356b 847/*
d9a64523
A
848 * machine_exception() performs machine-dependent translation
849 * of a mach exception to a unix signal.
1c79356b 850 */
d9a64523
A
851int
852machine_exception(int exception,
853 mach_exception_code_t code,
854 __unused mach_exception_subcode_t subcode)
91447636 855{
2d21ac55 856 switch(exception) {
d9a64523
A
857 case EXC_BAD_ACCESS:
858 /* Map GP fault to SIGSEGV, otherwise defer to caller */
859 if (code == EXC_I386_GPFLT) {
860 return SIGSEGV;
861 }
2d21ac55 862 break;
2d21ac55 863
d9a64523
A
864 case EXC_BAD_INSTRUCTION:
865 return SIGILL;
2d21ac55 866
d9a64523
A
867 case EXC_ARITHMETIC:
868 return SIGFPE;
2d21ac55 869
d9a64523
A
870 case EXC_SOFTWARE:
871 if (code == EXC_I386_BOUND) {
872 /*
873 * Map #BR, the Bound Range Exceeded exception, to
874 * SIGTRAP.
875 */
876 return SIGTRAP;
877 }
2d21ac55 878 break;
2d21ac55 879 }
d9a64523
A
880
881 return 0;
91447636
A
882}
883