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. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 */ 37 38 #include <sys/cdefs.h> 39 __FBSDID("$FreeBSD$"); 40 41 #include "opt_compat.h" 42 43 #include <sys/param.h> 44 #include <sys/exec.h> 45 #include <sys/fcntl.h> 46 #include <sys/imgact.h> 47 #include <sys/kernel.h> 48 #include <sys/lock.h> 49 #include <sys/malloc.h> 50 #include <sys/mutex.h> 51 #include <sys/mman.h> 52 #include <sys/namei.h> 53 #include <sys/pioctl.h> 54 #include <sys/proc.h> 55 #include <sys/procfs.h> 56 #include <sys/resourcevar.h> 57 #include <sys/systm.h> 58 #include <sys/signalvar.h> 59 #include <sys/stat.h> 60 #include <sys/sx.h> 61 #include <sys/syscall.h> 62 #include <sys/sysctl.h> 63 #include <sys/sysent.h> 64 #include <sys/vnode.h> 65 66 #include <vm/vm.h> 67 #include <vm/vm_kern.h> 68 #include <vm/vm_param.h> 69 #include <vm/pmap.h> 70 #include <vm/vm_map.h> 71 #include <vm/vm_object.h> 72 #include <vm/vm_extern.h> 73 74 #include <compat/freebsd32/freebsd32_util.h> 75 #include <compat/freebsd32/freebsd32_proto.h> 76 #include <compat/ia32/ia32_signal.h> 77 #include <machine/psl.h> 78 #include <machine/segments.h> 79 #include <machine/specialreg.h> 80 #include <machine/frame.h> 81 #include <machine/md_var.h> 82 #include <machine/pcb.h> 83 #include <machine/cpufunc.h> 84 85 #ifdef COMPAT_FREEBSD4 86 static void freebsd4_ia32_sendsig(sig_t, int, sigset_t *, u_long); 87 #endif 88 static void ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp); 89 static int ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp); 90 91 extern int _ucode32sel, _udatasel; 92 93 #define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) 94 #define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) 95 96 static void 97 ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp) 98 { 99 struct savefpu *addr; 100 101 /* 102 * XXX mc_fpstate might be misaligned, since its declaration is not 103 * unportabilized using __attribute__((aligned(16))) like the 104 * declaration of struct savemm, and anyway, alignment doesn't work 105 * for auto variables since we don't use gcc's pessimal stack 106 * alignment. Work around this by abusing the spare fields after 107 * mcp->mc_fpstate. 108 * 109 * XXX unpessimize most cases by only aligning when fxsave might be 110 * called, although this requires knowing too much about 111 * npxgetregs()'s internals. 112 */ 113 addr = (struct savefpu *)&mcp->mc_fpstate; 114 if (td == PCPU_GET(fpcurthread) && ((uintptr_t)(void *)addr & 0xF)) { 115 do 116 addr = (void *)((char *)addr + 4); 117 while ((uintptr_t)(void *)addr & 0xF); 118 } 119 mcp->mc_ownedfp = npxgetregs(td, addr); 120 if (addr != (struct savefpu *)&mcp->mc_fpstate) { 121 bcopy(addr, &mcp->mc_fpstate, sizeof(mcp->mc_fpstate)); 122 bzero(&mcp->mc_spare2, sizeof(mcp->mc_spare2)); 123 } 124 mcp->mc_fpformat = npxformat(); 125 } 126 127 static int 128 ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp) 129 { 130 struct savefpu *addr; 131 132 if (mcp->mc_fpformat == _MC_FPFMT_NODEV) 133 return (0); 134 else if (mcp->mc_fpformat != _MC_FPFMT_XMM) 135 return (EINVAL); 136 else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) 137 /* We don't care what state is left in the FPU or PCB. */ 138 fpstate_drop(td); 139 else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU || 140 mcp->mc_ownedfp == _MC_FPOWNED_PCB) { 141 /* XXX align as above. */ 142 addr = (struct savefpu *)&mcp->mc_fpstate; 143 if (td == PCPU_GET(fpcurthread) && 144 ((uintptr_t)(void *)addr & 0xF)) { 145 do 146 addr = (void *)((char *)addr + 4); 147 while ((uintptr_t)(void *)addr & 0xF); 148 bcopy(&mcp->mc_fpstate, addr, sizeof(mcp->mc_fpstate)); 149 } 150 /* 151 * XXX we violate the dubious requirement that npxsetregs() 152 * be called with interrupts disabled. 153 */ 154 npxsetregs(td, addr); 155 /* 156 * Don't bother putting things back where they were in the 157 * misaligned case, since we know that the caller won't use 158 * them again. 159 */ 160 } else 161 return (EINVAL); 162 return (0); 163 } 164 165 /* 166 * Send an interrupt to process. 167 * 168 * Stack is set up to allow sigcode stored 169 * at top to call routine, followed by kcall 170 * to sigreturn routine below. After sigreturn 171 * resets the signal mask, the stack, and the 172 * frame pointer, it returns to the user 173 * specified pc, psl. 174 */ 175 #ifdef COMPAT_FREEBSD4 176 static void 177 freebsd4_ia32_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 178 { 179 struct ia32_sigframe4 sf, *sfp; 180 struct proc *p; 181 struct thread *td; 182 struct sigacts *psp; 183 struct trapframe *regs; 184 int oonstack; 185 186 td = curthread; 187 p = td->td_proc; 188 PROC_LOCK_ASSERT(p, MA_OWNED); 189 psp = p->p_sigacts; 190 regs = td->td_frame; 191 oonstack = sigonstack(regs->tf_rsp); 192 193 /* Save user context. */ 194 bzero(&sf, sizeof(sf)); 195 sf.sf_uc.uc_sigmask = *mask; 196 sf.sf_uc.uc_stack.ss_sp = (uintptr_t)p->p_sigstk.ss_sp; 197 sf.sf_uc.uc_stack.ss_size = p->p_sigstk.ss_size; 198 sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK) 199 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 200 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 201 sf.sf_uc.uc_mcontext.mc_gs = rgs(); 202 sf.sf_uc.uc_mcontext.mc_fs = rfs(); 203 __asm __volatile("movl %%es,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_es)); 204 __asm __volatile("movl %%ds,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_ds)); 205 sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi; 206 sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi; 207 sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp; 208 sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */ 209 sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx; 210 sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx; 211 sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx; 212 sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax; 213 sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno; 214 sf.sf_uc.uc_mcontext.mc_err = regs->tf_err; 215 sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip; 216 sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs; 217 sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags; 218 sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp; 219 sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss; 220 221 /* Allocate space for the signal handler context. */ 222 if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack && 223 SIGISMEMBER(psp->ps_sigonstack, sig)) { 224 sfp = (struct ia32_sigframe4 *)(p->p_sigstk.ss_sp + 225 p->p_sigstk.ss_size - sizeof(sf)); 226 } else 227 sfp = (struct ia32_sigframe4 *)regs->tf_rsp - 1; 228 PROC_UNLOCK(p); 229 230 /* Translate the signal if appropriate. */ 231 if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 232 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 233 234 /* Build the argument list for the signal handler. */ 235 sf.sf_signum = sig; 236 sf.sf_ucontext = (register_t)&sfp->sf_uc; 237 PROC_LOCK(p); 238 if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { 239 /* Signal handler installed with SA_SIGINFO. */ 240 sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si; 241 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 242 243 /* Fill in POSIX parts */ 244 sf.sf_si.si_signo = sig; 245 sf.sf_si.si_code = code; 246 sf.sf_si.si_addr = regs->tf_addr; 247 } else { 248 /* Old FreeBSD-style arguments. */ 249 sf.sf_siginfo = code; 250 sf.sf_addr = regs->tf_addr; 251 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 252 } 253 PROC_UNLOCK(p); 254 255 /* 256 * Copy the sigframe out to the user's stack. 257 */ 258 if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { 259 #ifdef DEBUG 260 printf("process %ld has trashed its stack\n", (long)p->p_pid); 261 #endif 262 PROC_LOCK(p); 263 sigexit(td, SIGILL); 264 } 265 266 regs->tf_rsp = (uintptr_t)sfp; 267 regs->tf_rip = FREEBSD32_PS_STRINGS - sz_freebsd4_ia32_sigcode; 268 regs->tf_rflags &= ~PSL_T; 269 regs->tf_cs = _ucode32sel; 270 regs->tf_ss = _udatasel; 271 load_ds(_udatasel); 272 td->td_pcb->pcb_ds = _udatasel; 273 load_es(_udatasel); 274 td->td_pcb->pcb_es = _udatasel; 275 /* leave user %fs and %gs untouched */ 276 PROC_LOCK(p); 277 } 278 #endif /* COMPAT_FREEBSD4 */ 279 280 void 281 ia32_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 282 { 283 struct ia32_sigframe sf, *sfp; 284 struct proc *p; 285 struct thread *td; 286 struct sigacts *psp; 287 char *sp; 288 struct trapframe *regs; 289 int oonstack; 290 291 td = curthread; 292 p = td->td_proc; 293 PROC_LOCK_ASSERT(p, MA_OWNED); 294 psp = p->p_sigacts; 295 #ifdef COMPAT_FREEBSD4 296 if (SIGISMEMBER(psp->ps_freebsd4, sig)) { 297 freebsd4_ia32_sendsig(catcher, sig, mask, code); 298 return; 299 } 300 #endif 301 regs = td->td_frame; 302 oonstack = sigonstack(regs->tf_rsp); 303 304 /* Save user context. */ 305 bzero(&sf, sizeof(sf)); 306 sf.sf_uc.uc_sigmask = *mask; 307 sf.sf_uc.uc_stack.ss_sp = (uintptr_t)p->p_sigstk.ss_sp; 308 sf.sf_uc.uc_stack.ss_size = p->p_sigstk.ss_size; 309 sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK) 310 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 311 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 312 sf.sf_uc.uc_mcontext.mc_gs = rgs(); 313 sf.sf_uc.uc_mcontext.mc_fs = rfs(); 314 __asm __volatile("movl %%es,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_es)); 315 __asm __volatile("movl %%ds,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_ds)); 316 sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi; 317 sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi; 318 sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp; 319 sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */ 320 sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx; 321 sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx; 322 sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx; 323 sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax; 324 sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno; 325 sf.sf_uc.uc_mcontext.mc_err = regs->tf_err; 326 sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip; 327 sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs; 328 sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags; 329 sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp; 330 sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss; 331 sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */ 332 ia32_get_fpcontext(td, &sf.sf_uc.uc_mcontext); 333 fpstate_drop(td); 334 335 /* Allocate space for the signal handler context. */ 336 if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack && 337 SIGISMEMBER(psp->ps_sigonstack, sig)) { 338 sp = p->p_sigstk.ss_sp + 339 p->p_sigstk.ss_size - sizeof(sf); 340 } else 341 sp = (char *)regs->tf_rsp - sizeof(sf); 342 /* Align to 16 bytes. */ 343 sfp = (struct ia32_sigframe *)((uintptr_t)sp & ~0xF); 344 PROC_UNLOCK(p); 345 346 /* Translate the signal if appropriate. */ 347 if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 348 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 349 350 /* Build the argument list for the signal handler. */ 351 sf.sf_signum = sig; 352 sf.sf_ucontext = (register_t)&sfp->sf_uc; 353 PROC_LOCK(p); 354 if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { 355 /* Signal handler installed with SA_SIGINFO. */ 356 sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si; 357 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 358 359 /* Fill in POSIX parts */ 360 sf.sf_si.si_signo = sig; 361 sf.sf_si.si_code = code; 362 sf.sf_si.si_addr = regs->tf_addr; 363 } else { 364 /* Old FreeBSD-style arguments. */ 365 sf.sf_siginfo = code; 366 sf.sf_addr = regs->tf_addr; 367 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 368 } 369 PROC_UNLOCK(p); 370 371 /* 372 * Copy the sigframe out to the user's stack. 373 */ 374 if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { 375 #ifdef DEBUG 376 printf("process %ld has trashed its stack\n", (long)p->p_pid); 377 #endif 378 PROC_LOCK(p); 379 sigexit(td, SIGILL); 380 } 381 382 regs->tf_rsp = (uintptr_t)sfp; 383 regs->tf_rip = FREEBSD32_PS_STRINGS - *(p->p_sysent->sv_szsigcode); 384 regs->tf_rflags &= ~PSL_T; 385 regs->tf_cs = _ucode32sel; 386 regs->tf_ss = _udatasel; 387 load_ds(_udatasel); 388 td->td_pcb->pcb_ds = _udatasel; 389 load_es(_udatasel); 390 td->td_pcb->pcb_es = _udatasel; 391 /* leave user %fs and %gs untouched */ 392 PROC_LOCK(p); 393 } 394 395 /* 396 * System call to cleanup state after a signal 397 * has been taken. Reset signal mask and 398 * stack state from context left by sendsig (above). 399 * Return to previous pc and psl as specified by 400 * context left by sendsig. Check carefully to 401 * make sure that the user has not modified the 402 * state to gain improper privileges. 403 */ 404 #ifdef COMPAT_FREEBSD4 405 /* 406 * MPSAFE 407 */ 408 int 409 freebsd4_freebsd32_sigreturn(td, uap) 410 struct thread *td; 411 struct freebsd4_freebsd32_sigreturn_args /* { 412 const struct freebsd4_freebsd32_ucontext *sigcntxp; 413 } */ *uap; 414 { 415 struct ia32_ucontext4 uc; 416 struct proc *p = td->td_proc; 417 struct trapframe *regs; 418 const struct ia32_ucontext4 *ucp; 419 int cs, eflags, error; 420 421 error = copyin(uap->sigcntxp, &uc, sizeof(uc)); 422 if (error != 0) 423 return (error); 424 ucp = &uc; 425 regs = td->td_frame; 426 eflags = ucp->uc_mcontext.mc_eflags; 427 /* 428 * Don't allow users to change privileged or reserved flags. 429 */ 430 /* 431 * XXX do allow users to change the privileged flag PSL_RF. 432 * The cpu sets PSL_RF in tf_eflags for faults. Debuggers 433 * should sometimes set it there too. tf_eflags is kept in 434 * the signal context during signal handling and there is no 435 * other place to remember it, so the PSL_RF bit may be 436 * corrupted by the signal handler without us knowing. 437 * Corruption of the PSL_RF bit at worst causes one more or 438 * one less debugger trap, so allowing it is fairly harmless. 439 */ 440 if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) { 441 printf("freebsd4_freebsd32_sigreturn: eflags = 0x%x\n", eflags); 442 return (EINVAL); 443 } 444 445 /* 446 * Don't allow users to load a valid privileged %cs. Let the 447 * hardware check for invalid selectors, excess privilege in 448 * other selectors, invalid %eip's and invalid %esp's. 449 */ 450 cs = ucp->uc_mcontext.mc_cs; 451 if (!CS_SECURE(cs)) { 452 printf("freebsd4_sigreturn: cs = 0x%x\n", cs); 453 trapsignal(td, SIGBUS, T_PROTFLT); 454 return (EINVAL); 455 } 456 457 /* Segment selectors restored by sigtramp.S */ 458 regs->tf_rdi = ucp->uc_mcontext.mc_edi; 459 regs->tf_rsi = ucp->uc_mcontext.mc_esi; 460 regs->tf_rbp = ucp->uc_mcontext.mc_ebp; 461 regs->tf_rbx = ucp->uc_mcontext.mc_ebx; 462 regs->tf_rdx = ucp->uc_mcontext.mc_edx; 463 regs->tf_rcx = ucp->uc_mcontext.mc_ecx; 464 regs->tf_rax = ucp->uc_mcontext.mc_eax; 465 regs->tf_trapno = ucp->uc_mcontext.mc_trapno; 466 regs->tf_err = ucp->uc_mcontext.mc_err; 467 regs->tf_rip = ucp->uc_mcontext.mc_eip; 468 regs->tf_cs = cs; 469 regs->tf_rflags = ucp->uc_mcontext.mc_eflags; 470 regs->tf_rsp = ucp->uc_mcontext.mc_esp; 471 regs->tf_ss = ucp->uc_mcontext.mc_ss; 472 473 PROC_LOCK(p); 474 td->td_sigmask = ucp->uc_sigmask; 475 SIG_CANTMASK(td->td_sigmask); 476 signotify(td); 477 PROC_UNLOCK(p); 478 return (EJUSTRETURN); 479 } 480 #endif /* COMPAT_FREEBSD4 */ 481 482 /* 483 * MPSAFE 484 */ 485 int 486 freebsd32_sigreturn(td, uap) 487 struct thread *td; 488 struct freebsd32_sigreturn_args /* { 489 const struct freebsd32_ucontext *sigcntxp; 490 } */ *uap; 491 { 492 struct ia32_ucontext uc; 493 struct proc *p = td->td_proc; 494 struct trapframe *regs; 495 const struct ia32_ucontext *ucp; 496 int cs, eflags, error, ret; 497 498 error = copyin(uap->sigcntxp, &uc, sizeof(uc)); 499 if (error != 0) 500 return (error); 501 ucp = &uc; 502 regs = td->td_frame; 503 eflags = ucp->uc_mcontext.mc_eflags; 504 /* 505 * Don't allow users to change privileged or reserved flags. 506 */ 507 /* 508 * XXX do allow users to change the privileged flag PSL_RF. 509 * The cpu sets PSL_RF in tf_eflags for faults. Debuggers 510 * should sometimes set it there too. tf_eflags is kept in 511 * the signal context during signal handling and there is no 512 * other place to remember it, so the PSL_RF bit may be 513 * corrupted by the signal handler without us knowing. 514 * Corruption of the PSL_RF bit at worst causes one more or 515 * one less debugger trap, so allowing it is fairly harmless. 516 */ 517 if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) { 518 printf("freebsd32_sigreturn: eflags = 0x%x\n", eflags); 519 return (EINVAL); 520 } 521 522 /* 523 * Don't allow users to load a valid privileged %cs. Let the 524 * hardware check for invalid selectors, excess privilege in 525 * other selectors, invalid %eip's and invalid %esp's. 526 */ 527 cs = ucp->uc_mcontext.mc_cs; 528 if (!CS_SECURE(cs)) { 529 printf("sigreturn: cs = 0x%x\n", cs); 530 trapsignal(td, SIGBUS, T_PROTFLT); 531 return (EINVAL); 532 } 533 534 ret = ia32_set_fpcontext(td, &ucp->uc_mcontext); 535 if (ret != 0) 536 return (ret); 537 538 /* Segment selectors restored by sigtramp.S */ 539 regs->tf_rdi = ucp->uc_mcontext.mc_edi; 540 regs->tf_rsi = ucp->uc_mcontext.mc_esi; 541 regs->tf_rbp = ucp->uc_mcontext.mc_ebp; 542 regs->tf_rbx = ucp->uc_mcontext.mc_ebx; 543 regs->tf_rdx = ucp->uc_mcontext.mc_edx; 544 regs->tf_rcx = ucp->uc_mcontext.mc_ecx; 545 regs->tf_rax = ucp->uc_mcontext.mc_eax; 546 regs->tf_trapno = ucp->uc_mcontext.mc_trapno; 547 regs->tf_err = ucp->uc_mcontext.mc_err; 548 regs->tf_rip = ucp->uc_mcontext.mc_eip; 549 regs->tf_cs = cs; 550 regs->tf_rflags = ucp->uc_mcontext.mc_eflags; 551 regs->tf_rsp = ucp->uc_mcontext.mc_esp; 552 regs->tf_ss = ucp->uc_mcontext.mc_ss; 553 554 PROC_LOCK(p); 555 td->td_sigmask = ucp->uc_sigmask; 556 SIG_CANTMASK(td->td_sigmask); 557 signotify(td); 558 PROC_UNLOCK(p); 559 return (EJUSTRETURN); 560 } 561