| 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 |  | 
|---|
| 50 | #include <sys/ux_exception.h> | 
|---|
| 51 |  | 
|---|
| 52 | #include <mach/thread_act.h>	/* for thread_abort_safely */ | 
|---|
| 53 | #include <mach/thread_status.h> | 
|---|
| 54 |  | 
|---|
| 55 | #include <i386/eflags.h> | 
|---|
| 56 | #include <i386/psl.h> | 
|---|
| 57 | #include <i386/machine_routines.h> | 
|---|
| 58 | #include <i386/seg.h> | 
|---|
| 59 | #include <i386/fpu.h> | 
|---|
| 60 |  | 
|---|
| 61 | #include <machine/pal_routines.h> | 
|---|
| 62 |  | 
|---|
| 63 | #include <sys/kdebug.h> | 
|---|
| 64 | #include <sys/sdt.h> | 
|---|
| 65 |  | 
|---|
| 66 |  | 
|---|
| 67 | /* Forward: */ | 
|---|
| 68 | extern kern_return_t thread_getstatus(thread_t act, int flavor, | 
|---|
| 69 | thread_state_t tstate, mach_msg_type_number_t *count); | 
|---|
| 70 | extern kern_return_t thread_setstatus(thread_t thread, int flavor, | 
|---|
| 71 | thread_state_t tstate, mach_msg_type_number_t count); | 
|---|
| 72 |  | 
|---|
| 73 | /* Signal handler flavors supported */ | 
|---|
| 74 | /* These defns should match the Libc implmn */ | 
|---|
| 75 | #define UC_TRAD			1 | 
|---|
| 76 | #define UC_FLAVOR		30 | 
|---|
| 77 | #define	UC_SET_ALT_STACK	0x40000000 | 
|---|
| 78 | #define	UC_RESET_ALT_STACK	0x80000000 | 
|---|
| 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)))) | 
|---|
| 85 |  | 
|---|
| 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 | */ | 
|---|
| 96 | struct sigframe32 { | 
|---|
| 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 */ | 
|---|
| 103 | user32_addr_t	token; | 
|---|
| 104 | }; | 
|---|
| 105 |  | 
|---|
| 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 | */ | 
|---|
| 110 | typedef struct { | 
|---|
| 111 | int flavor;		natural_t state_count;		size_t	mcontext_size; | 
|---|
| 112 | } xstate_info_t; | 
|---|
| 113 | static 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 | }; | 
|---|
| 120 | static 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 |  | 
|---|
| 128 | /* | 
|---|
| 129 | * NOTE: Source and target may *NOT* overlap! | 
|---|
| 130 | * XXX: Unify with bsd/kern/kern_exit.c | 
|---|
| 131 | */ | 
|---|
| 132 | static void | 
|---|
| 133 | siginfo_user_to_user32_x86(user_siginfo_t *in, user32_siginfo_t *out) | 
|---|
| 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 | } | 
|---|
| 147 |  | 
|---|
| 148 | static void | 
|---|
| 149 | siginfo_user_to_user64_x86(user_siginfo_t *in, user64_siginfo_t *out) | 
|---|
| 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 | } | 
|---|
| 162 |  | 
|---|
| 163 | void | 
|---|
| 164 | sendsig(struct proc *p, user_addr_t ua_catcher, int sig, int mask, __unused uint32_t code) | 
|---|
| 165 | { | 
|---|
| 166 | union { | 
|---|
| 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 | 
|---|
| 173 | } mctx_store, *mctxp = &mctx_store; | 
|---|
| 174 |  | 
|---|
| 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 |  | 
|---|
| 183 | struct sigacts *ps = p->p_sigacts; | 
|---|
| 184 | int oonstack, flavor; | 
|---|
| 185 | user_addr_t trampact; | 
|---|
| 186 | int sigonstack; | 
|---|
| 187 | void * state; | 
|---|
| 188 | mach_msg_type_number_t state_count; | 
|---|
| 189 |  | 
|---|
| 190 | thread_t thread; | 
|---|
| 191 | struct uthread * ut; | 
|---|
| 192 | int stack_size = 0; | 
|---|
| 193 | int infostyle = UC_TRAD; | 
|---|
| 194 | xstate_t	sig_xstate; | 
|---|
| 195 | user_addr_t     token_uctx; | 
|---|
| 196 | kern_return_t   kr; | 
|---|
| 197 |  | 
|---|
| 198 | thread = current_thread(); | 
|---|
| 199 | ut = get_bsdthread_info(thread); | 
|---|
| 200 |  | 
|---|
| 201 | if (p->p_sigacts->ps_siginfo & sigmask(sig)) | 
|---|
| 202 | infostyle = UC_FLAVOR; | 
|---|
| 203 |  | 
|---|
| 204 | oonstack = ut->uu_sigstk.ss_flags & SA_ONSTACK; | 
|---|
| 205 | trampact = ps->ps_trampact[sig]; | 
|---|
| 206 | sigonstack = (ps->ps_sigonstack & sigmask(sig)); | 
|---|
| 207 |  | 
|---|
| 208 | /* | 
|---|
| 209 | * init siginfo | 
|---|
| 210 | */ | 
|---|
| 211 | proc_unlock(p); | 
|---|
| 212 |  | 
|---|
| 213 | bzero((caddr_t)&sinfo64, sizeof(sinfo64)); | 
|---|
| 214 | sinfo64.si_signo = sig; | 
|---|
| 215 |  | 
|---|
| 216 | bzero(mctxp, sizeof(*mctxp)); | 
|---|
| 217 |  | 
|---|
| 218 | sig_xstate = current_xstate(); | 
|---|
| 219 |  | 
|---|
| 220 | if (proc_is64bit(p)) { | 
|---|
| 221 | x86_thread_state64_t	*tstate64; | 
|---|
| 222 | struct user_ucontext64 	uctx64; | 
|---|
| 223 | user64_addr_t token; | 
|---|
| 224 |  | 
|---|
| 225 | flavor = x86_THREAD_STATE64; | 
|---|
| 226 | state_count = x86_THREAD_STATE64_COUNT; | 
|---|
| 227 | state = (void *)&mctxp->mctx_avx64.ss; | 
|---|
| 228 | if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS) | 
|---|
| 229 | goto bad; | 
|---|
| 230 |  | 
|---|
| 231 | flavor      = thread_state64[sig_xstate].flavor; | 
|---|
| 232 | state_count = thread_state64[sig_xstate].state_count; | 
|---|
| 233 | state = (void *)&mctxp->mctx_avx64.fs; | 
|---|
| 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; | 
|---|
| 239 | state = (void *)&mctxp->mctx_avx64.es; | 
|---|
| 240 | if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS) | 
|---|
| 241 | goto bad; | 
|---|
| 242 |  | 
|---|
| 243 | tstate64 = &mctxp->mctx_avx64.ss; | 
|---|
| 244 |  | 
|---|
| 245 | /* figure out where our new stack lives */ | 
|---|
| 246 | if ((ut->uu_flag & UT_ALTSTACK) && !oonstack && | 
|---|
| 247 | (sigonstack)) { | 
|---|
| 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 { | 
|---|
| 253 | ua_sp = tstate64->rsp; | 
|---|
| 254 | } | 
|---|
| 255 | ua_cr2 = mctxp->mctx_avx64.es.faultvaddr; | 
|---|
| 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 |  | 
|---|
| 263 | ua_sp -= sizeof (user64_siginfo_t); | 
|---|
| 264 | ua_sip = ua_sp; | 
|---|
| 265 |  | 
|---|
| 266 | ua_sp -= thread_state64[sig_xstate].mcontext_size; | 
|---|
| 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 |  | 
|---|
| 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 |  | 
|---|
| 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 |  | 
|---|
| 303 | uctx64.uc_mcsize = thread_state64[sig_xstate].mcontext_size; | 
|---|
| 304 | uctx64.uc_mcontext64 = ua_mctxp; | 
|---|
| 305 |  | 
|---|
| 306 | if (copyout((caddr_t)&uctx64, ua_uctxp, sizeof (uctx64))) | 
|---|
| 307 | goto bad; | 
|---|
| 308 |  | 
|---|
| 309 | if (copyout((caddr_t)&mctx_store, ua_mctxp, thread_state64[sig_xstate].mcontext_size)) | 
|---|
| 310 | goto bad; | 
|---|
| 311 |  | 
|---|
| 312 | sinfo64.pad[0]  = tstate64->rsp; | 
|---|
| 313 | sinfo64.si_addr = tstate64->rip; | 
|---|
| 314 |  | 
|---|
| 315 | tstate64->rip = trampact; | 
|---|
| 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; | 
|---|
| 334 | tstate64->r9  = token; | 
|---|
| 335 | } else { | 
|---|
| 336 | x86_thread_state32_t	*tstate32; | 
|---|
| 337 | struct user_ucontext32 	uctx32; | 
|---|
| 338 | struct sigframe32	frame32; | 
|---|
| 339 | user32_addr_t token; | 
|---|
| 340 |  | 
|---|
| 341 | flavor = x86_THREAD_STATE32; | 
|---|
| 342 | state_count = x86_THREAD_STATE32_COUNT; | 
|---|
| 343 | state = (void *)&mctxp->mctx_avx32.ss; | 
|---|
| 344 | if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS) | 
|---|
| 345 | goto bad; | 
|---|
| 346 |  | 
|---|
| 347 | flavor = thread_state32[sig_xstate].flavor; | 
|---|
| 348 | state_count = thread_state32[sig_xstate].state_count; | 
|---|
| 349 | state = (void *)&mctxp->mctx_avx32.fs; | 
|---|
| 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; | 
|---|
| 355 | state = (void *)&mctxp->mctx_avx32.es; | 
|---|
| 356 | if (thread_getstatus(thread, flavor, (thread_state_t)state, &state_count) != KERN_SUCCESS) | 
|---|
| 357 | goto bad; | 
|---|
| 358 |  | 
|---|
| 359 | tstate32 = &mctxp->mctx_avx32.ss; | 
|---|
| 360 |  | 
|---|
| 361 | /* figure out where our new stack lives */ | 
|---|
| 362 | if ((ut->uu_flag & UT_ALTSTACK) && !oonstack && | 
|---|
| 363 | (sigonstack)) { | 
|---|
| 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 { | 
|---|
| 369 | ua_sp = tstate32->esp; | 
|---|
| 370 | } | 
|---|
| 371 | ua_cr2 = mctxp->mctx_avx32.es.faultvaddr; | 
|---|
| 372 |  | 
|---|
| 373 | ua_sp -= sizeof (struct user_ucontext32); | 
|---|
| 374 | ua_uctxp = ua_sp;			 // someone tramples the first word! | 
|---|
| 375 |  | 
|---|
| 376 | ua_sp -= sizeof (user32_siginfo_t); | 
|---|
| 377 | ua_sip = ua_sp; | 
|---|
| 378 |  | 
|---|
| 379 | ua_sp -= thread_state32[sig_xstate].mcontext_size; | 
|---|
| 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 |  | 
|---|
| 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 |  | 
|---|
| 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; | 
|---|
| 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); | 
|---|
| 416 | frame32.token = token; | 
|---|
| 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; | 
|---|
| 428 | uctx32.uc_stack.ss_sp = CAST_DOWN_EXPLICIT(user32_addr_t, ua_fp); | 
|---|
| 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 |  | 
|---|
| 435 | uctx32.uc_mcsize = thread_state64[sig_xstate].mcontext_size; | 
|---|
| 436 |  | 
|---|
| 437 | uctx32.uc_mcontext = CAST_DOWN_EXPLICIT(user32_addr_t, ua_mctxp); | 
|---|
| 438 |  | 
|---|
| 439 | if (copyout((caddr_t)&uctx32, ua_uctxp, sizeof (uctx32))) | 
|---|
| 440 | goto bad; | 
|---|
| 441 |  | 
|---|
| 442 | if (copyout((caddr_t)&mctx_store, ua_mctxp, thread_state32[sig_xstate].mcontext_size)) | 
|---|
| 443 | goto bad; | 
|---|
| 444 |  | 
|---|
| 445 | sinfo64.pad[0]  = tstate32->esp; | 
|---|
| 446 | sinfo64.si_addr = tstate32->eip; | 
|---|
| 447 | } | 
|---|
| 448 |  | 
|---|
| 449 | switch (sig) { | 
|---|
| 450 | case SIGILL: | 
|---|
| 451 | switch (ut->uu_code) { | 
|---|
| 452 | case EXC_I386_INVOP: | 
|---|
| 453 | sinfo64.si_code = ILL_ILLOPC; | 
|---|
| 454 | break; | 
|---|
| 455 | default: | 
|---|
| 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 */ | 
|---|
| 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)) { | 
|---|
| 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 { | 
|---|
| 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) { | 
|---|
| 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; | 
|---|
| 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: | 
|---|
| 510 | sinfo64.si_code = FPE_NOOP; | 
|---|
| 511 | } | 
|---|
| 512 | break; | 
|---|
| 513 | default: | 
|---|
| 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 | */ | 
|---|
| 555 | sinfo64.si_status = (WEXITSTATUS(status_and_exitcode) & 0x00FFFFFF) | (((uint32_t)(p->p_xhighbits) << 24) & 0xFF000000); | 
|---|
| 556 | p->p_xhighbits = 0; | 
|---|
| 557 | break; | 
|---|
| 558 | } | 
|---|
| 559 | } | 
|---|
| 560 | if (proc_is64bit(p)) { | 
|---|
| 561 | user64_siginfo_t sinfo64_user64; | 
|---|
| 562 |  | 
|---|
| 563 | bzero((caddr_t)&sinfo64_user64, sizeof(sinfo64_user64)); | 
|---|
| 564 |  | 
|---|
| 565 | siginfo_user_to_user64_x86(&sinfo64,&sinfo64_user64); | 
|---|
| 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 | } | 
|---|
| 586 |  | 
|---|
| 587 | /* XXX truncates catcher address to uintptr_t */ | 
|---|
| 588 | DTRACE_PROC3(signal__handle, int, sig, siginfo_t *, &(ut->t_dtrace_siginfo), | 
|---|
| 589 | void (*)(void), CAST_DOWN(sig_t, ua_catcher)); | 
|---|
| 590 | #endif /* CONFIG_DTRACE */ | 
|---|
| 591 |  | 
|---|
| 592 | if (copyout((caddr_t)&sinfo64_user64, ua_sip, sizeof (sinfo64_user64))) | 
|---|
| 593 | goto bad; | 
|---|
| 594 |  | 
|---|
| 595 | flavor = x86_THREAD_STATE64; | 
|---|
| 596 | state_count = x86_THREAD_STATE64_COUNT; | 
|---|
| 597 | state = (void *)&mctxp->mctx_avx64.ss; | 
|---|
| 598 | } else { | 
|---|
| 599 | x86_thread_state32_t	*tstate32; | 
|---|
| 600 | user32_siginfo_t sinfo32; | 
|---|
| 601 |  | 
|---|
| 602 | bzero((caddr_t)&sinfo32, sizeof(sinfo32)); | 
|---|
| 603 |  | 
|---|
| 604 | siginfo_user_to_user32_x86(&sinfo64,&sinfo32); | 
|---|
| 605 |  | 
|---|
| 606 | #if CONFIG_DTRACE | 
|---|
| 607 | bzero((caddr_t)&(ut->t_dtrace_siginfo), sizeof(ut->t_dtrace_siginfo)); | 
|---|
| 608 |  | 
|---|
| 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), | 
|---|
| 626 | void (*)(void), CAST_DOWN(sig_t, ua_catcher)); | 
|---|
| 627 | #endif /* CONFIG_DTRACE */ | 
|---|
| 628 |  | 
|---|
| 629 | if (copyout((caddr_t)&sinfo32, ua_sip, sizeof (sinfo32))) | 
|---|
| 630 | goto bad; | 
|---|
| 631 |  | 
|---|
| 632 | tstate32 = &mctxp->mctx_avx32.ss; | 
|---|
| 633 |  | 
|---|
| 634 | tstate32->eip = CAST_DOWN_EXPLICIT(user32_addr_t, trampact); | 
|---|
| 635 | tstate32->esp = CAST_DOWN_EXPLICIT(user32_addr_t, ua_fp); | 
|---|
| 636 |  | 
|---|
| 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); | 
|---|
| 653 |  | 
|---|
| 654 | /* Tell the PAL layer about the signal */ | 
|---|
| 655 | pal_set_signal_delivery( thread ); | 
|---|
| 656 |  | 
|---|
| 657 | proc_lock(p); | 
|---|
| 658 |  | 
|---|
| 659 | return; | 
|---|
| 660 |  | 
|---|
| 661 | bad: | 
|---|
| 662 |  | 
|---|
| 663 | proc_lock(p); | 
|---|
| 664 | SIGACTION(p, SIGILL) = SIG_DFL; | 
|---|
| 665 | sig = sigmask(SIGILL); | 
|---|
| 666 | p->p_sigignore &= ~sig; | 
|---|
| 667 | p->p_sigcatch &= ~sig; | 
|---|
| 668 | ut->uu_sigmask &= ~sig; | 
|---|
| 669 | /* sendsig is called with signal lock held */ | 
|---|
| 670 | proc_unlock(p); | 
|---|
| 671 | psignal_locked(p, SIGILL); | 
|---|
| 672 | proc_lock(p); | 
|---|
| 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 | */ | 
|---|
| 686 |  | 
|---|
| 687 | int | 
|---|
| 688 | sigreturn(struct proc *p, struct sigreturn_args *uap, __unused int *retval) | 
|---|
| 689 | { | 
|---|
| 690 | union { | 
|---|
| 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 | 
|---|
| 697 | } mctx_store, *mctxp = &mctx_store; | 
|---|
| 698 |  | 
|---|
| 699 | thread_t thread = current_thread(); | 
|---|
| 700 | struct uthread * ut; | 
|---|
| 701 | struct sigacts *ps = p->p_sigacts; | 
|---|
| 702 | int	error; | 
|---|
| 703 | int	onstack = 0; | 
|---|
| 704 |  | 
|---|
| 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; | 
|---|
| 711 | int		       rval = EJUSTRETURN; | 
|---|
| 712 | xstate_t	       sig_xstate; | 
|---|
| 713 | uint32_t            sigreturn_validation; | 
|---|
| 714 | user_addr_t         token_uctx; | 
|---|
| 715 | kern_return_t       kr; | 
|---|
| 716 |  | 
|---|
| 717 | ut = (struct uthread *)get_bsdthread_info(thread); | 
|---|
| 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 | } | 
|---|
| 730 |  | 
|---|
| 731 | bzero(mctxp, sizeof(*mctxp)); | 
|---|
| 732 |  | 
|---|
| 733 | sig_xstate = current_xstate(); | 
|---|
| 734 |  | 
|---|
| 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 |  | 
|---|
| 741 | if (proc_is64bit(p)) { | 
|---|
| 742 | struct user_ucontext64	uctx64; | 
|---|
| 743 | user64_addr_t token; | 
|---|
| 744 |  | 
|---|
| 745 | if ((error = copyin(uap->uctx, (void *)&uctx64, sizeof (uctx64)))) | 
|---|
| 746 | return(error); | 
|---|
| 747 |  | 
|---|
| 748 | if ((error = copyin(uctx64.uc_mcontext64, (void *)mctxp, thread_state64[sig_xstate].mcontext_size))) | 
|---|
| 749 | return(error); | 
|---|
| 750 |  | 
|---|
| 751 | onstack = uctx64.uc_onstack & 01; | 
|---|
| 752 | ut->uu_sigmask = uctx64.uc_sigmask & ~sigcantmask; | 
|---|
| 753 |  | 
|---|
| 754 | ts_flavor = x86_THREAD_STATE64; | 
|---|
| 755 | ts_count  = x86_THREAD_STATE64_COUNT; | 
|---|
| 756 | ts = (void *)&mctxp->mctx_avx64.ss; | 
|---|
| 757 |  | 
|---|
| 758 | fs_flavor = thread_state64[sig_xstate].flavor; | 
|---|
| 759 | fs_count  = thread_state64[sig_xstate].state_count; | 
|---|
| 760 | fs = (void *)&mctxp->mctx_avx64.fs; | 
|---|
| 761 |  | 
|---|
| 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 | } | 
|---|
| 772 | } else { | 
|---|
| 773 | struct user_ucontext32	uctx32; | 
|---|
| 774 | user32_addr_t token; | 
|---|
| 775 |  | 
|---|
| 776 | if ((error = copyin(uap->uctx, (void *)&uctx32, sizeof (uctx32)))) | 
|---|
| 777 | return(error); | 
|---|
| 778 |  | 
|---|
| 779 | if ((error = copyin(CAST_USER_ADDR_T(uctx32.uc_mcontext), (void *)mctxp, thread_state32[sig_xstate].mcontext_size))) | 
|---|
| 780 | return(error); | 
|---|
| 781 |  | 
|---|
| 782 | onstack = uctx32.uc_onstack & 01; | 
|---|
| 783 | ut->uu_sigmask = uctx32.uc_sigmask & ~sigcantmask; | 
|---|
| 784 |  | 
|---|
| 785 | ts_flavor = x86_THREAD_STATE32; | 
|---|
| 786 | ts_count  = x86_THREAD_STATE32_COUNT; | 
|---|
| 787 | ts = (void *)&mctxp->mctx_avx32.ss; | 
|---|
| 788 |  | 
|---|
| 789 | fs_flavor = thread_state32[sig_xstate].flavor; | 
|---|
| 790 | fs_count  = thread_state32[sig_xstate].state_count; | 
|---|
| 791 | fs = (void *)&mctxp->mctx_avx32.fs; | 
|---|
| 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 | } | 
|---|
| 804 | } | 
|---|
| 805 |  | 
|---|
| 806 | if (onstack) | 
|---|
| 807 | ut->uu_sigstk.ss_flags |= SA_ONSTACK; | 
|---|
| 808 | else | 
|---|
| 809 | ut->uu_sigstk.ss_flags &= ~SA_ONSTACK; | 
|---|
| 810 |  | 
|---|
| 811 | if (ut->uu_siglist & ~ut->uu_sigmask) | 
|---|
| 812 | signal_setast(thread); | 
|---|
| 813 |  | 
|---|
| 814 | if (rval == EINVAL) { | 
|---|
| 815 | goto error_ret; | 
|---|
| 816 | } | 
|---|
| 817 |  | 
|---|
| 818 | /* | 
|---|
| 819 | * thread_set_state() does all the needed checks for the passed in | 
|---|
| 820 | * content | 
|---|
| 821 | */ | 
|---|
| 822 | if (thread_setstatus(thread, ts_flavor, ts, ts_count) != KERN_SUCCESS) { | 
|---|
| 823 | rval = EINVAL; | 
|---|
| 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 */ | 
|---|
| 828 | goto error_ret; | 
|---|
| 829 | } | 
|---|
| 830 |  | 
|---|
| 831 | ml_fp_setvalid(TRUE); | 
|---|
| 832 |  | 
|---|
| 833 | if (thread_setstatus(thread, fs_flavor, fs, fs_count)  != KERN_SUCCESS) { | 
|---|
| 834 | rval = EINVAL; | 
|---|
| 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 */ | 
|---|
| 839 | goto error_ret; | 
|---|
| 840 |  | 
|---|
| 841 | } | 
|---|
| 842 | error_ret: | 
|---|
| 843 | return rval; | 
|---|
| 844 | } | 
|---|
| 845 |  | 
|---|
| 846 |  | 
|---|
| 847 | /* | 
|---|
| 848 | * machine_exception() performs machine-dependent translation | 
|---|
| 849 | * of a mach exception to a unix signal. | 
|---|
| 850 | */ | 
|---|
| 851 | int | 
|---|
| 852 | machine_exception(int                           exception, | 
|---|
| 853 | mach_exception_code_t         code, | 
|---|
| 854 | __unused mach_exception_subcode_t      subcode) | 
|---|
| 855 | { | 
|---|
| 856 | switch(exception) { | 
|---|
| 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 | } | 
|---|
| 862 | break; | 
|---|
| 863 |  | 
|---|
| 864 | case EXC_BAD_INSTRUCTION: | 
|---|
| 865 | return SIGILL; | 
|---|
| 866 |  | 
|---|
| 867 | case EXC_ARITHMETIC: | 
|---|
| 868 | return SIGFPE; | 
|---|
| 869 |  | 
|---|
| 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 | } | 
|---|
| 878 | break; | 
|---|
| 879 | } | 
|---|
| 880 |  | 
|---|
| 881 | return 0; | 
|---|
| 882 | } | 
|---|
| 883 |  | 
|---|
| 884 |  | 
|---|