]> git.saurik.com Git - apple/xnu.git/blob - bsd/dev/arm/unix_signal.c
xnu-4903.231.4.tar.gz
[apple/xnu.git] / bsd / dev / arm / unix_signal.c
1 /*
2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
3 */
4
5 #include <mach/mach_types.h>
6 #include <mach/exception_types.h>
7
8 #include <sys/param.h>
9 #include <sys/proc_internal.h>
10 #include <sys/user.h>
11 #include <sys/signal.h>
12 #include <sys/ucontext.h>
13 #include <sys/sysproto.h>
14 #include <sys/systm.h>
15 #include <sys/ux_exception.h>
16
17 #include <arm/signal.h>
18 #include <sys/signalvar.h>
19 #include <sys/kdebug.h>
20 #include <sys/sdt.h>
21 #include <sys/wait.h>
22 #include <kern/thread.h>
23 #include <mach/arm/thread_status.h>
24 #include <arm/proc_reg.h>
25
26 #include <kern/assert.h>
27 #include <pexpert/pexpert.h>
28
29 extern struct arm_saved_state *get_user_regs(thread_t);
30 extern user_addr_t thread_get_cthread_self(void);
31 extern kern_return_t thread_getstatus(thread_t act, int flavor,
32 thread_state_t tstate, mach_msg_type_number_t *count);
33 extern kern_return_t thread_getstatus_to_user(thread_t act, int flavor,
34 thread_state_t tstate, mach_msg_type_number_t *count);
35 extern kern_return_t machine_thread_state_convert_to_user(thread_t act, int flavor,
36 thread_state_t tstate, mach_msg_type_number_t *count);
37 extern kern_return_t thread_setstatus(thread_t thread, int flavor,
38 thread_state_t tstate, mach_msg_type_number_t count);
39 extern kern_return_t thread_setstatus_from_user(thread_t thread, int flavor,
40 thread_state_t tstate, mach_msg_type_number_t count);
41 /* XXX Put these someplace smarter... */
42 typedef struct mcontext32 mcontext32_t;
43 typedef struct mcontext64 mcontext64_t;
44
45 /* Signal handler flavors supported */
46 /* These defns should match the Libc implmn */
47 #define UC_TRAD 1
48 #define UC_FLAVOR 30
49
50 /* The following are valid mcontext sizes */
51 #define UC_FLAVOR_SIZE32 ((ARM_THREAD_STATE_COUNT + ARM_EXCEPTION_STATE_COUNT + ARM_VFP_STATE_COUNT) * sizeof(int))
52 #define UC_FLAVOR_SIZE64 ((ARM_THREAD_STATE64_COUNT + ARM_EXCEPTION_STATE64_COUNT + ARM_NEON_STATE64_COUNT) * sizeof(int))
53
54 #if __arm64__
55 #define C_64_REDZONE_LEN 128
56 #endif
57
58 static int
59 sendsig_get_state32(thread_t th_act, arm_thread_state_t *ts, mcontext32_t *mcp)
60 {
61 void *tstate;
62 mach_msg_type_number_t state_count;
63
64 assert(!proc_is64bit_data(current_proc()));
65
66 tstate = (void *) ts;
67 state_count = ARM_THREAD_STATE_COUNT;
68 if (thread_getstatus(th_act, ARM_THREAD_STATE, (thread_state_t) tstate, &state_count) != KERN_SUCCESS)
69 return EINVAL;
70
71 mcp->ss = *ts;
72 tstate = (void *) &mcp->ss;
73 state_count = ARM_THREAD_STATE_COUNT;
74 if (machine_thread_state_convert_to_user(th_act, ARM_THREAD_STATE, (thread_state_t) tstate, &state_count) != KERN_SUCCESS)
75 return EINVAL;
76
77 tstate = (void *) &mcp->es;
78 state_count = ARM_EXCEPTION_STATE_COUNT;
79 if (thread_getstatus(th_act, ARM_EXCEPTION_STATE, (thread_state_t) tstate, &state_count) != KERN_SUCCESS)
80 return EINVAL;
81
82 tstate = (void *) &mcp->fs;
83 state_count = ARM_VFP_STATE_COUNT;
84 if (thread_getstatus_to_user(th_act, ARM_VFP_STATE, (thread_state_t) tstate, &state_count) != KERN_SUCCESS)
85 return EINVAL;
86
87 return 0;
88 }
89
90 #if defined(__arm64__)
91 struct user_sigframe64 {
92 /* We can pass the last two args in registers for ARM64 */
93 user64_siginfo_t sinfo;
94 struct user_ucontext64 uctx;
95 mcontext64_t mctx;
96 };
97
98 static int
99 sendsig_get_state64(thread_t th_act, arm_thread_state64_t *ts, mcontext64_t *mcp)
100 {
101 void *tstate;
102 mach_msg_type_number_t state_count;
103
104 assert(proc_is64bit_data(current_proc()));
105
106 tstate = (void *) ts;
107 state_count = ARM_THREAD_STATE64_COUNT;
108 if (thread_getstatus(th_act, ARM_THREAD_STATE64, (thread_state_t) tstate, &state_count) != KERN_SUCCESS)
109 return EINVAL;
110
111 mcp->ss = *ts;
112 tstate = (void *) &mcp->ss;
113 state_count = ARM_THREAD_STATE64_COUNT;
114 if (machine_thread_state_convert_to_user(th_act, ARM_THREAD_STATE64, (thread_state_t) tstate, &state_count) != KERN_SUCCESS)
115 return EINVAL;
116
117 tstate = (void *) &mcp->es;
118 state_count = ARM_EXCEPTION_STATE64_COUNT;
119 if (thread_getstatus(th_act, ARM_EXCEPTION_STATE64, (thread_state_t) tstate, &state_count) != KERN_SUCCESS)
120 return EINVAL;
121
122 tstate = (void *) &mcp->ns;
123 state_count = ARM_NEON_STATE64_COUNT;
124 if (thread_getstatus_to_user(th_act, ARM_NEON_STATE64, (thread_state_t) tstate, &state_count) != KERN_SUCCESS)
125 return EINVAL;
126
127 return 0;
128 }
129
130 static void
131 sendsig_fill_uctx64(user_ucontext64_t *uctx, int oonstack, int mask, user64_addr_t sp, user64_size_t stack_size, user64_addr_t p_mctx)
132 {
133 bzero(uctx, sizeof(*uctx));
134 uctx->uc_onstack = oonstack;
135 uctx->uc_sigmask = mask;
136 uctx->uc_stack.ss_sp = sp;
137 uctx->uc_stack.ss_size = stack_size;
138 if (oonstack)
139 uctx->uc_stack.ss_flags |= SS_ONSTACK;
140 uctx->uc_link = (user64_addr_t)0;
141 uctx->uc_mcsize = (user64_size_t) UC_FLAVOR_SIZE64;
142 uctx->uc_mcontext64 = (user64_addr_t) p_mctx;
143 }
144
145 static kern_return_t
146 sendsig_set_thread_state64(arm_thread_state64_t *regs,
147 user64_addr_t catcher, int infostyle, int sig, user64_addr_t p_sinfo,
148 user64_addr_t p_uctx, user64_addr_t token, user64_addr_t trampact, user64_addr_t sp, thread_t th_act)
149 {
150 assert(proc_is64bit_data(current_proc()));
151
152 regs->x[0] = catcher;
153 regs->x[1] = infostyle;
154 regs->x[2] = sig;
155 regs->x[3] = p_sinfo;
156 regs->x[4] = p_uctx;
157 regs->x[5] = token;
158 regs->pc = trampact;
159 regs->cpsr = PSR64_USER64_DEFAULT;
160 regs->sp = sp;
161
162 return thread_setstatus(th_act, ARM_THREAD_STATE64, (void *)regs, ARM_THREAD_STATE64_COUNT);
163 }
164 #endif /* defined(__arm64__) */
165
166 static void
167 sendsig_fill_uctx32(user_ucontext32_t *uctx, int oonstack, int mask, user_addr_t sp, user_size_t stack_size, user_addr_t p_mctx)
168 {
169 bzero(uctx, sizeof(*uctx));
170 uctx->uc_onstack = oonstack;
171 uctx->uc_sigmask = mask;
172 uctx->uc_stack.ss_sp = (user32_addr_t) sp;
173 uctx->uc_stack.ss_size = (user32_size_t) stack_size;
174 if (oonstack)
175 uctx->uc_stack.ss_flags |= SS_ONSTACK;
176 uctx->uc_link = (user32_addr_t)0;
177 uctx->uc_mcsize = (user32_size_t) UC_FLAVOR_SIZE32;
178 uctx->uc_mcontext = (user32_addr_t) p_mctx;
179 }
180
181 static kern_return_t
182 sendsig_set_thread_state32(arm_thread_state_t *regs,
183 user32_addr_t catcher, int infostyle, int sig, user32_addr_t p_sinfo,
184 user32_addr_t trampact, user32_addr_t sp, thread_t th_act)
185 {
186
187 assert(!proc_is64bit_data(current_proc()));
188
189 regs->r[0] = catcher;
190 regs->r[1] = infostyle;
191 regs->r[2] = sig;
192 regs->r[3] = p_sinfo;
193 if (trampact & 1) {
194 regs->pc = trampact & ~1;
195 #if defined(__arm64__)
196 regs->cpsr = PSR64_USER32_DEFAULT | PSR64_MODE_USER32_THUMB;
197 #elif defined(__arm__)
198 regs->cpsr = PSR_USERDFLT | PSR_TF;
199 #else
200 #error Unknown architeture.
201 #endif
202 } else {
203 regs->pc = trampact;
204 regs->cpsr = PSR_USERDFLT;
205 }
206 regs->sp = sp;
207
208 return thread_setstatus(th_act, ARM_THREAD_STATE, (void *)regs, ARM_THREAD_STATE_COUNT);
209 }
210
211 #if CONFIG_DTRACE
212 static void
213 sendsig_do_dtrace(uthread_t ut, user_siginfo_t *sinfo, int sig, user_addr_t catcher)
214 {
215 bzero((caddr_t)&(ut->t_dtrace_siginfo), sizeof(ut->t_dtrace_siginfo));
216
217 ut->t_dtrace_siginfo.si_signo = sinfo->si_signo;
218 ut->t_dtrace_siginfo.si_code = sinfo->si_code;
219 ut->t_dtrace_siginfo.si_pid = sinfo->si_pid;
220 ut->t_dtrace_siginfo.si_uid = sinfo->si_uid;
221 ut->t_dtrace_siginfo.si_status = sinfo->si_status;
222 /* XXX truncates faulting address to void * */
223 ut->t_dtrace_siginfo.si_addr = CAST_DOWN_EXPLICIT(void *, sinfo->si_addr);
224
225 /* Fire DTrace proc:::fault probe when signal is generated by hardware. */
226 switch (sig) {
227 case SIGILL: case SIGBUS: case SIGSEGV: case SIGFPE: case SIGTRAP:
228 DTRACE_PROC2(fault, int, (int)(ut->uu_code), siginfo_t *, &(ut->t_dtrace_siginfo));
229 break;
230 default:
231 break;
232 }
233
234 /* XXX truncates faulting address to uintptr_t */
235 DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &(ut->t_dtrace_siginfo),
236 void (*)(void), CAST_DOWN(sig_t, catcher));
237 }
238 #endif
239
240 struct user_sigframe32 {
241 user32_addr_t puctx;
242 user32_addr_t token;
243 user32_siginfo_t sinfo;
244 struct user_ucontext32 uctx;
245 mcontext32_t mctx;
246 };
247
248 /*
249 * Send an interrupt to process.
250 *
251 */
252 void
253 sendsig(
254 struct proc * p,
255 user_addr_t catcher,
256 int sig,
257 int mask,
258 __unused uint32_t code
259 )
260 {
261 union {
262 struct ts32 {
263 arm_thread_state_t ss;
264 } ts32;
265 #if defined(__arm64__)
266 struct ts64 {
267 arm_thread_state64_t ss;
268 } ts64;
269 #endif
270 } ts;
271 union {
272 struct user_sigframe32 uf32;
273 #if defined(__arm64__)
274 struct user_sigframe64 uf64;
275 #endif
276 } user_frame;
277
278 user_siginfo_t sinfo;
279 user_addr_t sp = 0, trampact;
280 struct sigacts *ps = p->p_sigacts;
281 int oonstack, infostyle;
282 thread_t th_act;
283 struct uthread *ut;
284 user_size_t stack_size = 0;
285 user_addr_t p_uctx, token_uctx;
286 kern_return_t kr;
287
288 th_act = current_thread();
289 ut = get_bsdthread_info(th_act);
290
291 bzero(&ts, sizeof(ts));
292 bzero(&user_frame, sizeof(user_frame));
293
294 if (p->p_sigacts->ps_siginfo & sigmask(sig))
295 infostyle = UC_FLAVOR;
296 else
297 infostyle = UC_TRAD;
298
299 trampact = ps->ps_trampact[sig];
300 oonstack = ps->ps_sigstk.ss_flags & SA_ONSTACK;
301
302 /*
303 * Get sundry thread state.
304 */
305 if (proc_is64bit_data(p)) {
306 #ifdef __arm64__
307 if (sendsig_get_state64(th_act, &ts.ts64.ss, &user_frame.uf64.mctx) != 0) {
308 goto bad2;
309 }
310 #else
311 panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
312 #endif
313 } else {
314 if (sendsig_get_state32(th_act, &ts.ts32.ss, &user_frame.uf32.mctx) != 0) {
315 goto bad2;
316 }
317 }
318
319 /*
320 * Figure out where our new stack lives.
321 */
322 if ((ps->ps_flags & SAS_ALTSTACK) && !oonstack &&
323 (ps->ps_sigonstack & sigmask(sig))) {
324 sp = ps->ps_sigstk.ss_sp;
325 sp += ps->ps_sigstk.ss_size;
326 stack_size = ps->ps_sigstk.ss_size;
327 ps->ps_sigstk.ss_flags |= SA_ONSTACK;
328 } else {
329 /*
330 * Get stack pointer, and allocate enough space
331 * for signal handler data.
332 */
333 if (proc_is64bit_data(p)) {
334 #if defined(__arm64__)
335 sp = CAST_USER_ADDR_T(ts.ts64.ss.sp);
336 sp = (sp - sizeof(user_frame.uf64) - C_64_REDZONE_LEN) & ~0xf; /* Make sure to align to 16 bytes and respect red zone */
337 #else
338 panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
339 #endif
340 } else {
341 sp = CAST_USER_ADDR_T(ts.ts32.ss.sp);
342 sp -= sizeof(user_frame.uf32);
343 #if defined(__arm__) && (__BIGGEST_ALIGNMENT__ > 4)
344 sp &= ~0xf; /* Make sure to align to 16 bytes for armv7k */
345 #endif
346 }
347 }
348
349 proc_unlock(p);
350
351 /*
352 * Fill in ucontext (points to mcontext, i.e. thread states).
353 */
354 if (proc_is64bit_data(p)) {
355 #if defined(__arm64__)
356 sendsig_fill_uctx64(&user_frame.uf64.uctx, oonstack, mask, sp, (user64_size_t)stack_size,
357 (user64_addr_t)&((struct user_sigframe64*)sp)->mctx);
358 #else
359 panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
360 #endif
361 } else {
362 sendsig_fill_uctx32(&user_frame.uf32.uctx, oonstack, mask, sp, (user32_size_t)stack_size,
363 (user32_addr_t)&((struct user_sigframe32*)sp)->mctx);
364 }
365
366 /*
367 * Setup siginfo.
368 */
369 bzero((caddr_t) & sinfo, sizeof(sinfo));
370 sinfo.si_signo = sig;
371
372 if (proc_is64bit_data(p)) {
373 #if defined(__arm64__)
374 sinfo.si_addr = ts.ts64.ss.pc;
375 sinfo.pad[0] = ts.ts64.ss.sp;
376 #else
377 panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
378 #endif
379 } else {
380 sinfo.si_addr = ts.ts32.ss.pc;
381 sinfo.pad[0] = ts.ts32.ss.sp;
382 }
383
384 switch (sig) {
385 case SIGILL:
386 #ifdef BER_XXX
387 if (mctx.ss.srr1 & (1 << (31 - SRR1_PRG_ILL_INS_BIT)))
388 sinfo.si_code = ILL_ILLOPC;
389 else if (mctx.ss.srr1 & (1 << (31 - SRR1_PRG_PRV_INS_BIT)))
390 sinfo.si_code = ILL_PRVOPC;
391 else if (mctx.ss.srr1 & (1 << (31 - SRR1_PRG_TRAP_BIT)))
392 sinfo.si_code = ILL_ILLTRP;
393 else
394 sinfo.si_code = ILL_NOOP;
395 #else
396 sinfo.si_code = ILL_ILLTRP;
397 #endif
398 break;
399
400 case SIGFPE:
401 break;
402
403 case SIGBUS:
404 if (proc_is64bit_data(p)) {
405 #if defined(__arm64__)
406 sinfo.si_addr = user_frame.uf64.mctx.es.far;
407 #else
408 panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
409 #endif
410 } else {
411 sinfo.si_addr = user_frame.uf32.mctx.es.far;
412 }
413
414 sinfo.si_code = BUS_ADRALN;
415 break;
416
417 case SIGSEGV:
418 if (proc_is64bit_data(p)) {
419 #if defined(__arm64__)
420 sinfo.si_addr = user_frame.uf64.mctx.es.far;
421 #else
422 panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
423 #endif
424 } else {
425 sinfo.si_addr = user_frame.uf32.mctx.es.far;
426 }
427
428 #ifdef BER_XXX
429 /* First check in srr1 and then in dsisr */
430 if (mctx.ss.srr1 & (1 << (31 - DSISR_PROT_BIT)))
431 sinfo.si_code = SEGV_ACCERR;
432 else if (mctx.es.dsisr & (1 << (31 - DSISR_PROT_BIT)))
433 sinfo.si_code = SEGV_ACCERR;
434 else
435 sinfo.si_code = SEGV_MAPERR;
436 #else
437 sinfo.si_code = SEGV_ACCERR;
438 #endif
439 break;
440
441 default:
442 {
443 int status_and_exitcode;
444
445 /*
446 * All other signals need to fill out a minimum set of
447 * information for the siginfo structure passed into
448 * the signal handler, if SA_SIGINFO was specified.
449 *
450 * p->si_status actually contains both the status and
451 * the exit code; we save it off in its own variable
452 * for later breakdown.
453 */
454 proc_lock(p);
455 sinfo.si_pid = p->si_pid;
456 p->si_pid = 0;
457 status_and_exitcode = p->si_status;
458 p->si_status = 0;
459 sinfo.si_uid = p->si_uid;
460 p->si_uid = 0;
461 sinfo.si_code = p->si_code;
462 p->si_code = 0;
463 proc_unlock(p);
464 if (sinfo.si_code == CLD_EXITED) {
465 if (WIFEXITED(status_and_exitcode))
466 sinfo.si_code = CLD_EXITED;
467 else if (WIFSIGNALED(status_and_exitcode)) {
468 if (WCOREDUMP(status_and_exitcode)) {
469 sinfo.si_code = CLD_DUMPED;
470 status_and_exitcode = W_EXITCODE(status_and_exitcode,status_and_exitcode);
471 } else {
472 sinfo.si_code = CLD_KILLED;
473 status_and_exitcode = W_EXITCODE(status_and_exitcode,status_and_exitcode);
474 }
475 }
476 }
477 /*
478 * The recorded status contains the exit code and the
479 * signal information, but the information to be passed
480 * in the siginfo to the handler is supposed to only
481 * contain the status, so we have to shift it out.
482 */
483 sinfo.si_status = (WEXITSTATUS(status_and_exitcode) & 0x00FFFFFF) | (((uint32_t)(p->p_xhighbits) << 24) & 0xFF000000);
484 p->p_xhighbits = 0;
485 break;
486 }
487 }
488
489 #if CONFIG_DTRACE
490 sendsig_do_dtrace(ut, &sinfo, sig, catcher);
491 #endif /* CONFIG_DTRACE */
492
493 /*
494 * Copy signal-handling frame out to user space, set thread state.
495 */
496 if (proc_is64bit_data(p)) {
497 #if defined(__arm64__)
498 user64_addr_t token;
499
500 /*
501 * mctx filled in when we get state. uctx filled in by
502 * sendsig_fill_uctx64(). We fill in the sinfo now.
503 */
504 siginfo_user_to_user64(&sinfo, &user_frame.uf64.sinfo);
505
506 p_uctx = (user_addr_t)&((struct user_sigframe64*)sp)->uctx;
507 /*
508 * Generate the validation token for sigreturn
509 */
510 token_uctx = p_uctx;
511 kr = machine_thread_siguctx_pointer_convert_to_user(th_act, &token_uctx);
512 assert(kr == KERN_SUCCESS);
513 token = (user64_addr_t)token_uctx ^ (user64_addr_t)ps->ps_sigreturn_token;
514
515 if (copyout(&user_frame.uf64, sp, sizeof(user_frame.uf64)) != 0) {
516 goto bad;
517 }
518
519 if (sendsig_set_thread_state64(&ts.ts64.ss,
520 catcher, infostyle, sig, (user64_addr_t)&((struct user_sigframe64*)sp)->sinfo,
521 (user64_addr_t)p_uctx, token, trampact, sp, th_act) != KERN_SUCCESS)
522 goto bad;
523
524 #else
525 panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
526 #endif
527 } else {
528 user32_addr_t token;
529
530 /*
531 * mctx filled in when we get state. uctx filled in by
532 * sendsig_fill_uctx32(). We fill in the sinfo, *pointer*
533 * to uctx and token now.
534 */
535 siginfo_user_to_user32(&sinfo, &user_frame.uf32.sinfo);
536
537 p_uctx = (user_addr_t)&((struct user_sigframe32*)sp)->uctx;
538 /*
539 * Generate the validation token for sigreturn
540 */
541 token_uctx = (user_addr_t)p_uctx;
542 kr = machine_thread_siguctx_pointer_convert_to_user(th_act, &token_uctx);
543 assert(kr == KERN_SUCCESS);
544 token = (user32_addr_t)token_uctx ^ (user32_addr_t)ps->ps_sigreturn_token;
545
546 user_frame.uf32.puctx = (user32_addr_t)p_uctx;
547 user_frame.uf32.token = token;
548
549 if (copyout(&user_frame.uf32, sp, sizeof(user_frame.uf32)) != 0) {
550 goto bad;
551 }
552
553 if (sendsig_set_thread_state32(&ts.ts32.ss,
554 CAST_DOWN_EXPLICIT(user32_addr_t, catcher), infostyle, sig, (user32_addr_t)&((struct user_sigframe32*)sp)->sinfo,
555 CAST_DOWN_EXPLICIT(user32_addr_t, trampact), CAST_DOWN_EXPLICIT(user32_addr_t, sp), th_act) != KERN_SUCCESS)
556 goto bad;
557 }
558
559 proc_lock(p);
560 return;
561
562 bad:
563 proc_lock(p);
564 bad2:
565 SIGACTION(p, SIGILL) = SIG_DFL;
566 sig = sigmask(SIGILL);
567 p->p_sigignore &= ~sig;
568 p->p_sigcatch &= ~sig;
569 ut->uu_sigmask &= ~sig;
570 /* sendsig is called with signal lock held */
571 proc_unlock(p);
572 psignal_locked(p, SIGILL);
573 proc_lock(p);
574 }
575
576 /*
577 * System call to cleanup state after a signal
578 * has been taken. Reset signal mask and
579 * stack state from context left by sendsig (above).
580 * Return to previous * context left by sendsig.
581 * Check carefully to * make sure that the user has not
582 * modified the * spr to gain improper priviledges.
583 */
584
585 static int
586 sigreturn_copyin_ctx32(struct user_ucontext32 *uctx, mcontext32_t *mctx, user_addr_t uctx_addr)
587 {
588 int error;
589
590 assert(!proc_is64bit_data(current_proc()));
591
592 error = copyin(uctx_addr, uctx, sizeof(*uctx));
593 if (error) {
594 return (error);
595 }
596
597 /* validate the machine context size */
598 switch (uctx->uc_mcsize) {
599 case UC_FLAVOR_SIZE32:
600 break;
601 default:
602 return (EINVAL);
603 }
604
605 assert(uctx->uc_mcsize == sizeof(*mctx));
606 error = copyin((user_addr_t)uctx->uc_mcontext, mctx, uctx->uc_mcsize);
607 if (error) {
608 return (error);
609 }
610
611 return 0;
612 }
613
614 static int
615 sigreturn_set_state32(thread_t th_act, mcontext32_t *mctx)
616 {
617 assert(!proc_is64bit_data(current_proc()));
618
619 /* validate the thread state, set/reset appropriate mode bits in cpsr */
620 #if defined(__arm__)
621 mctx->ss.cpsr = (mctx->ss.cpsr & ~PSR_MODE_MASK) | PSR_USERDFLT;
622 #elif defined(__arm64__)
623 mctx->ss.cpsr = (mctx->ss.cpsr & ~PSR64_MODE_MASK) | PSR64_USER32_DEFAULT;
624 #else
625 #error Unknown architecture.
626 #endif
627
628 if (thread_setstatus_from_user(th_act, ARM_THREAD_STATE, (void *)&mctx->ss, ARM_THREAD_STATE_COUNT) != KERN_SUCCESS) {
629 return (EINVAL);
630 }
631 if (thread_setstatus_from_user(th_act, ARM_VFP_STATE, (void *)&mctx->fs, ARM_VFP_STATE_COUNT) != KERN_SUCCESS) {
632 return (EINVAL);
633 }
634
635 return 0;
636 }
637
638 #if defined(__arm64__)
639 static int
640 sigreturn_copyin_ctx64(struct user_ucontext64 *uctx, mcontext64_t *mctx, user_addr_t uctx_addr)
641 {
642 int error;
643
644 assert(proc_is64bit_data(current_proc()));
645
646 error = copyin(uctx_addr, uctx, sizeof(*uctx));
647 if (error) {
648 return (error);
649 }
650
651 /* validate the machine context size */
652 switch (uctx->uc_mcsize) {
653 case UC_FLAVOR_SIZE64:
654 break;
655 default:
656 return (EINVAL);
657 }
658
659 assert(uctx->uc_mcsize == sizeof(*mctx));
660 error = copyin((user_addr_t)uctx->uc_mcontext64, mctx, uctx->uc_mcsize);
661 if (error) {
662 return (error);
663 }
664
665 return 0;
666 }
667
668 static int
669 sigreturn_set_state64(thread_t th_act, mcontext64_t *mctx)
670 {
671 assert(proc_is64bit_data(current_proc()));
672
673 /* validate the thread state, set/reset appropriate mode bits in cpsr */
674 mctx->ss.cpsr = (mctx->ss.cpsr & ~PSR64_MODE_MASK) | PSR64_USER64_DEFAULT;
675
676 if (thread_setstatus_from_user(th_act, ARM_THREAD_STATE64, (void *)&mctx->ss, ARM_THREAD_STATE64_COUNT) != KERN_SUCCESS) {
677 return (EINVAL);
678 }
679 if (thread_setstatus_from_user(th_act, ARM_NEON_STATE64, (void *)&mctx->ns, ARM_NEON_STATE64_COUNT) != KERN_SUCCESS) {
680 return (EINVAL);
681 }
682
683 return 0;
684 }
685 #endif /* defined(__arm64__) */
686
687 /* ARGSUSED */
688 int
689 sigreturn(
690 struct proc * p,
691 struct sigreturn_args * uap,
692 __unused int *retval)
693 {
694 union {
695 user_ucontext32_t uc32;
696 #if defined(__arm64__)
697 user_ucontext64_t uc64;
698 #endif
699 } uctx;
700
701 union {
702 mcontext32_t mc32;
703 #if defined(__arm64__)
704 mcontext64_t mc64;
705 #endif
706 } mctx;
707
708 struct sigacts *ps = p->p_sigacts;
709 int error, sigmask = 0, onstack = 0;
710 thread_t th_act;
711 struct uthread *ut;
712 uint32_t sigreturn_validation;
713 user_addr_t token_uctx;
714 kern_return_t kr;
715
716 th_act = current_thread();
717 ut = (struct uthread *) get_bsdthread_info(th_act);
718
719 if (proc_is64bit_data(p)) {
720 #if defined(__arm64__)
721 error = sigreturn_copyin_ctx64(&uctx.uc64, &mctx.mc64, uap->uctx);
722 if (error != 0) {
723 return error;
724 }
725
726 onstack = uctx.uc64.uc_onstack;
727 sigmask = uctx.uc64.uc_sigmask;
728 #else
729 panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
730 #endif
731 } else {
732 error = sigreturn_copyin_ctx32(&uctx.uc32, &mctx.mc32, uap->uctx);
733 if (error != 0) {
734 return error;
735 }
736
737 onstack = uctx.uc32.uc_onstack;
738 sigmask = uctx.uc32.uc_sigmask;
739 }
740
741 if ((onstack & 01))
742 p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
743 else
744 p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
745
746 ut->uu_sigmask = sigmask & ~sigcantmask;
747 if (ut->uu_siglist & ~ut->uu_sigmask)
748 signal_setast(current_thread());
749
750 sigreturn_validation = atomic_load_explicit(
751 &ps->ps_sigreturn_validation, memory_order_relaxed);
752 token_uctx = uap->uctx;
753 kr = machine_thread_siguctx_pointer_convert_to_user(th_act, &token_uctx);
754 assert(kr == KERN_SUCCESS);
755
756 if (proc_is64bit_data(p)) {
757 #if defined(__arm64__)
758 user64_addr_t token;
759 token = (user64_addr_t)token_uctx ^ (user64_addr_t)ps->ps_sigreturn_token;
760 if ((user64_addr_t)uap->token != token) {
761 #if DEVELOPMENT || DEBUG
762 printf("process %s[%d] sigreturn token mismatch: received 0x%llx expected 0x%llx\n",
763 p->p_comm, p->p_pid, (user64_addr_t)uap->token, token);
764 #endif /* DEVELOPMENT || DEBUG */
765 if (sigreturn_validation != PS_SIGRETURN_VALIDATION_DISABLED) {
766 return EINVAL;
767 }
768 }
769 error = sigreturn_set_state64(th_act, &mctx.mc64);
770 if (error != 0) {
771 #if DEVELOPMENT || DEBUG
772 printf("process %s[%d] sigreturn set_state64 error %d\n",
773 p->p_comm, p->p_pid, error);
774 #endif /* DEVELOPMENT || DEBUG */
775 return error;
776 }
777 #else
778 panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
779 #endif
780 } else {
781 user32_addr_t token;
782 token = (user32_addr_t)token_uctx ^ (user32_addr_t)ps->ps_sigreturn_token;
783 if ((user32_addr_t)uap->token != token) {
784 #if DEVELOPMENT || DEBUG
785 printf("process %s[%d] sigreturn token mismatch: received 0x%x expected 0x%x\n",
786 p->p_comm, p->p_pid, (user32_addr_t)uap->token, token);
787 #endif /* DEVELOPMENT || DEBUG */
788 if (sigreturn_validation != PS_SIGRETURN_VALIDATION_DISABLED) {
789 return EINVAL;
790 }
791 }
792 error = sigreturn_set_state32(th_act, &mctx.mc32);
793 if (error != 0) {
794 #if DEVELOPMENT || DEBUG
795 printf("process %s[%d] sigreturn sigreturn_set_state32 error %d\n",
796 p->p_comm, p->p_pid, error);
797 #endif /* DEVELOPMENT || DEBUG */
798 return error;
799 }
800 }
801
802 return (EJUSTRETURN);
803 }
804
805 /*
806 * machine_exception() performs machine-dependent translation
807 * of a mach exception to a unix signal.
808 */
809 int
810 machine_exception(int exception,
811 __unused mach_exception_code_t code,
812 __unused mach_exception_subcode_t subcode)
813 {
814 switch (exception) {
815 case EXC_BAD_INSTRUCTION:
816 return SIGILL;
817
818 case EXC_ARITHMETIC:
819 return SIGFPE;
820 }
821
822 return 0;
823 }
824