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