ia32_signal.c revision 123119
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: head/sys/amd64/ia32/ia32_signal.c 123119 2003-12-03 07:00:30Z peter $"); 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 86static void freebsd4_ia32_sendsig(sig_t, int, sigset_t *, u_long); 87#endif 88static void ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp); 89static int ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp); 90 91extern 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 96static void 97ia32_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 * fpugetregs()'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 = fpugetregs(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 = fpuformat(); 125} 126 127static int 128ia32_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 fpusetregs() 152 * be called with interrupts disabled. 153 */ 154 fpusetregs(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 176static void 177freebsd4_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 mtx_assert(&psp->ps_mtx, MA_OWNED); 191 regs = td->td_frame; 192 oonstack = sigonstack(regs->tf_rsp); 193 194 /* Save user context. */ 195 bzero(&sf, sizeof(sf)); 196 sf.sf_uc.uc_sigmask = *mask; 197 sf.sf_uc.uc_stack.ss_sp = (uintptr_t)p->p_sigstk.ss_sp; 198 sf.sf_uc.uc_stack.ss_size = p->p_sigstk.ss_size; 199 sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK) 200 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 201 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 202 sf.sf_uc.uc_mcontext.mc_gs = rgs(); 203 sf.sf_uc.uc_mcontext.mc_fs = rfs(); 204 __asm __volatile("movl %%es,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_es)); 205 __asm __volatile("movl %%ds,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_ds)); 206 sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi; 207 sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi; 208 sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp; 209 sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */ 210 sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx; 211 sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx; 212 sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx; 213 sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax; 214 sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno; 215 sf.sf_uc.uc_mcontext.mc_err = regs->tf_err; 216 sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip; 217 sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs; 218 sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags; 219 sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp; 220 sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss; 221 222 /* Allocate space for the signal handler context. */ 223 if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack && 224 SIGISMEMBER(psp->ps_sigonstack, sig)) { 225 sfp = (struct ia32_sigframe4 *)(p->p_sigstk.ss_sp + 226 p->p_sigstk.ss_size - sizeof(sf)); 227 } else 228 sfp = (struct ia32_sigframe4 *)regs->tf_rsp - 1; 229 PROC_UNLOCK(p); 230 231 /* Translate the signal if appropriate. */ 232 if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 233 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 234 235 /* Build the argument list for the signal handler. */ 236 sf.sf_signum = sig; 237 sf.sf_ucontext = (register_t)&sfp->sf_uc; 238 PROC_LOCK(p); 239 if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { 240 /* Signal handler installed with SA_SIGINFO. */ 241 sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si; 242 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 243 244 /* Fill in POSIX parts */ 245 sf.sf_si.si_signo = sig; 246 sf.sf_si.si_code = code; 247 sf.sf_si.si_addr = regs->tf_addr; 248 } else { 249 /* Old FreeBSD-style arguments. */ 250 sf.sf_siginfo = code; 251 sf.sf_addr = regs->tf_addr; 252 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 253 } 254 mtx_unlock(&psp->ps_mtx); 255 PROC_UNLOCK(p); 256 257 /* 258 * Copy the sigframe out to the user's stack. 259 */ 260 if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { 261#ifdef DEBUG 262 printf("process %ld has trashed its stack\n", (long)p->p_pid); 263#endif 264 PROC_LOCK(p); 265 sigexit(td, SIGILL); 266 } 267 268 regs->tf_rsp = (uintptr_t)sfp; 269 regs->tf_rip = FREEBSD32_PS_STRINGS - sz_freebsd4_ia32_sigcode; 270 regs->tf_rflags &= ~PSL_T; 271 regs->tf_cs = _ucode32sel; 272 regs->tf_ss = _udatasel; 273 load_ds(_udatasel); 274 td->td_pcb->pcb_ds = _udatasel; 275 load_es(_udatasel); 276 td->td_pcb->pcb_es = _udatasel; 277 /* leave user %fs and %gs untouched */ 278 PROC_LOCK(p); 279 mtx_lock(&psp->ps_mtx); 280} 281#endif /* COMPAT_FREEBSD4 */ 282 283void 284ia32_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 285{ 286 struct ia32_sigframe sf, *sfp; 287 struct proc *p; 288 struct thread *td; 289 struct sigacts *psp; 290 char *sp; 291 struct trapframe *regs; 292 int oonstack; 293 294 td = curthread; 295 p = td->td_proc; 296 PROC_LOCK_ASSERT(p, MA_OWNED); 297 psp = p->p_sigacts; 298#ifdef COMPAT_FREEBSD4 299 if (SIGISMEMBER(psp->ps_freebsd4, sig)) { 300 freebsd4_ia32_sendsig(catcher, sig, mask, code); 301 return; 302 } 303#endif 304 mtx_assert(&psp->ps_mtx, MA_OWNED); 305 regs = td->td_frame; 306 oonstack = sigonstack(regs->tf_rsp); 307 308 /* Save user context. */ 309 bzero(&sf, sizeof(sf)); 310 sf.sf_uc.uc_sigmask = *mask; 311 sf.sf_uc.uc_stack.ss_sp = (uintptr_t)p->p_sigstk.ss_sp; 312 sf.sf_uc.uc_stack.ss_size = p->p_sigstk.ss_size; 313 sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK) 314 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 315 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 316 sf.sf_uc.uc_mcontext.mc_gs = rgs(); 317 sf.sf_uc.uc_mcontext.mc_fs = rfs(); 318 __asm __volatile("movl %%es,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_es)); 319 __asm __volatile("movl %%ds,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_ds)); 320 sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi; 321 sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi; 322 sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp; 323 sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */ 324 sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx; 325 sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx; 326 sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx; 327 sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax; 328 sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno; 329 sf.sf_uc.uc_mcontext.mc_err = regs->tf_err; 330 sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip; 331 sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs; 332 sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags; 333 sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp; 334 sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss; 335 sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */ 336 ia32_get_fpcontext(td, &sf.sf_uc.uc_mcontext); 337 fpstate_drop(td); 338 339 /* Allocate space for the signal handler context. */ 340 if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack && 341 SIGISMEMBER(psp->ps_sigonstack, sig)) { 342 sp = p->p_sigstk.ss_sp + 343 p->p_sigstk.ss_size - sizeof(sf); 344 } else 345 sp = (char *)regs->tf_rsp - sizeof(sf); 346 /* Align to 16 bytes. */ 347 sfp = (struct ia32_sigframe *)((uintptr_t)sp & ~0xF); 348 PROC_UNLOCK(p); 349 350 /* Translate the signal if appropriate. */ 351 if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 352 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 353 354 /* Build the argument list for the signal handler. */ 355 sf.sf_signum = sig; 356 sf.sf_ucontext = (register_t)&sfp->sf_uc; 357 PROC_LOCK(p); 358 if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { 359 /* Signal handler installed with SA_SIGINFO. */ 360 sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si; 361 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 362 363 /* Fill in POSIX parts */ 364 sf.sf_si.si_signo = sig; 365 sf.sf_si.si_code = code; 366 sf.sf_si.si_addr = regs->tf_addr; 367 } else { 368 /* Old FreeBSD-style arguments. */ 369 sf.sf_siginfo = code; 370 sf.sf_addr = regs->tf_addr; 371 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 372 } 373 mtx_unlock(&psp->ps_mtx); 374 PROC_UNLOCK(p); 375 376 /* 377 * Copy the sigframe out to the user's stack. 378 */ 379 if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { 380#ifdef DEBUG 381 printf("process %ld has trashed its stack\n", (long)p->p_pid); 382#endif 383 PROC_LOCK(p); 384 sigexit(td, SIGILL); 385 } 386 387 regs->tf_rsp = (uintptr_t)sfp; 388 regs->tf_rip = FREEBSD32_PS_STRINGS - *(p->p_sysent->sv_szsigcode); 389 regs->tf_rflags &= ~PSL_T; 390 regs->tf_cs = _ucode32sel; 391 regs->tf_ss = _udatasel; 392 load_ds(_udatasel); 393 td->td_pcb->pcb_ds = _udatasel; 394 load_es(_udatasel); 395 td->td_pcb->pcb_es = _udatasel; 396 /* leave user %fs and %gs untouched */ 397 PROC_LOCK(p); 398 mtx_lock(&psp->ps_mtx); 399} 400 401/* 402 * System call to cleanup state after a signal 403 * has been taken. Reset signal mask and 404 * stack state from context left by sendsig (above). 405 * Return to previous pc and psl as specified by 406 * context left by sendsig. Check carefully to 407 * make sure that the user has not modified the 408 * state to gain improper privileges. 409 */ 410#ifdef COMPAT_FREEBSD4 411/* 412 * MPSAFE 413 */ 414int 415freebsd4_freebsd32_sigreturn(td, uap) 416 struct thread *td; 417 struct freebsd4_freebsd32_sigreturn_args /* { 418 const struct freebsd4_freebsd32_ucontext *sigcntxp; 419 } */ *uap; 420{ 421 struct ia32_ucontext4 uc; 422 struct proc *p = td->td_proc; 423 struct trapframe *regs; 424 const struct ia32_ucontext4 *ucp; 425 int cs, eflags, error; 426 427 error = copyin(uap->sigcntxp, &uc, sizeof(uc)); 428 if (error != 0) 429 return (error); 430 ucp = &uc; 431 regs = td->td_frame; 432 eflags = ucp->uc_mcontext.mc_eflags; 433 /* 434 * Don't allow users to change privileged or reserved flags. 435 */ 436 /* 437 * XXX do allow users to change the privileged flag PSL_RF. 438 * The cpu sets PSL_RF in tf_eflags for faults. Debuggers 439 * should sometimes set it there too. tf_eflags is kept in 440 * the signal context during signal handling and there is no 441 * other place to remember it, so the PSL_RF bit may be 442 * corrupted by the signal handler without us knowing. 443 * Corruption of the PSL_RF bit at worst causes one more or 444 * one less debugger trap, so allowing it is fairly harmless. 445 */ 446 if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) { 447 printf("freebsd4_freebsd32_sigreturn: eflags = 0x%x\n", eflags); 448 return (EINVAL); 449 } 450 451 /* 452 * Don't allow users to load a valid privileged %cs. Let the 453 * hardware check for invalid selectors, excess privilege in 454 * other selectors, invalid %eip's and invalid %esp's. 455 */ 456 cs = ucp->uc_mcontext.mc_cs; 457 if (!CS_SECURE(cs)) { 458 printf("freebsd4_sigreturn: cs = 0x%x\n", cs); 459 trapsignal(td, SIGBUS, T_PROTFLT); 460 return (EINVAL); 461 } 462 463 /* Segment selectors restored by sigtramp.S */ 464 regs->tf_rdi = ucp->uc_mcontext.mc_edi; 465 regs->tf_rsi = ucp->uc_mcontext.mc_esi; 466 regs->tf_rbp = ucp->uc_mcontext.mc_ebp; 467 regs->tf_rbx = ucp->uc_mcontext.mc_ebx; 468 regs->tf_rdx = ucp->uc_mcontext.mc_edx; 469 regs->tf_rcx = ucp->uc_mcontext.mc_ecx; 470 regs->tf_rax = ucp->uc_mcontext.mc_eax; 471 regs->tf_trapno = ucp->uc_mcontext.mc_trapno; 472 regs->tf_err = ucp->uc_mcontext.mc_err; 473 regs->tf_rip = ucp->uc_mcontext.mc_eip; 474 regs->tf_cs = cs; 475 regs->tf_rflags = ucp->uc_mcontext.mc_eflags; 476 regs->tf_rsp = ucp->uc_mcontext.mc_esp; 477 regs->tf_ss = ucp->uc_mcontext.mc_ss; 478 479 PROC_LOCK(p); 480 td->td_sigmask = ucp->uc_sigmask; 481 SIG_CANTMASK(td->td_sigmask); 482 signotify(td); 483 PROC_UNLOCK(p); 484 return (EJUSTRETURN); 485} 486#endif /* COMPAT_FREEBSD4 */ 487 488/* 489 * MPSAFE 490 */ 491int 492freebsd32_sigreturn(td, uap) 493 struct thread *td; 494 struct freebsd32_sigreturn_args /* { 495 const struct freebsd32_ucontext *sigcntxp; 496 } */ *uap; 497{ 498 struct ia32_ucontext uc; 499 struct proc *p = td->td_proc; 500 struct trapframe *regs; 501 const struct ia32_ucontext *ucp; 502 int cs, eflags, error, ret; 503 504 error = copyin(uap->sigcntxp, &uc, sizeof(uc)); 505 if (error != 0) 506 return (error); 507 ucp = &uc; 508 regs = td->td_frame; 509 eflags = ucp->uc_mcontext.mc_eflags; 510 /* 511 * Don't allow users to change privileged or reserved flags. 512 */ 513 /* 514 * XXX do allow users to change the privileged flag PSL_RF. 515 * The cpu sets PSL_RF in tf_eflags for faults. Debuggers 516 * should sometimes set it there too. tf_eflags is kept in 517 * the signal context during signal handling and there is no 518 * other place to remember it, so the PSL_RF bit may be 519 * corrupted by the signal handler without us knowing. 520 * Corruption of the PSL_RF bit at worst causes one more or 521 * one less debugger trap, so allowing it is fairly harmless. 522 */ 523 if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) { 524 printf("freebsd32_sigreturn: eflags = 0x%x\n", eflags); 525 return (EINVAL); 526 } 527 528 /* 529 * Don't allow users to load a valid privileged %cs. Let the 530 * hardware check for invalid selectors, excess privilege in 531 * other selectors, invalid %eip's and invalid %esp's. 532 */ 533 cs = ucp->uc_mcontext.mc_cs; 534 if (!CS_SECURE(cs)) { 535 printf("sigreturn: cs = 0x%x\n", cs); 536 trapsignal(td, SIGBUS, T_PROTFLT); 537 return (EINVAL); 538 } 539 540 ret = ia32_set_fpcontext(td, &ucp->uc_mcontext); 541 if (ret != 0) 542 return (ret); 543 544 /* Segment selectors restored by sigtramp.S */ 545 regs->tf_rdi = ucp->uc_mcontext.mc_edi; 546 regs->tf_rsi = ucp->uc_mcontext.mc_esi; 547 regs->tf_rbp = ucp->uc_mcontext.mc_ebp; 548 regs->tf_rbx = ucp->uc_mcontext.mc_ebx; 549 regs->tf_rdx = ucp->uc_mcontext.mc_edx; 550 regs->tf_rcx = ucp->uc_mcontext.mc_ecx; 551 regs->tf_rax = ucp->uc_mcontext.mc_eax; 552 regs->tf_trapno = ucp->uc_mcontext.mc_trapno; 553 regs->tf_err = ucp->uc_mcontext.mc_err; 554 regs->tf_rip = ucp->uc_mcontext.mc_eip; 555 regs->tf_cs = cs; 556 regs->tf_rflags = ucp->uc_mcontext.mc_eflags; 557 regs->tf_rsp = ucp->uc_mcontext.mc_esp; 558 regs->tf_ss = ucp->uc_mcontext.mc_ss; 559 560 PROC_LOCK(p); 561 td->td_sigmask = ucp->uc_sigmask; 562 SIG_CANTMASK(td->td_sigmask); 563 signotify(td); 564 PROC_UNLOCK(p); 565 return (EJUSTRETURN); 566} 567 568/* 569 * Clear registers on exec 570 */ 571void 572ia32_setregs(td, entry, stack, ps_strings) 573 struct thread *td; 574 u_long entry; 575 u_long stack; 576 u_long ps_strings; 577{ 578 struct trapframe *regs = td->td_frame; 579 struct pcb *pcb = td->td_pcb; 580 581 wrmsr(MSR_FSBASE, 0); 582 wrmsr(MSR_KGSBASE, 0); /* User value while we're in the kernel */ 583 pcb->pcb_fsbase = 0; 584 pcb->pcb_gsbase = 0; 585 load_ds(_udatasel); 586 load_es(_udatasel); 587 load_fs(_udatasel); 588 load_gs(_udatasel); 589 pcb->pcb_ds = _udatasel; 590 pcb->pcb_es = _udatasel; 591 pcb->pcb_fs = _udatasel; 592 pcb->pcb_gs = _udatasel; 593 594 bzero((char *)regs, sizeof(struct trapframe)); 595 regs->tf_rip = entry; 596 regs->tf_rsp = stack; 597 regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T); 598 regs->tf_ss = _udatasel; 599 regs->tf_cs = _ucode32sel; 600 regs->tf_rbx = ps_strings; 601 load_cr0(rcr0() | CR0_MP | CR0_TS); 602 fpstate_drop(td); 603 604 /* Return via doreti so that we can change to a different %cs */ 605 pcb->pcb_flags |= PCB_FULLCTX; 606 td->td_retval[1] = 0; 607} 608