1 /*- 2 * Copyright (c) 2003 Peter Wemm 3 * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * William Jolitz. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include <sys/cdefs.h> 35 __FBSDID("$FreeBSD$"); 36 37 #include "opt_compat.h" 38 39 #include <sys/param.h> 40 #include <sys/exec.h> 41 #include <sys/fcntl.h> 42 #include <sys/imgact.h> 43 #include <sys/kernel.h> 44 #include <sys/lock.h> 45 #include <sys/malloc.h> 46 #include <sys/mutex.h> 47 #include <sys/mman.h> 48 #include <sys/namei.h> 49 #include <sys/pioctl.h> 50 #include <sys/proc.h> 51 #include <sys/procfs.h> 52 #include <sys/resourcevar.h> 53 #include <sys/systm.h> 54 #include <sys/signalvar.h> 55 #include <sys/stat.h> 56 #include <sys/sx.h> 57 #include <sys/syscall.h> 58 #include <sys/syscallsubr.h> 59 #include <sys/sysctl.h> 60 #include <sys/sysent.h> 61 #include <sys/vnode.h> 62 63 #include <vm/vm.h> 64 #include <vm/vm_kern.h> 65 #include <vm/vm_param.h> 66 #include <vm/pmap.h> 67 #include <vm/vm_map.h> 68 #include <vm/vm_object.h> 69 #include <vm/vm_extern.h> 70 71 #include <compat/freebsd32/freebsd32_signal.h> 72 #include <compat/freebsd32/freebsd32_util.h> 73 #include <compat/freebsd32/freebsd32_proto.h> 74 #include <compat/freebsd32/freebsd32.h> 75 #include <compat/ia32/ia32_signal.h> 76 #include <machine/psl.h> 77 #include <machine/segments.h> 78 #include <machine/specialreg.h> 79 #include <machine/frame.h> 80 #include <machine/md_var.h> 81 #include <machine/pcb.h> 82 #include <machine/cpufunc.h> 83 84 #ifdef COMPAT_FREEBSD4 85 static void freebsd4_ia32_sendsig(sig_t, ksiginfo_t *, sigset_t *); 86 #endif 87 88 #define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) 89 #define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) 90 91 static void 92 ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp, 93 char *xfpusave, size_t xfpusave_len) 94 { 95 size_t max_len, len; 96 97 /* 98 * XXX Format of 64bit and 32bit FXSAVE areas differs. FXSAVE 99 * in 32bit mode saves %cs and %ds, while on 64bit it saves 100 * 64bit instruction and data pointers. Ignore the difference 101 * for now, it should be irrelevant for most applications. 102 */ 103 mcp->mc_ownedfp = fpugetregs(td); 104 bcopy(get_pcb_user_save_td(td), &mcp->mc_fpstate[0], 105 sizeof(mcp->mc_fpstate)); 106 mcp->mc_fpformat = fpuformat(); 107 if (!use_xsave || xfpusave_len == 0) 108 return; 109 max_len = cpu_max_ext_state_size - sizeof(struct savefpu); 110 len = xfpusave_len; 111 if (len > max_len) { 112 len = max_len; 113 bzero(xfpusave + max_len, len - max_len); 114 } 115 mcp->mc_flags |= _MC_IA32_HASFPXSTATE; 116 mcp->mc_xfpustate_len = len; 117 bcopy(get_pcb_user_save_td(td) + 1, xfpusave, len); 118 } 119 120 static int 121 ia32_set_fpcontext(struct thread *td, struct ia32_mcontext *mcp, 122 char *xfpustate, size_t xfpustate_len) 123 { 124 int error; 125 126 if (mcp->mc_fpformat == _MC_FPFMT_NODEV) 127 return (0); 128 else if (mcp->mc_fpformat != _MC_FPFMT_XMM) 129 return (EINVAL); 130 else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) { 131 /* We don't care what state is left in the FPU or PCB. */ 132 fpstate_drop(td); 133 error = 0; 134 } else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU || 135 mcp->mc_ownedfp == _MC_FPOWNED_PCB) { 136 error = fpusetregs(td, (struct savefpu *)&mcp->mc_fpstate, 137 xfpustate, xfpustate_len); 138 } else 139 return (EINVAL); 140 return (error); 141 } 142 143 /* 144 * Get machine context. 145 */ 146 static int 147 ia32_get_mcontext(struct thread *td, struct ia32_mcontext *mcp, int flags) 148 { 149 struct pcb *pcb; 150 struct trapframe *tp; 151 152 pcb = td->td_pcb; 153 tp = td->td_frame; 154 155 PROC_LOCK(curthread->td_proc); 156 mcp->mc_onstack = sigonstack(tp->tf_rsp); 157 PROC_UNLOCK(curthread->td_proc); 158 /* Entry into kernel always sets TF_HASSEGS */ 159 mcp->mc_gs = tp->tf_gs; 160 mcp->mc_fs = tp->tf_fs; 161 mcp->mc_es = tp->tf_es; 162 mcp->mc_ds = tp->tf_ds; 163 mcp->mc_edi = tp->tf_rdi; 164 mcp->mc_esi = tp->tf_rsi; 165 mcp->mc_ebp = tp->tf_rbp; 166 mcp->mc_isp = tp->tf_rsp; 167 mcp->mc_eflags = tp->tf_rflags; 168 if (flags & GET_MC_CLEAR_RET) { 169 mcp->mc_eax = 0; 170 mcp->mc_edx = 0; 171 mcp->mc_eflags &= ~PSL_C; 172 } else { 173 mcp->mc_eax = tp->tf_rax; 174 mcp->mc_edx = tp->tf_rdx; 175 } 176 mcp->mc_ebx = tp->tf_rbx; 177 mcp->mc_ecx = tp->tf_rcx; 178 mcp->mc_eip = tp->tf_rip; 179 mcp->mc_cs = tp->tf_cs; 180 mcp->mc_esp = tp->tf_rsp; 181 mcp->mc_ss = tp->tf_ss; 182 mcp->mc_len = sizeof(*mcp); 183 mcp->mc_flags = tp->tf_flags; 184 ia32_get_fpcontext(td, mcp, NULL, 0); 185 mcp->mc_fsbase = pcb->pcb_fsbase; 186 mcp->mc_gsbase = pcb->pcb_gsbase; 187 mcp->mc_xfpustate = 0; 188 mcp->mc_xfpustate_len = 0; 189 bzero(mcp->mc_spare2, sizeof(mcp->mc_spare2)); 190 return (0); 191 } 192 193 /* 194 * Set machine context. 195 * 196 * However, we don't set any but the user modifiable flags, and we won't 197 * touch the cs selector. 198 */ 199 static int 200 ia32_set_mcontext(struct thread *td, struct ia32_mcontext *mcp) 201 { 202 struct trapframe *tp; 203 char *xfpustate; 204 long rflags; 205 int ret; 206 207 tp = td->td_frame; 208 if (mcp->mc_len != sizeof(*mcp)) 209 return (EINVAL); 210 rflags = (mcp->mc_eflags & PSL_USERCHANGE) | 211 (tp->tf_rflags & ~PSL_USERCHANGE); 212 if (mcp->mc_flags & _MC_IA32_HASFPXSTATE) { 213 if (mcp->mc_xfpustate_len > cpu_max_ext_state_size - 214 sizeof(struct savefpu)) 215 return (EINVAL); 216 xfpustate = __builtin_alloca(mcp->mc_xfpustate_len); 217 ret = copyin(PTRIN(mcp->mc_xfpustate), xfpustate, 218 mcp->mc_xfpustate_len); 219 if (ret != 0) 220 return (ret); 221 } else 222 xfpustate = NULL; 223 ret = ia32_set_fpcontext(td, mcp, xfpustate, mcp->mc_xfpustate_len); 224 if (ret != 0) 225 return (ret); 226 tp->tf_gs = mcp->mc_gs; 227 tp->tf_fs = mcp->mc_fs; 228 tp->tf_es = mcp->mc_es; 229 tp->tf_ds = mcp->mc_ds; 230 tp->tf_flags = TF_HASSEGS; 231 tp->tf_rdi = mcp->mc_edi; 232 tp->tf_rsi = mcp->mc_esi; 233 tp->tf_rbp = mcp->mc_ebp; 234 tp->tf_rbx = mcp->mc_ebx; 235 tp->tf_rdx = mcp->mc_edx; 236 tp->tf_rcx = mcp->mc_ecx; 237 tp->tf_rax = mcp->mc_eax; 238 /* trapno, err */ 239 tp->tf_rip = mcp->mc_eip; 240 tp->tf_rflags = rflags; 241 tp->tf_rsp = mcp->mc_esp; 242 tp->tf_ss = mcp->mc_ss; 243 set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 244 return (0); 245 } 246 247 /* 248 * The first two fields of a ucontext_t are the signal mask and 249 * the machine context. The next field is uc_link; we want to 250 * avoid destroying the link when copying out contexts. 251 */ 252 #define UC_COPY_SIZE offsetof(struct ia32_ucontext, uc_link) 253 254 int 255 freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap) 256 { 257 struct ia32_ucontext uc; 258 int ret; 259 260 if (uap->ucp == NULL) 261 ret = EINVAL; 262 else { 263 ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 264 PROC_LOCK(td->td_proc); 265 uc.uc_sigmask = td->td_sigmask; 266 PROC_UNLOCK(td->td_proc); 267 bzero(&uc.__spare__, sizeof(uc.__spare__)); 268 ret = copyout(&uc, uap->ucp, UC_COPY_SIZE); 269 } 270 return (ret); 271 } 272 273 int 274 freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap) 275 { 276 struct ia32_ucontext uc; 277 int ret; 278 279 if (uap->ucp == NULL) 280 ret = EINVAL; 281 else { 282 ret = copyin(uap->ucp, &uc, UC_COPY_SIZE); 283 if (ret == 0) { 284 ret = ia32_set_mcontext(td, &uc.uc_mcontext); 285 if (ret == 0) { 286 kern_sigprocmask(td, SIG_SETMASK, 287 &uc.uc_sigmask, NULL, 0); 288 } 289 } 290 } 291 return (ret == 0 ? EJUSTRETURN : ret); 292 } 293 294 int 295 freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap) 296 { 297 struct ia32_ucontext uc; 298 int ret; 299 300 if (uap->oucp == NULL || uap->ucp == NULL) 301 ret = EINVAL; 302 else { 303 ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 304 PROC_LOCK(td->td_proc); 305 uc.uc_sigmask = td->td_sigmask; 306 PROC_UNLOCK(td->td_proc); 307 ret = copyout(&uc, uap->oucp, UC_COPY_SIZE); 308 if (ret == 0) { 309 ret = copyin(uap->ucp, &uc, UC_COPY_SIZE); 310 if (ret == 0) { 311 ret = ia32_set_mcontext(td, &uc.uc_mcontext); 312 if (ret == 0) { 313 kern_sigprocmask(td, SIG_SETMASK, 314 &uc.uc_sigmask, NULL, 0); 315 } 316 } 317 } 318 } 319 return (ret == 0 ? EJUSTRETURN : ret); 320 } 321 322 /* 323 * Send an interrupt to process. 324 * 325 * Stack is set up to allow sigcode stored 326 * at top to call routine, followed by kcall 327 * to sigreturn routine below. After sigreturn 328 * resets the signal mask, the stack, and the 329 * frame pointer, it returns to the user 330 * specified pc, psl. 331 */ 332 333 #ifdef COMPAT_43 334 static void 335 ia32_osendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 336 { 337 struct ia32_sigframe3 sf, *fp; 338 struct proc *p; 339 struct thread *td; 340 struct sigacts *psp; 341 struct trapframe *regs; 342 int sig; 343 int oonstack; 344 345 td = curthread; 346 p = td->td_proc; 347 PROC_LOCK_ASSERT(p, MA_OWNED); 348 sig = ksi->ksi_signo; 349 psp = p->p_sigacts; 350 mtx_assert(&psp->ps_mtx, MA_OWNED); 351 regs = td->td_frame; 352 oonstack = sigonstack(regs->tf_rsp); 353 354 /* Allocate space for the signal handler context. */ 355 if ((td->td_pflags & TDP_ALTSTACK) && !oonstack && 356 SIGISMEMBER(psp->ps_sigonstack, sig)) { 357 fp = (struct ia32_sigframe3 *)((uintptr_t)td->td_sigstk.ss_sp + 358 td->td_sigstk.ss_size - sizeof(sf)); 359 td->td_sigstk.ss_flags |= SS_ONSTACK; 360 } else 361 fp = (struct ia32_sigframe3 *)regs->tf_rsp - 1; 362 363 /* Build the argument list for the signal handler. */ 364 sf.sf_signum = sig; 365 sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc; 366 if (SIGISMEMBER(psp->ps_siginfo, sig)) { 367 /* Signal handler installed with SA_SIGINFO. */ 368 sf.sf_arg2 = (register_t)&fp->sf_siginfo; 369 sf.sf_siginfo.si_signo = sig; 370 sf.sf_siginfo.si_code = ksi->ksi_code; 371 sf.sf_ah = (uintptr_t)catcher; 372 } else { 373 /* Old FreeBSD-style arguments. */ 374 sf.sf_arg2 = ksi->ksi_code; 375 sf.sf_addr = (register_t)ksi->ksi_addr; 376 sf.sf_ah = (uintptr_t)catcher; 377 } 378 mtx_unlock(&psp->ps_mtx); 379 PROC_UNLOCK(p); 380 381 /* Save most if not all of trap frame. */ 382 sf.sf_siginfo.si_sc.sc_eax = regs->tf_rax; 383 sf.sf_siginfo.si_sc.sc_ebx = regs->tf_rbx; 384 sf.sf_siginfo.si_sc.sc_ecx = regs->tf_rcx; 385 sf.sf_siginfo.si_sc.sc_edx = regs->tf_rdx; 386 sf.sf_siginfo.si_sc.sc_esi = regs->tf_rsi; 387 sf.sf_siginfo.si_sc.sc_edi = regs->tf_rdi; 388 sf.sf_siginfo.si_sc.sc_cs = regs->tf_cs; 389 sf.sf_siginfo.si_sc.sc_ds = regs->tf_ds; 390 sf.sf_siginfo.si_sc.sc_ss = regs->tf_ss; 391 sf.sf_siginfo.si_sc.sc_es = regs->tf_es; 392 sf.sf_siginfo.si_sc.sc_fs = regs->tf_fs; 393 sf.sf_siginfo.si_sc.sc_gs = regs->tf_gs; 394 sf.sf_siginfo.si_sc.sc_isp = regs->tf_rsp; 395 396 /* Build the signal context to be used by osigreturn(). */ 397 sf.sf_siginfo.si_sc.sc_onstack = (oonstack) ? 1 : 0; 398 SIG2OSIG(*mask, sf.sf_siginfo.si_sc.sc_mask); 399 sf.sf_siginfo.si_sc.sc_esp = regs->tf_rsp; 400 sf.sf_siginfo.si_sc.sc_ebp = regs->tf_rbp; 401 sf.sf_siginfo.si_sc.sc_eip = regs->tf_rip; 402 sf.sf_siginfo.si_sc.sc_eflags = regs->tf_rflags; 403 sf.sf_siginfo.si_sc.sc_trapno = regs->tf_trapno; 404 sf.sf_siginfo.si_sc.sc_err = regs->tf_err; 405 406 /* 407 * Copy the sigframe out to the user's stack. 408 */ 409 if (copyout(&sf, fp, sizeof(*fp)) != 0) { 410 #ifdef DEBUG 411 printf("process %ld has trashed its stack\n", (long)p->p_pid); 412 #endif 413 PROC_LOCK(p); 414 sigexit(td, SIGILL); 415 } 416 417 regs->tf_rsp = (uintptr_t)fp; 418 regs->tf_rip = p->p_sysent->sv_psstrings - sz_ia32_osigcode; 419 regs->tf_rflags &= ~(PSL_T | PSL_D); 420 regs->tf_cs = _ucode32sel; 421 regs->tf_ds = _udatasel; 422 regs->tf_es = _udatasel; 423 regs->tf_fs = _udatasel; 424 regs->tf_ss = _udatasel; 425 set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 426 PROC_LOCK(p); 427 mtx_lock(&psp->ps_mtx); 428 } 429 #endif 430 431 #ifdef COMPAT_FREEBSD4 432 static void 433 freebsd4_ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 434 { 435 struct ia32_sigframe4 sf, *sfp; 436 struct siginfo32 siginfo; 437 struct proc *p; 438 struct thread *td; 439 struct sigacts *psp; 440 struct trapframe *regs; 441 int oonstack; 442 int sig; 443 444 td = curthread; 445 p = td->td_proc; 446 siginfo_to_siginfo32(&ksi->ksi_info, &siginfo); 447 448 PROC_LOCK_ASSERT(p, MA_OWNED); 449 sig = siginfo.si_signo; 450 psp = p->p_sigacts; 451 mtx_assert(&psp->ps_mtx, MA_OWNED); 452 regs = td->td_frame; 453 oonstack = sigonstack(regs->tf_rsp); 454 455 /* Save user context. */ 456 bzero(&sf, sizeof(sf)); 457 sf.sf_uc.uc_sigmask = *mask; 458 sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp; 459 sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size; 460 sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) 461 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 462 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 463 sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi; 464 sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi; 465 sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp; 466 sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */ 467 sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx; 468 sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx; 469 sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx; 470 sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax; 471 sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno; 472 sf.sf_uc.uc_mcontext.mc_err = regs->tf_err; 473 sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip; 474 sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs; 475 sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags; 476 sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp; 477 sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss; 478 sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds; 479 sf.sf_uc.uc_mcontext.mc_es = regs->tf_es; 480 sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs; 481 sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs; 482 bzero(sf.sf_uc.uc_mcontext.mc_fpregs, 483 sizeof(sf.sf_uc.uc_mcontext.mc_fpregs)); 484 bzero(sf.sf_uc.uc_mcontext.__spare__, 485 sizeof(sf.sf_uc.uc_mcontext.__spare__)); 486 bzero(sf.sf_uc.__spare__, sizeof(sf.sf_uc.__spare__)); 487 488 /* Allocate space for the signal handler context. */ 489 if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 490 SIGISMEMBER(psp->ps_sigonstack, sig)) { 491 sfp = (struct ia32_sigframe4 *)((uintptr_t)td->td_sigstk.ss_sp + 492 td->td_sigstk.ss_size - sizeof(sf)); 493 } else 494 sfp = (struct ia32_sigframe4 *)regs->tf_rsp - 1; 495 PROC_UNLOCK(p); 496 497 /* Build the argument list for the signal handler. */ 498 sf.sf_signum = sig; 499 sf.sf_ucontext = (register_t)&sfp->sf_uc; 500 bzero(&sf.sf_si, sizeof(sf.sf_si)); 501 if (SIGISMEMBER(psp->ps_siginfo, sig)) { 502 /* Signal handler installed with SA_SIGINFO. */ 503 sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si; 504 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 505 506 /* Fill in POSIX parts */ 507 sf.sf_si = siginfo; 508 sf.sf_si.si_signo = sig; 509 } else { 510 /* Old FreeBSD-style arguments. */ 511 sf.sf_siginfo = siginfo.si_code; 512 sf.sf_addr = (u_int32_t)siginfo.si_addr; 513 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 514 } 515 mtx_unlock(&psp->ps_mtx); 516 517 /* 518 * Copy the sigframe out to the user's stack. 519 */ 520 if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { 521 #ifdef DEBUG 522 printf("process %ld has trashed its stack\n", (long)p->p_pid); 523 #endif 524 PROC_LOCK(p); 525 sigexit(td, SIGILL); 526 } 527 528 regs->tf_rsp = (uintptr_t)sfp; 529 regs->tf_rip = p->p_sysent->sv_sigcode_base + sz_ia32_sigcode - 530 sz_freebsd4_ia32_sigcode; 531 regs->tf_rflags &= ~(PSL_T | PSL_D); 532 regs->tf_cs = _ucode32sel; 533 regs->tf_ss = _udatasel; 534 regs->tf_ds = _udatasel; 535 regs->tf_es = _udatasel; 536 set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 537 /* leave user %fs and %gs untouched */ 538 PROC_LOCK(p); 539 mtx_lock(&psp->ps_mtx); 540 } 541 #endif /* COMPAT_FREEBSD4 */ 542 543 void 544 ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 545 { 546 struct ia32_sigframe sf, *sfp; 547 struct siginfo32 siginfo; 548 struct proc *p; 549 struct thread *td; 550 struct sigacts *psp; 551 char *sp; 552 struct trapframe *regs; 553 char *xfpusave; 554 size_t xfpusave_len; 555 int oonstack; 556 int sig; 557 558 siginfo_to_siginfo32(&ksi->ksi_info, &siginfo); 559 td = curthread; 560 p = td->td_proc; 561 PROC_LOCK_ASSERT(p, MA_OWNED); 562 sig = siginfo.si_signo; 563 psp = p->p_sigacts; 564 #ifdef COMPAT_FREEBSD4 565 if (SIGISMEMBER(psp->ps_freebsd4, sig)) { 566 freebsd4_ia32_sendsig(catcher, ksi, mask); 567 return; 568 } 569 #endif 570 #ifdef COMPAT_43 571 if (SIGISMEMBER(psp->ps_osigset, sig)) { 572 ia32_osendsig(catcher, ksi, mask); 573 return; 574 } 575 #endif 576 mtx_assert(&psp->ps_mtx, MA_OWNED); 577 regs = td->td_frame; 578 oonstack = sigonstack(regs->tf_rsp); 579 580 if (cpu_max_ext_state_size > sizeof(struct savefpu) && use_xsave) { 581 xfpusave_len = cpu_max_ext_state_size - sizeof(struct savefpu); 582 xfpusave = __builtin_alloca(xfpusave_len); 583 } else { 584 xfpusave_len = 0; 585 xfpusave = NULL; 586 } 587 588 /* Save user context. */ 589 bzero(&sf, sizeof(sf)); 590 sf.sf_uc.uc_sigmask = *mask; 591 sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp; 592 sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size; 593 sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) 594 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 595 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 596 sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi; 597 sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi; 598 sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp; 599 sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */ 600 sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx; 601 sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx; 602 sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx; 603 sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax; 604 sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno; 605 sf.sf_uc.uc_mcontext.mc_err = regs->tf_err; 606 sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip; 607 sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs; 608 sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags; 609 sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp; 610 sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss; 611 sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds; 612 sf.sf_uc.uc_mcontext.mc_es = regs->tf_es; 613 sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs; 614 sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs; 615 sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */ 616 ia32_get_fpcontext(td, &sf.sf_uc.uc_mcontext, xfpusave, xfpusave_len); 617 fpstate_drop(td); 618 sf.sf_uc.uc_mcontext.mc_fsbase = td->td_pcb->pcb_fsbase; 619 sf.sf_uc.uc_mcontext.mc_gsbase = td->td_pcb->pcb_gsbase; 620 bzero(sf.sf_uc.__spare__, sizeof(sf.sf_uc.__spare__)); 621 622 /* Allocate space for the signal handler context. */ 623 if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 624 SIGISMEMBER(psp->ps_sigonstack, sig)) 625 sp = (char *)td->td_sigstk.ss_sp + td->td_sigstk.ss_size; 626 else 627 sp = (char *)regs->tf_rsp; 628 if (xfpusave != NULL) { 629 sp -= xfpusave_len; 630 sp = (char *)((unsigned long)sp & ~0x3Ful); 631 sf.sf_uc.uc_mcontext.mc_xfpustate = (register_t)sp; 632 } 633 sp -= sizeof(sf); 634 /* Align to 16 bytes. */ 635 sfp = (struct ia32_sigframe *)((uintptr_t)sp & ~0xF); 636 PROC_UNLOCK(p); 637 638 /* Build the argument list for the signal handler. */ 639 sf.sf_signum = sig; 640 sf.sf_ucontext = (register_t)&sfp->sf_uc; 641 bzero(&sf.sf_si, sizeof(sf.sf_si)); 642 if (SIGISMEMBER(psp->ps_siginfo, sig)) { 643 /* Signal handler installed with SA_SIGINFO. */ 644 sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si; 645 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 646 647 /* Fill in POSIX parts */ 648 sf.sf_si = siginfo; 649 sf.sf_si.si_signo = sig; 650 } else { 651 /* Old FreeBSD-style arguments. */ 652 sf.sf_siginfo = siginfo.si_code; 653 sf.sf_addr = (u_int32_t)siginfo.si_addr; 654 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 655 } 656 mtx_unlock(&psp->ps_mtx); 657 658 /* 659 * Copy the sigframe out to the user's stack. 660 */ 661 if (copyout(&sf, sfp, sizeof(*sfp)) != 0 || 662 (xfpusave != NULL && copyout(xfpusave, 663 PTRIN(sf.sf_uc.uc_mcontext.mc_xfpustate), xfpusave_len) 664 != 0)) { 665 #ifdef DEBUG 666 printf("process %ld has trashed its stack\n", (long)p->p_pid); 667 #endif 668 PROC_LOCK(p); 669 sigexit(td, SIGILL); 670 } 671 672 regs->tf_rsp = (uintptr_t)sfp; 673 regs->tf_rip = p->p_sysent->sv_sigcode_base; 674 regs->tf_rflags &= ~(PSL_T | PSL_D); 675 regs->tf_cs = _ucode32sel; 676 regs->tf_ss = _udatasel; 677 regs->tf_ds = _udatasel; 678 regs->tf_es = _udatasel; 679 set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 680 /* XXXKIB leave user %fs and %gs untouched */ 681 PROC_LOCK(p); 682 mtx_lock(&psp->ps_mtx); 683 } 684 685 /* 686 * System call to cleanup state after a signal 687 * has been taken. Reset signal mask and 688 * stack state from context left by sendsig (above). 689 * Return to previous pc and psl as specified by 690 * context left by sendsig. Check carefully to 691 * make sure that the user has not modified the 692 * state to gain improper privileges. 693 */ 694 695 #ifdef COMPAT_43 696 int 697 ofreebsd32_sigreturn(struct thread *td, struct ofreebsd32_sigreturn_args *uap) 698 { 699 struct ia32_sigcontext3 sc, *scp; 700 struct trapframe *regs; 701 int eflags, error; 702 ksiginfo_t ksi; 703 704 regs = td->td_frame; 705 error = copyin(uap->sigcntxp, &sc, sizeof(sc)); 706 if (error != 0) 707 return (error); 708 scp = ≻ 709 eflags = scp->sc_eflags; 710 if (!EFL_SECURE(eflags, regs->tf_rflags)) { 711 return (EINVAL); 712 } 713 if (!CS_SECURE(scp->sc_cs)) { 714 ksiginfo_init_trap(&ksi); 715 ksi.ksi_signo = SIGBUS; 716 ksi.ksi_code = BUS_OBJERR; 717 ksi.ksi_trapno = T_PROTFLT; 718 ksi.ksi_addr = (void *)regs->tf_rip; 719 trapsignal(td, &ksi); 720 return (EINVAL); 721 } 722 regs->tf_ds = scp->sc_ds; 723 regs->tf_es = scp->sc_es; 724 regs->tf_fs = scp->sc_fs; 725 regs->tf_gs = scp->sc_gs; 726 727 regs->tf_rax = scp->sc_eax; 728 regs->tf_rbx = scp->sc_ebx; 729 regs->tf_rcx = scp->sc_ecx; 730 regs->tf_rdx = scp->sc_edx; 731 regs->tf_rsi = scp->sc_esi; 732 regs->tf_rdi = scp->sc_edi; 733 regs->tf_cs = scp->sc_cs; 734 regs->tf_ss = scp->sc_ss; 735 regs->tf_rbp = scp->sc_ebp; 736 regs->tf_rsp = scp->sc_esp; 737 regs->tf_rip = scp->sc_eip; 738 regs->tf_rflags = eflags; 739 740 if (scp->sc_onstack & 1) 741 td->td_sigstk.ss_flags |= SS_ONSTACK; 742 else 743 td->td_sigstk.ss_flags &= ~SS_ONSTACK; 744 745 kern_sigprocmask(td, SIG_SETMASK, (sigset_t *)&scp->sc_mask, NULL, 746 SIGPROCMASK_OLD); 747 set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 748 return (EJUSTRETURN); 749 } 750 #endif 751 752 #ifdef COMPAT_FREEBSD4 753 /* 754 * MPSAFE 755 */ 756 int 757 freebsd4_freebsd32_sigreturn(td, uap) 758 struct thread *td; 759 struct freebsd4_freebsd32_sigreturn_args /* { 760 const struct freebsd4_freebsd32_ucontext *sigcntxp; 761 } */ *uap; 762 { 763 struct ia32_ucontext4 uc; 764 struct trapframe *regs; 765 struct ia32_ucontext4 *ucp; 766 int cs, eflags, error; 767 ksiginfo_t ksi; 768 769 error = copyin(uap->sigcntxp, &uc, sizeof(uc)); 770 if (error != 0) 771 return (error); 772 ucp = &uc; 773 regs = td->td_frame; 774 eflags = ucp->uc_mcontext.mc_eflags; 775 /* 776 * Don't allow users to change privileged or reserved flags. 777 */ 778 if (!EFL_SECURE(eflags, regs->tf_rflags)) { 779 uprintf("pid %d (%s): freebsd4_freebsd32_sigreturn eflags = 0x%x\n", 780 td->td_proc->p_pid, td->td_name, eflags); 781 return (EINVAL); 782 } 783 784 /* 785 * Don't allow users to load a valid privileged %cs. Let the 786 * hardware check for invalid selectors, excess privilege in 787 * other selectors, invalid %eip's and invalid %esp's. 788 */ 789 cs = ucp->uc_mcontext.mc_cs; 790 if (!CS_SECURE(cs)) { 791 uprintf("pid %d (%s): freebsd4_sigreturn cs = 0x%x\n", 792 td->td_proc->p_pid, td->td_name, cs); 793 ksiginfo_init_trap(&ksi); 794 ksi.ksi_signo = SIGBUS; 795 ksi.ksi_code = BUS_OBJERR; 796 ksi.ksi_trapno = T_PROTFLT; 797 ksi.ksi_addr = (void *)regs->tf_rip; 798 trapsignal(td, &ksi); 799 return (EINVAL); 800 } 801 802 regs->tf_rdi = ucp->uc_mcontext.mc_edi; 803 regs->tf_rsi = ucp->uc_mcontext.mc_esi; 804 regs->tf_rbp = ucp->uc_mcontext.mc_ebp; 805 regs->tf_rbx = ucp->uc_mcontext.mc_ebx; 806 regs->tf_rdx = ucp->uc_mcontext.mc_edx; 807 regs->tf_rcx = ucp->uc_mcontext.mc_ecx; 808 regs->tf_rax = ucp->uc_mcontext.mc_eax; 809 regs->tf_trapno = ucp->uc_mcontext.mc_trapno; 810 regs->tf_err = ucp->uc_mcontext.mc_err; 811 regs->tf_rip = ucp->uc_mcontext.mc_eip; 812 regs->tf_cs = cs; 813 regs->tf_rflags = ucp->uc_mcontext.mc_eflags; 814 regs->tf_rsp = ucp->uc_mcontext.mc_esp; 815 regs->tf_ss = ucp->uc_mcontext.mc_ss; 816 regs->tf_ds = ucp->uc_mcontext.mc_ds; 817 regs->tf_es = ucp->uc_mcontext.mc_es; 818 regs->tf_fs = ucp->uc_mcontext.mc_fs; 819 regs->tf_gs = ucp->uc_mcontext.mc_gs; 820 821 kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0); 822 set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 823 return (EJUSTRETURN); 824 } 825 #endif /* COMPAT_FREEBSD4 */ 826 827 /* 828 * MPSAFE 829 */ 830 int 831 freebsd32_sigreturn(td, uap) 832 struct thread *td; 833 struct freebsd32_sigreturn_args /* { 834 const struct freebsd32_ucontext *sigcntxp; 835 } */ *uap; 836 { 837 struct ia32_ucontext uc; 838 struct trapframe *regs; 839 struct ia32_ucontext *ucp; 840 char *xfpustate; 841 size_t xfpustate_len; 842 int cs, eflags, error, ret; 843 ksiginfo_t ksi; 844 845 error = copyin(uap->sigcntxp, &uc, sizeof(uc)); 846 if (error != 0) 847 return (error); 848 ucp = &uc; 849 regs = td->td_frame; 850 eflags = ucp->uc_mcontext.mc_eflags; 851 /* 852 * Don't allow users to change privileged or reserved flags. 853 */ 854 if (!EFL_SECURE(eflags, regs->tf_rflags)) { 855 uprintf("pid %d (%s): freebsd32_sigreturn eflags = 0x%x\n", 856 td->td_proc->p_pid, td->td_name, eflags); 857 return (EINVAL); 858 } 859 860 /* 861 * Don't allow users to load a valid privileged %cs. Let the 862 * hardware check for invalid selectors, excess privilege in 863 * other selectors, invalid %eip's and invalid %esp's. 864 */ 865 cs = ucp->uc_mcontext.mc_cs; 866 if (!CS_SECURE(cs)) { 867 uprintf("pid %d (%s): sigreturn cs = 0x%x\n", 868 td->td_proc->p_pid, td->td_name, cs); 869 ksiginfo_init_trap(&ksi); 870 ksi.ksi_signo = SIGBUS; 871 ksi.ksi_code = BUS_OBJERR; 872 ksi.ksi_trapno = T_PROTFLT; 873 ksi.ksi_addr = (void *)regs->tf_rip; 874 trapsignal(td, &ksi); 875 return (EINVAL); 876 } 877 878 if ((ucp->uc_mcontext.mc_flags & _MC_HASFPXSTATE) != 0) { 879 xfpustate_len = uc.uc_mcontext.mc_xfpustate_len; 880 if (xfpustate_len > cpu_max_ext_state_size - 881 sizeof(struct savefpu)) { 882 uprintf("pid %d (%s): sigreturn xfpusave_len = 0x%zx\n", 883 td->td_proc->p_pid, td->td_name, xfpustate_len); 884 return (EINVAL); 885 } 886 xfpustate = __builtin_alloca(xfpustate_len); 887 error = copyin(PTRIN(ucp->uc_mcontext.mc_xfpustate), 888 xfpustate, xfpustate_len); 889 if (error != 0) { 890 uprintf( 891 "pid %d (%s): sigreturn copying xfpustate failed\n", 892 td->td_proc->p_pid, td->td_name); 893 return (error); 894 } 895 } else { 896 xfpustate = NULL; 897 xfpustate_len = 0; 898 } 899 ret = ia32_set_fpcontext(td, &ucp->uc_mcontext, xfpustate, 900 xfpustate_len); 901 if (ret != 0) { 902 uprintf("pid %d (%s): sigreturn set_fpcontext err %d\n", 903 td->td_proc->p_pid, td->td_name, ret); 904 return (ret); 905 } 906 907 regs->tf_rdi = ucp->uc_mcontext.mc_edi; 908 regs->tf_rsi = ucp->uc_mcontext.mc_esi; 909 regs->tf_rbp = ucp->uc_mcontext.mc_ebp; 910 regs->tf_rbx = ucp->uc_mcontext.mc_ebx; 911 regs->tf_rdx = ucp->uc_mcontext.mc_edx; 912 regs->tf_rcx = ucp->uc_mcontext.mc_ecx; 913 regs->tf_rax = ucp->uc_mcontext.mc_eax; 914 regs->tf_trapno = ucp->uc_mcontext.mc_trapno; 915 regs->tf_err = ucp->uc_mcontext.mc_err; 916 regs->tf_rip = ucp->uc_mcontext.mc_eip; 917 regs->tf_cs = cs; 918 regs->tf_rflags = ucp->uc_mcontext.mc_eflags; 919 regs->tf_rsp = ucp->uc_mcontext.mc_esp; 920 regs->tf_ss = ucp->uc_mcontext.mc_ss; 921 regs->tf_ds = ucp->uc_mcontext.mc_ds; 922 regs->tf_es = ucp->uc_mcontext.mc_es; 923 regs->tf_fs = ucp->uc_mcontext.mc_fs; 924 regs->tf_gs = ucp->uc_mcontext.mc_gs; 925 regs->tf_flags = TF_HASSEGS; 926 927 kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0); 928 set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 929 return (EJUSTRETURN); 930 } 931 932 /* 933 * Clear registers on exec 934 */ 935 void 936 ia32_setregs(struct thread *td, struct image_params *imgp, u_long stack) 937 { 938 struct trapframe *regs = td->td_frame; 939 struct pcb *pcb = td->td_pcb; 940 941 mtx_lock(&dt_lock); 942 if (td->td_proc->p_md.md_ldt != NULL) 943 user_ldt_free(td); 944 else 945 mtx_unlock(&dt_lock); 946 #ifdef COMPAT_43 947 setup_lcall_gate(); 948 #endif 949 950 pcb->pcb_fsbase = 0; 951 pcb->pcb_gsbase = 0; 952 pcb->pcb_initial_fpucw = __INITIAL_FPUCW_I386__; 953 954 bzero((char *)regs, sizeof(struct trapframe)); 955 regs->tf_rip = imgp->entry_addr; 956 regs->tf_rsp = stack; 957 regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T); 958 regs->tf_ss = _udatasel; 959 regs->tf_cs = _ucode32sel; 960 regs->tf_rbx = imgp->ps_strings; 961 regs->tf_ds = _udatasel; 962 regs->tf_es = _udatasel; 963 regs->tf_fs = _ufssel; 964 regs->tf_gs = _ugssel; 965 regs->tf_flags = TF_HASSEGS; 966 967 fpstate_drop(td); 968 969 /* Return via doreti so that we can change to a different %cs */ 970 set_pcb_flags(pcb, PCB_32BIT | PCB_FULL_IRET); 971 td->td_retval[1] = 0; 972 } 973