ia32_signal.c revision 119336
1114987Speter/*- 2114987Speter * Copyright (c) 2003 Peter Wemm 3114987Speter * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. 4114987Speter * All rights reserved. 5114987Speter * 6114987Speter * This code is derived from software contributed to Berkeley by 7114987Speter * William Jolitz. 8114987Speter * 9114987Speter * Redistribution and use in source and binary forms, with or without 10114987Speter * modification, are permitted provided that the following conditions 11114987Speter * are met: 12114987Speter * 1. Redistributions of source code must retain the above copyright 13114987Speter * notice, this list of conditions and the following disclaimer. 14114987Speter * 2. Redistributions in binary form must reproduce the above copyright 15114987Speter * notice, this list of conditions and the following disclaimer in the 16114987Speter * documentation and/or other materials provided with the distribution. 17114987Speter * 3. All advertising materials mentioning features or use of this software 18114987Speter * must display the following acknowledgement: 19114987Speter * This product includes software developed by the University of 20114987Speter * California, Berkeley and its contributors. 21114987Speter * 4. Neither the name of the University nor the names of its contributors 22114987Speter * may be used to endorse or promote products derived from this software 23114987Speter * without specific prior written permission. 24114987Speter * 25114987Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26114987Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27114987Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28114987Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29114987Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30114987Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31114987Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32114987Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33114987Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34114987Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35114987Speter * SUCH DAMAGE. 36114987Speter */ 37114987Speter 38118031Sobrien#include <sys/cdefs.h> 39118031Sobrien__FBSDID("$FreeBSD: head/sys/amd64/ia32/ia32_signal.c 119336 2003-08-23 00:04:53Z peter $"); 40118031Sobrien 41114987Speter#include "opt_compat.h" 42114987Speter 43114987Speter#include <sys/param.h> 44114987Speter#include <sys/exec.h> 45114987Speter#include <sys/fcntl.h> 46114987Speter#include <sys/imgact.h> 47114987Speter#include <sys/kernel.h> 48114987Speter#include <sys/lock.h> 49114987Speter#include <sys/malloc.h> 50114987Speter#include <sys/mutex.h> 51114987Speter#include <sys/mman.h> 52114987Speter#include <sys/namei.h> 53114987Speter#include <sys/pioctl.h> 54114987Speter#include <sys/proc.h> 55114987Speter#include <sys/procfs.h> 56114987Speter#include <sys/resourcevar.h> 57114987Speter#include <sys/systm.h> 58114987Speter#include <sys/signalvar.h> 59114987Speter#include <sys/stat.h> 60114987Speter#include <sys/sx.h> 61114987Speter#include <sys/syscall.h> 62114987Speter#include <sys/sysctl.h> 63114987Speter#include <sys/sysent.h> 64114987Speter#include <sys/vnode.h> 65114987Speter 66114987Speter#include <vm/vm.h> 67114987Speter#include <vm/vm_kern.h> 68114987Speter#include <vm/vm_param.h> 69114987Speter#include <vm/pmap.h> 70114987Speter#include <vm/vm_map.h> 71114987Speter#include <vm/vm_object.h> 72114987Speter#include <vm/vm_extern.h> 73114987Speter 74119336Speter#include <compat/freebsd32/freebsd32_util.h> 75119336Speter#include <compat/freebsd32/freebsd32_proto.h> 76119336Speter#include <compat/ia32/ia32_signal.h> 77114987Speter#include <machine/psl.h> 78114987Speter#include <machine/segments.h> 79114987Speter#include <machine/specialreg.h> 80114987Speter#include <machine/frame.h> 81114987Speter#include <machine/md_var.h> 82114987Speter#include <machine/pcb.h> 83114987Speter#include <machine/cpufunc.h> 84114987Speter 85114987Speter#ifdef COMPAT_FREEBSD4 86114987Speterstatic void freebsd4_ia32_sendsig(sig_t, int, sigset_t *, u_long); 87114987Speter#endif 88114987Speterstatic void ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp); 89114987Speterstatic int ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp); 90114987Speter 91114987Speterextern int _ucode32sel, _udatasel; 92114987Speter 93114987Speter#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) 94114987Speter#define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) 95114987Speter 96114987Speterstatic void 97114987Speteria32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp) 98114987Speter{ 99114987Speter struct savefpu *addr; 100114987Speter 101114987Speter /* 102114987Speter * XXX mc_fpstate might be misaligned, since its declaration is not 103114987Speter * unportabilized using __attribute__((aligned(16))) like the 104114987Speter * declaration of struct savemm, and anyway, alignment doesn't work 105114987Speter * for auto variables since we don't use gcc's pessimal stack 106114987Speter * alignment. Work around this by abusing the spare fields after 107114987Speter * mcp->mc_fpstate. 108114987Speter * 109114987Speter * XXX unpessimize most cases by only aligning when fxsave might be 110114987Speter * called, although this requires knowing too much about 111114987Speter * npxgetregs()'s internals. 112114987Speter */ 113114987Speter addr = (struct savefpu *)&mcp->mc_fpstate; 114114987Speter if (td == PCPU_GET(fpcurthread) && ((uintptr_t)(void *)addr & 0xF)) { 115114987Speter do 116114987Speter addr = (void *)((char *)addr + 4); 117114987Speter while ((uintptr_t)(void *)addr & 0xF); 118114987Speter } 119114987Speter mcp->mc_ownedfp = npxgetregs(td, addr); 120114987Speter if (addr != (struct savefpu *)&mcp->mc_fpstate) { 121114987Speter bcopy(addr, &mcp->mc_fpstate, sizeof(mcp->mc_fpstate)); 122114987Speter bzero(&mcp->mc_spare2, sizeof(mcp->mc_spare2)); 123114987Speter } 124114987Speter mcp->mc_fpformat = npxformat(); 125114987Speter} 126114987Speter 127114987Speterstatic int 128114987Speteria32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp) 129114987Speter{ 130114987Speter struct savefpu *addr; 131114987Speter 132114987Speter if (mcp->mc_fpformat == _MC_FPFMT_NODEV) 133114987Speter return (0); 134114987Speter else if (mcp->mc_fpformat != _MC_FPFMT_XMM) 135114987Speter return (EINVAL); 136114987Speter else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) 137114987Speter /* We don't care what state is left in the FPU or PCB. */ 138114987Speter fpstate_drop(td); 139114987Speter else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU || 140114987Speter mcp->mc_ownedfp == _MC_FPOWNED_PCB) { 141114987Speter /* XXX align as above. */ 142114987Speter addr = (struct savefpu *)&mcp->mc_fpstate; 143114987Speter if (td == PCPU_GET(fpcurthread) && 144114987Speter ((uintptr_t)(void *)addr & 0xF)) { 145114987Speter do 146114987Speter addr = (void *)((char *)addr + 4); 147114987Speter while ((uintptr_t)(void *)addr & 0xF); 148114987Speter bcopy(&mcp->mc_fpstate, addr, sizeof(mcp->mc_fpstate)); 149114987Speter } 150114987Speter /* 151114987Speter * XXX we violate the dubious requirement that npxsetregs() 152114987Speter * be called with interrupts disabled. 153114987Speter */ 154114987Speter npxsetregs(td, addr); 155114987Speter /* 156114987Speter * Don't bother putting things back where they were in the 157114987Speter * misaligned case, since we know that the caller won't use 158114987Speter * them again. 159114987Speter */ 160114987Speter } else 161114987Speter return (EINVAL); 162114987Speter return (0); 163114987Speter} 164114987Speter 165114987Speter/* 166114987Speter * Send an interrupt to process. 167114987Speter * 168114987Speter * Stack is set up to allow sigcode stored 169114987Speter * at top to call routine, followed by kcall 170114987Speter * to sigreturn routine below. After sigreturn 171114987Speter * resets the signal mask, the stack, and the 172114987Speter * frame pointer, it returns to the user 173114987Speter * specified pc, psl. 174114987Speter */ 175114987Speter#ifdef COMPAT_FREEBSD4 176114987Speterstatic void 177114987Speterfreebsd4_ia32_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 178114987Speter{ 179114987Speter struct ia32_sigframe4 sf, *sfp; 180114987Speter struct proc *p; 181114987Speter struct thread *td; 182114987Speter struct sigacts *psp; 183114987Speter struct trapframe *regs; 184114987Speter int oonstack; 185114987Speter 186114987Speter td = curthread; 187114987Speter p = td->td_proc; 188114987Speter PROC_LOCK_ASSERT(p, MA_OWNED); 189114987Speter psp = p->p_sigacts; 190114987Speter regs = td->td_frame; 191114987Speter oonstack = sigonstack(regs->tf_rsp); 192114987Speter 193114987Speter /* Save user context. */ 194114987Speter bzero(&sf, sizeof(sf)); 195114987Speter sf.sf_uc.uc_sigmask = *mask; 196114987Speter sf.sf_uc.uc_stack.ss_sp = (uintptr_t)p->p_sigstk.ss_sp; 197114987Speter sf.sf_uc.uc_stack.ss_size = p->p_sigstk.ss_size; 198114987Speter sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK) 199114987Speter ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 200114987Speter sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 201114987Speter sf.sf_uc.uc_mcontext.mc_gs = rgs(); 202114987Speter sf.sf_uc.uc_mcontext.mc_fs = rfs(); 203114987Speter __asm __volatile("movl %%es,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_es)); 204114987Speter __asm __volatile("movl %%ds,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_ds)); 205114987Speter sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi; 206114987Speter sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi; 207114987Speter sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp; 208114987Speter sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */ 209114987Speter sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx; 210114987Speter sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx; 211114987Speter sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx; 212114987Speter sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax; 213114987Speter sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno; 214114987Speter sf.sf_uc.uc_mcontext.mc_err = regs->tf_err; 215114987Speter sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip; 216114987Speter sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs; 217114987Speter sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags; 218114987Speter sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp; 219114987Speter sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss; 220114987Speter 221114987Speter /* Allocate space for the signal handler context. */ 222114987Speter if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack && 223114987Speter SIGISMEMBER(psp->ps_sigonstack, sig)) { 224114987Speter sfp = (struct ia32_sigframe4 *)(p->p_sigstk.ss_sp + 225114987Speter p->p_sigstk.ss_size - sizeof(sf)); 226114987Speter } else 227114987Speter sfp = (struct ia32_sigframe4 *)regs->tf_rsp - 1; 228114987Speter PROC_UNLOCK(p); 229114987Speter 230114987Speter /* Translate the signal if appropriate. */ 231114987Speter if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 232114987Speter sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 233114987Speter 234114987Speter /* Build the argument list for the signal handler. */ 235114987Speter sf.sf_signum = sig; 236114987Speter sf.sf_ucontext = (register_t)&sfp->sf_uc; 237114987Speter PROC_LOCK(p); 238114987Speter if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { 239114987Speter /* Signal handler installed with SA_SIGINFO. */ 240114987Speter sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si; 241114987Speter sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 242114987Speter 243114987Speter /* Fill in POSIX parts */ 244114987Speter sf.sf_si.si_signo = sig; 245114987Speter sf.sf_si.si_code = code; 246114987Speter sf.sf_si.si_addr = regs->tf_addr; 247114987Speter } else { 248114987Speter /* Old FreeBSD-style arguments. */ 249114987Speter sf.sf_siginfo = code; 250114987Speter sf.sf_addr = regs->tf_addr; 251114987Speter sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 252114987Speter } 253114987Speter PROC_UNLOCK(p); 254114987Speter 255114987Speter /* 256114987Speter * Copy the sigframe out to the user's stack. 257114987Speter */ 258114987Speter if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { 259114987Speter#ifdef DEBUG 260114987Speter printf("process %ld has trashed its stack\n", (long)p->p_pid); 261114987Speter#endif 262114987Speter PROC_LOCK(p); 263114987Speter sigexit(td, SIGILL); 264114987Speter } 265114987Speter 266114987Speter regs->tf_rsp = (uintptr_t)sfp; 267119336Speter regs->tf_rip = FREEBSD32_PS_STRINGS - sz_freebsd4_ia32_sigcode; 268114987Speter regs->tf_rflags &= ~PSL_T; 269114987Speter regs->tf_cs = _ucode32sel; 270114987Speter regs->tf_ss = _udatasel; 271114987Speter load_ds(_udatasel); 272114987Speter td->td_pcb->pcb_ds = _udatasel; 273114987Speter load_es(_udatasel); 274114987Speter td->td_pcb->pcb_es = _udatasel; 275114987Speter /* leave user %fs and %gs untouched */ 276114987Speter PROC_LOCK(p); 277114987Speter} 278114987Speter#endif /* COMPAT_FREEBSD4 */ 279114987Speter 280114987Spetervoid 281114987Speteria32_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 282114987Speter{ 283114987Speter struct ia32_sigframe sf, *sfp; 284114987Speter struct proc *p; 285114987Speter struct thread *td; 286114987Speter struct sigacts *psp; 287114987Speter char *sp; 288114987Speter struct trapframe *regs; 289114987Speter int oonstack; 290114987Speter 291114987Speter td = curthread; 292114987Speter p = td->td_proc; 293114987Speter PROC_LOCK_ASSERT(p, MA_OWNED); 294114987Speter psp = p->p_sigacts; 295114987Speter#ifdef COMPAT_FREEBSD4 296114987Speter if (SIGISMEMBER(psp->ps_freebsd4, sig)) { 297114987Speter freebsd4_ia32_sendsig(catcher, sig, mask, code); 298114987Speter return; 299114987Speter } 300114987Speter#endif 301114987Speter regs = td->td_frame; 302114987Speter oonstack = sigonstack(regs->tf_rsp); 303114987Speter 304114987Speter /* Save user context. */ 305114987Speter bzero(&sf, sizeof(sf)); 306114987Speter sf.sf_uc.uc_sigmask = *mask; 307114987Speter sf.sf_uc.uc_stack.ss_sp = (uintptr_t)p->p_sigstk.ss_sp; 308114987Speter sf.sf_uc.uc_stack.ss_size = p->p_sigstk.ss_size; 309114987Speter sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK) 310114987Speter ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 311114987Speter sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 312114987Speter sf.sf_uc.uc_mcontext.mc_gs = rgs(); 313114987Speter sf.sf_uc.uc_mcontext.mc_fs = rfs(); 314114987Speter __asm __volatile("movl %%es,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_es)); 315114987Speter __asm __volatile("movl %%ds,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_ds)); 316114987Speter sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi; 317114987Speter sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi; 318114987Speter sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp; 319114987Speter sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */ 320114987Speter sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx; 321114987Speter sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx; 322114987Speter sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx; 323114987Speter sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax; 324114987Speter sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno; 325114987Speter sf.sf_uc.uc_mcontext.mc_err = regs->tf_err; 326114987Speter sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip; 327114987Speter sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs; 328114987Speter sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags; 329114987Speter sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp; 330114987Speter sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss; 331114987Speter sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */ 332114987Speter ia32_get_fpcontext(td, &sf.sf_uc.uc_mcontext); 333114987Speter fpstate_drop(td); 334114987Speter 335114987Speter /* Allocate space for the signal handler context. */ 336114987Speter if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack && 337114987Speter SIGISMEMBER(psp->ps_sigonstack, sig)) { 338114987Speter sp = p->p_sigstk.ss_sp + 339114987Speter p->p_sigstk.ss_size - sizeof(sf); 340114987Speter } else 341114987Speter sp = (char *)regs->tf_rsp - sizeof(sf); 342114987Speter /* Align to 16 bytes. */ 343114987Speter sfp = (struct ia32_sigframe *)((uintptr_t)sp & ~0xF); 344114987Speter PROC_UNLOCK(p); 345114987Speter 346114987Speter /* Translate the signal if appropriate. */ 347114987Speter if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 348114987Speter sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 349114987Speter 350114987Speter /* Build the argument list for the signal handler. */ 351114987Speter sf.sf_signum = sig; 352114987Speter sf.sf_ucontext = (register_t)&sfp->sf_uc; 353114987Speter PROC_LOCK(p); 354114987Speter if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { 355114987Speter /* Signal handler installed with SA_SIGINFO. */ 356114987Speter sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si; 357114987Speter sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 358114987Speter 359114987Speter /* Fill in POSIX parts */ 360114987Speter sf.sf_si.si_signo = sig; 361114987Speter sf.sf_si.si_code = code; 362114987Speter sf.sf_si.si_addr = regs->tf_addr; 363114987Speter } else { 364114987Speter /* Old FreeBSD-style arguments. */ 365114987Speter sf.sf_siginfo = code; 366115252Speter sf.sf_addr = regs->tf_addr; 367114987Speter sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 368114987Speter } 369114987Speter PROC_UNLOCK(p); 370114987Speter 371114987Speter /* 372114987Speter * Copy the sigframe out to the user's stack. 373114987Speter */ 374114987Speter if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { 375114987Speter#ifdef DEBUG 376114987Speter printf("process %ld has trashed its stack\n", (long)p->p_pid); 377114987Speter#endif 378114987Speter PROC_LOCK(p); 379114987Speter sigexit(td, SIGILL); 380114987Speter } 381114987Speter 382114987Speter regs->tf_rsp = (uintptr_t)sfp; 383119336Speter regs->tf_rip = FREEBSD32_PS_STRINGS - *(p->p_sysent->sv_szsigcode); 384114987Speter regs->tf_rflags &= ~PSL_T; 385114987Speter regs->tf_cs = _ucode32sel; 386114987Speter regs->tf_ss = _udatasel; 387114987Speter load_ds(_udatasel); 388114987Speter td->td_pcb->pcb_ds = _udatasel; 389114987Speter load_es(_udatasel); 390114987Speter td->td_pcb->pcb_es = _udatasel; 391114987Speter /* leave user %fs and %gs untouched */ 392114987Speter PROC_LOCK(p); 393114987Speter} 394114987Speter 395114987Speter/* 396114987Speter * System call to cleanup state after a signal 397114987Speter * has been taken. Reset signal mask and 398114987Speter * stack state from context left by sendsig (above). 399114987Speter * Return to previous pc and psl as specified by 400114987Speter * context left by sendsig. Check carefully to 401114987Speter * make sure that the user has not modified the 402114987Speter * state to gain improper privileges. 403114987Speter */ 404114987Speter#ifdef COMPAT_FREEBSD4 405114987Speter/* 406114987Speter * MPSAFE 407114987Speter */ 408114987Speterint 409119336Speterfreebsd4_freebsd32_sigreturn(td, uap) 410114987Speter struct thread *td; 411119336Speter struct freebsd4_freebsd32_sigreturn_args /* { 412119336Speter const struct freebsd4_freebsd32_ucontext *sigcntxp; 413114987Speter } */ *uap; 414114987Speter{ 415114987Speter struct ia32_ucontext4 uc; 416114987Speter struct proc *p = td->td_proc; 417114987Speter struct trapframe *regs; 418114987Speter const struct ia32_ucontext4 *ucp; 419114987Speter int cs, eflags, error; 420114987Speter 421114987Speter error = copyin(uap->sigcntxp, &uc, sizeof(uc)); 422114987Speter if (error != 0) 423114987Speter return (error); 424114987Speter ucp = &uc; 425114987Speter regs = td->td_frame; 426114987Speter eflags = ucp->uc_mcontext.mc_eflags; 427114987Speter /* 428114987Speter * Don't allow users to change privileged or reserved flags. 429114987Speter */ 430114987Speter /* 431114987Speter * XXX do allow users to change the privileged flag PSL_RF. 432114987Speter * The cpu sets PSL_RF in tf_eflags for faults. Debuggers 433114987Speter * should sometimes set it there too. tf_eflags is kept in 434114987Speter * the signal context during signal handling and there is no 435114987Speter * other place to remember it, so the PSL_RF bit may be 436114987Speter * corrupted by the signal handler without us knowing. 437114987Speter * Corruption of the PSL_RF bit at worst causes one more or 438114987Speter * one less debugger trap, so allowing it is fairly harmless. 439114987Speter */ 440114987Speter if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) { 441119336Speter printf("freebsd4_freebsd32_sigreturn: eflags = 0x%x\n", eflags); 442114987Speter return (EINVAL); 443114987Speter } 444114987Speter 445114987Speter /* 446114987Speter * Don't allow users to load a valid privileged %cs. Let the 447114987Speter * hardware check for invalid selectors, excess privilege in 448114987Speter * other selectors, invalid %eip's and invalid %esp's. 449114987Speter */ 450114987Speter cs = ucp->uc_mcontext.mc_cs; 451114987Speter if (!CS_SECURE(cs)) { 452114987Speter printf("freebsd4_sigreturn: cs = 0x%x\n", cs); 453114987Speter trapsignal(td, SIGBUS, T_PROTFLT); 454114987Speter return (EINVAL); 455114987Speter } 456114987Speter 457114987Speter /* Segment selectors restored by sigtramp.S */ 458114987Speter regs->tf_rdi = ucp->uc_mcontext.mc_edi; 459114987Speter regs->tf_rsi = ucp->uc_mcontext.mc_esi; 460114987Speter regs->tf_rbp = ucp->uc_mcontext.mc_ebp; 461114987Speter regs->tf_rbx = ucp->uc_mcontext.mc_ebx; 462114987Speter regs->tf_rdx = ucp->uc_mcontext.mc_edx; 463114987Speter regs->tf_rcx = ucp->uc_mcontext.mc_ecx; 464114987Speter regs->tf_rax = ucp->uc_mcontext.mc_eax; 465114987Speter regs->tf_trapno = ucp->uc_mcontext.mc_trapno; 466114987Speter regs->tf_err = ucp->uc_mcontext.mc_err; 467114987Speter regs->tf_rip = ucp->uc_mcontext.mc_eip; 468114987Speter regs->tf_cs = cs; 469114987Speter regs->tf_rflags = ucp->uc_mcontext.mc_eflags; 470114987Speter regs->tf_rsp = ucp->uc_mcontext.mc_esp; 471114987Speter regs->tf_ss = ucp->uc_mcontext.mc_ss; 472114987Speter 473114987Speter PROC_LOCK(p); 474114987Speter td->td_sigmask = ucp->uc_sigmask; 475114987Speter SIG_CANTMASK(td->td_sigmask); 476114987Speter signotify(td); 477114987Speter PROC_UNLOCK(p); 478114987Speter return (EJUSTRETURN); 479114987Speter} 480114987Speter#endif /* COMPAT_FREEBSD4 */ 481114987Speter 482114987Speter/* 483114987Speter * MPSAFE 484114987Speter */ 485114987Speterint 486119336Speterfreebsd32_sigreturn(td, uap) 487114987Speter struct thread *td; 488119336Speter struct freebsd32_sigreturn_args /* { 489119336Speter const struct freebsd32_ucontext *sigcntxp; 490114987Speter } */ *uap; 491114987Speter{ 492114987Speter struct ia32_ucontext uc; 493114987Speter struct proc *p = td->td_proc; 494114987Speter struct trapframe *regs; 495114987Speter const struct ia32_ucontext *ucp; 496114987Speter int cs, eflags, error, ret; 497114987Speter 498114987Speter error = copyin(uap->sigcntxp, &uc, sizeof(uc)); 499114987Speter if (error != 0) 500114987Speter return (error); 501114987Speter ucp = &uc; 502114987Speter regs = td->td_frame; 503114987Speter eflags = ucp->uc_mcontext.mc_eflags; 504114987Speter /* 505114987Speter * Don't allow users to change privileged or reserved flags. 506114987Speter */ 507114987Speter /* 508114987Speter * XXX do allow users to change the privileged flag PSL_RF. 509114987Speter * The cpu sets PSL_RF in tf_eflags for faults. Debuggers 510114987Speter * should sometimes set it there too. tf_eflags is kept in 511114987Speter * the signal context during signal handling and there is no 512114987Speter * other place to remember it, so the PSL_RF bit may be 513114987Speter * corrupted by the signal handler without us knowing. 514114987Speter * Corruption of the PSL_RF bit at worst causes one more or 515114987Speter * one less debugger trap, so allowing it is fairly harmless. 516114987Speter */ 517114987Speter if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) { 518119336Speter printf("freebsd32_sigreturn: eflags = 0x%x\n", eflags); 519114987Speter return (EINVAL); 520114987Speter } 521114987Speter 522114987Speter /* 523114987Speter * Don't allow users to load a valid privileged %cs. Let the 524114987Speter * hardware check for invalid selectors, excess privilege in 525114987Speter * other selectors, invalid %eip's and invalid %esp's. 526114987Speter */ 527114987Speter cs = ucp->uc_mcontext.mc_cs; 528114987Speter if (!CS_SECURE(cs)) { 529114987Speter printf("sigreturn: cs = 0x%x\n", cs); 530114987Speter trapsignal(td, SIGBUS, T_PROTFLT); 531114987Speter return (EINVAL); 532114987Speter } 533114987Speter 534114987Speter ret = ia32_set_fpcontext(td, &ucp->uc_mcontext); 535114987Speter if (ret != 0) 536114987Speter return (ret); 537114987Speter 538114987Speter /* Segment selectors restored by sigtramp.S */ 539114987Speter regs->tf_rdi = ucp->uc_mcontext.mc_edi; 540114987Speter regs->tf_rsi = ucp->uc_mcontext.mc_esi; 541114987Speter regs->tf_rbp = ucp->uc_mcontext.mc_ebp; 542114987Speter regs->tf_rbx = ucp->uc_mcontext.mc_ebx; 543114987Speter regs->tf_rdx = ucp->uc_mcontext.mc_edx; 544114987Speter regs->tf_rcx = ucp->uc_mcontext.mc_ecx; 545114987Speter regs->tf_rax = ucp->uc_mcontext.mc_eax; 546114987Speter regs->tf_trapno = ucp->uc_mcontext.mc_trapno; 547114987Speter regs->tf_err = ucp->uc_mcontext.mc_err; 548114987Speter regs->tf_rip = ucp->uc_mcontext.mc_eip; 549114987Speter regs->tf_cs = cs; 550114987Speter regs->tf_rflags = ucp->uc_mcontext.mc_eflags; 551114987Speter regs->tf_rsp = ucp->uc_mcontext.mc_esp; 552114987Speter regs->tf_ss = ucp->uc_mcontext.mc_ss; 553114987Speter 554114987Speter PROC_LOCK(p); 555114987Speter td->td_sigmask = ucp->uc_sigmask; 556114987Speter SIG_CANTMASK(td->td_sigmask); 557114987Speter signotify(td); 558114987Speter PROC_UNLOCK(p); 559114987Speter return (EJUSTRETURN); 560114987Speter} 561