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