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 * 4. Neither the name of the University nor the names of its contributors 18114987Speter * may be used to endorse or promote products derived from this software 19114987Speter * without specific prior written permission. 20114987Speter * 21114987Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22114987Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23114987Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24114987Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25114987Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26114987Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27114987Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28114987Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29114987Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30114987Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31114987Speter * SUCH DAMAGE. 32114987Speter */ 33114987Speter 34118031Sobrien#include <sys/cdefs.h> 35118031Sobrien__FBSDID("$FreeBSD: stable/11/sys/amd64/ia32/ia32_signal.c 341165 2018-11-28 21:19:58Z vangyzen $"); 36118031Sobrien 37114987Speter#include "opt_compat.h" 38114987Speter 39114987Speter#include <sys/param.h> 40114987Speter#include <sys/exec.h> 41114987Speter#include <sys/fcntl.h> 42114987Speter#include <sys/imgact.h> 43114987Speter#include <sys/kernel.h> 44114987Speter#include <sys/lock.h> 45114987Speter#include <sys/malloc.h> 46114987Speter#include <sys/mutex.h> 47114987Speter#include <sys/mman.h> 48114987Speter#include <sys/namei.h> 49114987Speter#include <sys/pioctl.h> 50114987Speter#include <sys/proc.h> 51114987Speter#include <sys/procfs.h> 52114987Speter#include <sys/resourcevar.h> 53114987Speter#include <sys/systm.h> 54114987Speter#include <sys/signalvar.h> 55114987Speter#include <sys/stat.h> 56114987Speter#include <sys/sx.h> 57114987Speter#include <sys/syscall.h> 58209613Sjhb#include <sys/syscallsubr.h> 59114987Speter#include <sys/sysctl.h> 60114987Speter#include <sys/sysent.h> 61114987Speter#include <sys/vnode.h> 62114987Speter 63114987Speter#include <vm/vm.h> 64114987Speter#include <vm/vm_kern.h> 65114987Speter#include <vm/vm_param.h> 66114987Speter#include <vm/pmap.h> 67114987Speter#include <vm/vm_map.h> 68114987Speter#include <vm/vm_object.h> 69114987Speter#include <vm/vm_extern.h> 70114987Speter 71163018Sdavidxu#include <compat/freebsd32/freebsd32_signal.h> 72119336Speter#include <compat/freebsd32/freebsd32_util.h> 73119336Speter#include <compat/freebsd32/freebsd32_proto.h> 74230426Skib#include <compat/freebsd32/freebsd32.h> 75119336Speter#include <compat/ia32/ia32_signal.h> 76114987Speter#include <machine/psl.h> 77114987Speter#include <machine/segments.h> 78114987Speter#include <machine/specialreg.h> 79114987Speter#include <machine/frame.h> 80114987Speter#include <machine/md_var.h> 81114987Speter#include <machine/pcb.h> 82114987Speter#include <machine/cpufunc.h> 83114987Speter 84114987Speter#ifdef COMPAT_FREEBSD4 85151316Sdavidxustatic void freebsd4_ia32_sendsig(sig_t, ksiginfo_t *, sigset_t *); 86114987Speter#endif 87114987Speter 88114987Speter#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) 89114987Speter#define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) 90114987Speter 91114987Speterstatic void 92230426Skibia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp, 93230426Skib char *xfpusave, size_t xfpusave_len) 94114987Speter{ 95230426Skib size_t max_len, len; 96114987Speter 97209208Skib /* 98209208Skib * XXX Format of 64bit and 32bit FXSAVE areas differs. FXSAVE 99209208Skib * in 32bit mode saves %cs and %ds, while on 64bit it saves 100209208Skib * 64bit instruction and data pointers. Ignore the difference 101209208Skib * for now, it should be irrelevant for most applications. 102209208Skib */ 103215865Skib mcp->mc_ownedfp = fpugetregs(td); 104251039Skib bcopy(get_pcb_user_save_td(td), &mcp->mc_fpstate[0], 105215865Skib sizeof(mcp->mc_fpstate)); 106122292Speter mcp->mc_fpformat = fpuformat(); 107230426Skib if (!use_xsave || xfpusave_len == 0) 108230426Skib return; 109230426Skib max_len = cpu_max_ext_state_size - sizeof(struct savefpu); 110230426Skib len = xfpusave_len; 111230426Skib if (len > max_len) { 112230426Skib len = max_len; 113230426Skib bzero(xfpusave + max_len, len - max_len); 114230426Skib } 115251038Skib mcp->mc_flags |= _MC_IA32_HASFPXSTATE; 116230426Skib mcp->mc_xfpustate_len = len; 117230426Skib bcopy(get_pcb_user_save_td(td) + 1, xfpusave, len); 118114987Speter} 119114987Speter 120114987Speterstatic int 121278001Skibia32_set_fpcontext(struct thread *td, struct ia32_mcontext *mcp, 122230426Skib char *xfpustate, size_t xfpustate_len) 123114987Speter{ 124230426Skib int error; 125114987Speter 126114987Speter if (mcp->mc_fpformat == _MC_FPFMT_NODEV) 127114987Speter return (0); 128114987Speter else if (mcp->mc_fpformat != _MC_FPFMT_XMM) 129114987Speter return (EINVAL); 130230426Skib else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) { 131114987Speter /* We don't care what state is left in the FPU or PCB. */ 132114987Speter fpstate_drop(td); 133230426Skib error = 0; 134230426Skib } else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU || 135114987Speter mcp->mc_ownedfp == _MC_FPOWNED_PCB) { 136230426Skib error = fpusetregs(td, (struct savefpu *)&mcp->mc_fpstate, 137230426Skib xfpustate, xfpustate_len); 138114987Speter } else 139114987Speter return (EINVAL); 140230426Skib return (error); 141114987Speter} 142114987Speter 143114987Speter/* 144150631Speter * Get machine context. 145150631Speter */ 146150631Speterstatic int 147150631Speteria32_get_mcontext(struct thread *td, struct ia32_mcontext *mcp, int flags) 148150631Speter{ 149216634Sjkim struct pcb *pcb; 150150631Speter struct trapframe *tp; 151150631Speter 152216634Sjkim pcb = td->td_pcb; 153150631Speter tp = td->td_frame; 154150631Speter 155150631Speter PROC_LOCK(curthread->td_proc); 156150631Speter mcp->mc_onstack = sigonstack(tp->tf_rsp); 157150631Speter PROC_UNLOCK(curthread->td_proc); 158190620Skib /* Entry into kernel always sets TF_HASSEGS */ 159190620Skib mcp->mc_gs = tp->tf_gs; 160190620Skib mcp->mc_fs = tp->tf_fs; 161190620Skib mcp->mc_es = tp->tf_es; 162190620Skib mcp->mc_ds = tp->tf_ds; 163150631Speter mcp->mc_edi = tp->tf_rdi; 164150631Speter mcp->mc_esi = tp->tf_rsi; 165150631Speter mcp->mc_ebp = tp->tf_rbp; 166150631Speter mcp->mc_isp = tp->tf_rsp; 167206992Skib mcp->mc_eflags = tp->tf_rflags; 168150631Speter if (flags & GET_MC_CLEAR_RET) { 169150631Speter mcp->mc_eax = 0; 170150631Speter mcp->mc_edx = 0; 171206992Skib mcp->mc_eflags &= ~PSL_C; 172150631Speter } else { 173150631Speter mcp->mc_eax = tp->tf_rax; 174150631Speter mcp->mc_edx = tp->tf_rdx; 175150631Speter } 176150631Speter mcp->mc_ebx = tp->tf_rbx; 177150631Speter mcp->mc_ecx = tp->tf_rcx; 178150631Speter mcp->mc_eip = tp->tf_rip; 179150631Speter mcp->mc_cs = tp->tf_cs; 180150631Speter mcp->mc_esp = tp->tf_rsp; 181150631Speter mcp->mc_ss = tp->tf_ss; 182150631Speter mcp->mc_len = sizeof(*mcp); 183230426Skib mcp->mc_flags = tp->tf_flags; 184230426Skib ia32_get_fpcontext(td, mcp, NULL, 0); 185216634Sjkim mcp->mc_fsbase = pcb->pcb_fsbase; 186216634Sjkim mcp->mc_gsbase = pcb->pcb_gsbase; 187230426Skib mcp->mc_xfpustate = 0; 188230426Skib mcp->mc_xfpustate_len = 0; 189218327Skib bzero(mcp->mc_spare2, sizeof(mcp->mc_spare2)); 190150631Speter return (0); 191150631Speter} 192150631Speter 193150631Speter/* 194150631Speter * Set machine context. 195150631Speter * 196150631Speter * However, we don't set any but the user modifiable flags, and we won't 197150631Speter * touch the cs selector. 198150631Speter */ 199150631Speterstatic int 200278001Skibia32_set_mcontext(struct thread *td, struct ia32_mcontext *mcp) 201150631Speter{ 202150631Speter struct trapframe *tp; 203230426Skib char *xfpustate; 204150631Speter long rflags; 205150631Speter int ret; 206150631Speter 207150631Speter tp = td->td_frame; 208150631Speter if (mcp->mc_len != sizeof(*mcp)) 209150631Speter return (EINVAL); 210150631Speter rflags = (mcp->mc_eflags & PSL_USERCHANGE) | 211150631Speter (tp->tf_rflags & ~PSL_USERCHANGE); 212230426Skib if (mcp->mc_flags & _MC_IA32_HASFPXSTATE) { 213230426Skib if (mcp->mc_xfpustate_len > cpu_max_ext_state_size - 214230426Skib sizeof(struct savefpu)) 215230426Skib return (EINVAL); 216230426Skib xfpustate = __builtin_alloca(mcp->mc_xfpustate_len); 217230426Skib ret = copyin(PTRIN(mcp->mc_xfpustate), xfpustate, 218230426Skib mcp->mc_xfpustate_len); 219230426Skib if (ret != 0) 220230426Skib return (ret); 221230426Skib } else 222230426Skib xfpustate = NULL; 223230426Skib ret = ia32_set_fpcontext(td, mcp, xfpustate, mcp->mc_xfpustate_len); 224150631Speter if (ret != 0) 225150631Speter return (ret); 226190620Skib tp->tf_gs = mcp->mc_gs; 227150631Speter tp->tf_fs = mcp->mc_fs; 228150631Speter tp->tf_es = mcp->mc_es; 229150631Speter tp->tf_ds = mcp->mc_ds; 230190620Skib tp->tf_flags = TF_HASSEGS; 231150631Speter tp->tf_rdi = mcp->mc_edi; 232150631Speter tp->tf_rsi = mcp->mc_esi; 233150631Speter tp->tf_rbp = mcp->mc_ebp; 234150631Speter tp->tf_rbx = mcp->mc_ebx; 235150631Speter tp->tf_rdx = mcp->mc_edx; 236150631Speter tp->tf_rcx = mcp->mc_ecx; 237150631Speter tp->tf_rax = mcp->mc_eax; 238150631Speter /* trapno, err */ 239150631Speter tp->tf_rip = mcp->mc_eip; 240150631Speter tp->tf_rflags = rflags; 241150631Speter tp->tf_rsp = mcp->mc_esp; 242150631Speter tp->tf_ss = mcp->mc_ss; 243216634Sjkim set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 244150631Speter return (0); 245150631Speter} 246150631Speter 247150631Speter/* 248150631Speter * The first two fields of a ucontext_t are the signal mask and 249150631Speter * the machine context. The next field is uc_link; we want to 250150631Speter * avoid destroying the link when copying out contexts. 251150631Speter */ 252150631Speter#define UC_COPY_SIZE offsetof(struct ia32_ucontext, uc_link) 253150631Speter 254150631Speterint 255150631Speterfreebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap) 256150631Speter{ 257150631Speter struct ia32_ucontext uc; 258150631Speter int ret; 259150631Speter 260150631Speter if (uap->ucp == NULL) 261150631Speter ret = EINVAL; 262150631Speter else { 263341165Svangyzen bzero(&uc, sizeof(uc)); 264150631Speter ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 265150631Speter PROC_LOCK(td->td_proc); 266150631Speter uc.uc_sigmask = td->td_sigmask; 267150631Speter PROC_UNLOCK(td->td_proc); 268218327Skib bzero(&uc.__spare__, sizeof(uc.__spare__)); 269150631Speter ret = copyout(&uc, uap->ucp, UC_COPY_SIZE); 270150631Speter } 271150631Speter return (ret); 272150631Speter} 273150631Speter 274150631Speterint 275150631Speterfreebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap) 276150631Speter{ 277150631Speter struct ia32_ucontext uc; 278150631Speter int ret; 279150631Speter 280150631Speter if (uap->ucp == NULL) 281150631Speter ret = EINVAL; 282150631Speter else { 283150631Speter ret = copyin(uap->ucp, &uc, UC_COPY_SIZE); 284150631Speter if (ret == 0) { 285150631Speter ret = ia32_set_mcontext(td, &uc.uc_mcontext); 286150631Speter if (ret == 0) { 287198507Skib kern_sigprocmask(td, SIG_SETMASK, 288198507Skib &uc.uc_sigmask, NULL, 0); 289150631Speter } 290150631Speter } 291150631Speter } 292150631Speter return (ret == 0 ? EJUSTRETURN : ret); 293150631Speter} 294150631Speter 295150631Speterint 296150631Speterfreebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap) 297150631Speter{ 298150631Speter struct ia32_ucontext uc; 299150631Speter int ret; 300150631Speter 301150631Speter if (uap->oucp == NULL || uap->ucp == NULL) 302150631Speter ret = EINVAL; 303150631Speter else { 304341165Svangyzen bzero(&uc, sizeof(uc)); 305150631Speter ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 306150631Speter PROC_LOCK(td->td_proc); 307150631Speter uc.uc_sigmask = td->td_sigmask; 308150631Speter PROC_UNLOCK(td->td_proc); 309150631Speter ret = copyout(&uc, uap->oucp, UC_COPY_SIZE); 310150631Speter if (ret == 0) { 311150631Speter ret = copyin(uap->ucp, &uc, UC_COPY_SIZE); 312150631Speter if (ret == 0) { 313150631Speter ret = ia32_set_mcontext(td, &uc.uc_mcontext); 314150631Speter if (ret == 0) { 315198507Skib kern_sigprocmask(td, SIG_SETMASK, 316198507Skib &uc.uc_sigmask, NULL, 0); 317150631Speter } 318150631Speter } 319150631Speter } 320150631Speter } 321150631Speter return (ret == 0 ? EJUSTRETURN : ret); 322150631Speter} 323150631Speter 324150631Speter/* 325114987Speter * Send an interrupt to process. 326114987Speter * 327114987Speter * Stack is set up to allow sigcode stored 328114987Speter * at top to call routine, followed by kcall 329114987Speter * to sigreturn routine below. After sigreturn 330114987Speter * resets the signal mask, the stack, and the 331114987Speter * frame pointer, it returns to the user 332114987Speter * specified pc, psl. 333114987Speter */ 334220238Skib 335220238Skib#ifdef COMPAT_43 336220238Skibstatic void 337220238Skibia32_osendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 338220238Skib{ 339220238Skib struct ia32_sigframe3 sf, *fp; 340220238Skib struct proc *p; 341220238Skib struct thread *td; 342220238Skib struct sigacts *psp; 343220238Skib struct trapframe *regs; 344220238Skib int sig; 345220238Skib int oonstack; 346220238Skib 347220238Skib td = curthread; 348220238Skib p = td->td_proc; 349220238Skib PROC_LOCK_ASSERT(p, MA_OWNED); 350220238Skib sig = ksi->ksi_signo; 351220238Skib psp = p->p_sigacts; 352220238Skib mtx_assert(&psp->ps_mtx, MA_OWNED); 353220238Skib regs = td->td_frame; 354220238Skib oonstack = sigonstack(regs->tf_rsp); 355220238Skib 356220238Skib /* Allocate space for the signal handler context. */ 357220238Skib if ((td->td_pflags & TDP_ALTSTACK) && !oonstack && 358220238Skib SIGISMEMBER(psp->ps_sigonstack, sig)) { 359294930Sjhb fp = (struct ia32_sigframe3 *)((uintptr_t)td->td_sigstk.ss_sp + 360220238Skib td->td_sigstk.ss_size - sizeof(sf)); 361220238Skib td->td_sigstk.ss_flags |= SS_ONSTACK; 362220238Skib } else 363220238Skib fp = (struct ia32_sigframe3 *)regs->tf_rsp - 1; 364220238Skib 365220238Skib /* Build the argument list for the signal handler. */ 366220238Skib sf.sf_signum = sig; 367220238Skib sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc; 368340920Smarkj bzero(&sf.sf_siginfo, sizeof(sf.sf_siginfo)); 369220238Skib if (SIGISMEMBER(psp->ps_siginfo, sig)) { 370220238Skib /* Signal handler installed with SA_SIGINFO. */ 371220238Skib sf.sf_arg2 = (register_t)&fp->sf_siginfo; 372220238Skib sf.sf_siginfo.si_signo = sig; 373220238Skib sf.sf_siginfo.si_code = ksi->ksi_code; 374220238Skib sf.sf_ah = (uintptr_t)catcher; 375340920Smarkj sf.sf_addr = 0; 376220238Skib } else { 377220238Skib /* Old FreeBSD-style arguments. */ 378220238Skib sf.sf_arg2 = ksi->ksi_code; 379220238Skib sf.sf_addr = (register_t)ksi->ksi_addr; 380220238Skib sf.sf_ah = (uintptr_t)catcher; 381220238Skib } 382220238Skib mtx_unlock(&psp->ps_mtx); 383220238Skib PROC_UNLOCK(p); 384220238Skib 385220238Skib /* Save most if not all of trap frame. */ 386220238Skib sf.sf_siginfo.si_sc.sc_eax = regs->tf_rax; 387220238Skib sf.sf_siginfo.si_sc.sc_ebx = regs->tf_rbx; 388220238Skib sf.sf_siginfo.si_sc.sc_ecx = regs->tf_rcx; 389220238Skib sf.sf_siginfo.si_sc.sc_edx = regs->tf_rdx; 390220238Skib sf.sf_siginfo.si_sc.sc_esi = regs->tf_rsi; 391220238Skib sf.sf_siginfo.si_sc.sc_edi = regs->tf_rdi; 392220238Skib sf.sf_siginfo.si_sc.sc_cs = regs->tf_cs; 393220238Skib sf.sf_siginfo.si_sc.sc_ds = regs->tf_ds; 394220238Skib sf.sf_siginfo.si_sc.sc_ss = regs->tf_ss; 395220238Skib sf.sf_siginfo.si_sc.sc_es = regs->tf_es; 396220238Skib sf.sf_siginfo.si_sc.sc_fs = regs->tf_fs; 397220238Skib sf.sf_siginfo.si_sc.sc_gs = regs->tf_gs; 398220238Skib sf.sf_siginfo.si_sc.sc_isp = regs->tf_rsp; 399220238Skib 400220238Skib /* Build the signal context to be used by osigreturn(). */ 401220238Skib sf.sf_siginfo.si_sc.sc_onstack = (oonstack) ? 1 : 0; 402220238Skib SIG2OSIG(*mask, sf.sf_siginfo.si_sc.sc_mask); 403220238Skib sf.sf_siginfo.si_sc.sc_esp = regs->tf_rsp; 404220238Skib sf.sf_siginfo.si_sc.sc_ebp = regs->tf_rbp; 405220238Skib sf.sf_siginfo.si_sc.sc_eip = regs->tf_rip; 406220238Skib sf.sf_siginfo.si_sc.sc_eflags = regs->tf_rflags; 407220238Skib sf.sf_siginfo.si_sc.sc_trapno = regs->tf_trapno; 408220238Skib sf.sf_siginfo.si_sc.sc_err = regs->tf_err; 409220238Skib 410220238Skib /* 411220238Skib * Copy the sigframe out to the user's stack. 412220238Skib */ 413220238Skib if (copyout(&sf, fp, sizeof(*fp)) != 0) { 414220238Skib#ifdef DEBUG 415220238Skib printf("process %ld has trashed its stack\n", (long)p->p_pid); 416220238Skib#endif 417220238Skib PROC_LOCK(p); 418220238Skib sigexit(td, SIGILL); 419220238Skib } 420220238Skib 421220238Skib regs->tf_rsp = (uintptr_t)fp; 422220238Skib regs->tf_rip = p->p_sysent->sv_psstrings - sz_ia32_osigcode; 423220238Skib regs->tf_rflags &= ~(PSL_T | PSL_D); 424220238Skib regs->tf_cs = _ucode32sel; 425220238Skib regs->tf_ds = _udatasel; 426220238Skib regs->tf_es = _udatasel; 427220238Skib regs->tf_fs = _udatasel; 428220238Skib regs->tf_ss = _udatasel; 429220238Skib set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 430220238Skib PROC_LOCK(p); 431220238Skib mtx_lock(&psp->ps_mtx); 432220238Skib} 433220238Skib#endif 434220238Skib 435114987Speter#ifdef COMPAT_FREEBSD4 436114987Speterstatic void 437151316Sdavidxufreebsd4_ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 438114987Speter{ 439114987Speter struct ia32_sigframe4 sf, *sfp; 440163018Sdavidxu struct siginfo32 siginfo; 441114987Speter struct proc *p; 442114987Speter struct thread *td; 443114987Speter struct sigacts *psp; 444114987Speter struct trapframe *regs; 445114987Speter int oonstack; 446151316Sdavidxu int sig; 447114987Speter 448114987Speter td = curthread; 449114987Speter p = td->td_proc; 450163018Sdavidxu siginfo_to_siginfo32(&ksi->ksi_info, &siginfo); 451151316Sdavidxu 452114987Speter PROC_LOCK_ASSERT(p, MA_OWNED); 453151316Sdavidxu sig = siginfo.si_signo; 454114987Speter psp = p->p_sigacts; 455123119Speter mtx_assert(&psp->ps_mtx, MA_OWNED); 456114987Speter regs = td->td_frame; 457114987Speter oonstack = sigonstack(regs->tf_rsp); 458114987Speter 459114987Speter /* Save user context. */ 460114987Speter bzero(&sf, sizeof(sf)); 461114987Speter sf.sf_uc.uc_sigmask = *mask; 462124092Sdavidxu sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp; 463124092Sdavidxu sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size; 464124092Sdavidxu sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) 465114987Speter ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 466114987Speter sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 467114987Speter sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi; 468114987Speter sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi; 469114987Speter sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp; 470114987Speter sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */ 471114987Speter sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx; 472114987Speter sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx; 473114987Speter sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx; 474114987Speter sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax; 475114987Speter sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno; 476114987Speter sf.sf_uc.uc_mcontext.mc_err = regs->tf_err; 477114987Speter sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip; 478114987Speter sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs; 479114987Speter sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags; 480114987Speter sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp; 481114987Speter sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss; 482190620Skib sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds; 483190620Skib sf.sf_uc.uc_mcontext.mc_es = regs->tf_es; 484190620Skib sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs; 485190620Skib sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs; 486218327Skib bzero(sf.sf_uc.uc_mcontext.mc_fpregs, 487218327Skib sizeof(sf.sf_uc.uc_mcontext.mc_fpregs)); 488218327Skib bzero(sf.sf_uc.uc_mcontext.__spare__, 489218327Skib sizeof(sf.sf_uc.uc_mcontext.__spare__)); 490218327Skib bzero(sf.sf_uc.__spare__, sizeof(sf.sf_uc.__spare__)); 491114987Speter 492114987Speter /* Allocate space for the signal handler context. */ 493124092Sdavidxu if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 494114987Speter SIGISMEMBER(psp->ps_sigonstack, sig)) { 495294930Sjhb sfp = (struct ia32_sigframe4 *)((uintptr_t)td->td_sigstk.ss_sp + 496124092Sdavidxu td->td_sigstk.ss_size - sizeof(sf)); 497114987Speter } else 498114987Speter sfp = (struct ia32_sigframe4 *)regs->tf_rsp - 1; 499114987Speter PROC_UNLOCK(p); 500114987Speter 501114987Speter /* Build the argument list for the signal handler. */ 502114987Speter sf.sf_signum = sig; 503114987Speter sf.sf_ucontext = (register_t)&sfp->sf_uc; 504218327Skib bzero(&sf.sf_si, sizeof(sf.sf_si)); 505126089Speter if (SIGISMEMBER(psp->ps_siginfo, sig)) { 506114987Speter /* Signal handler installed with SA_SIGINFO. */ 507114987Speter sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si; 508114987Speter sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 509114987Speter 510114987Speter /* Fill in POSIX parts */ 511151316Sdavidxu sf.sf_si = siginfo; 512114987Speter sf.sf_si.si_signo = sig; 513114987Speter } else { 514114987Speter /* Old FreeBSD-style arguments. */ 515151316Sdavidxu sf.sf_siginfo = siginfo.si_code; 516151316Sdavidxu sf.sf_addr = (u_int32_t)siginfo.si_addr; 517114987Speter sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 518114987Speter } 519123119Speter mtx_unlock(&psp->ps_mtx); 520114987Speter 521114987Speter /* 522114987Speter * Copy the sigframe out to the user's stack. 523114987Speter */ 524114987Speter if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { 525114987Speter#ifdef DEBUG 526114987Speter printf("process %ld has trashed its stack\n", (long)p->p_pid); 527114987Speter#endif 528114987Speter PROC_LOCK(p); 529114987Speter sigexit(td, SIGILL); 530114987Speter } 531114987Speter 532114987Speter regs->tf_rsp = (uintptr_t)sfp; 533217151Skib regs->tf_rip = p->p_sysent->sv_sigcode_base + sz_ia32_sigcode - 534217151Skib sz_freebsd4_ia32_sigcode; 535177145Skib regs->tf_rflags &= ~(PSL_T | PSL_D); 536114987Speter regs->tf_cs = _ucode32sel; 537114987Speter regs->tf_ss = _udatasel; 538190620Skib regs->tf_ds = _udatasel; 539190620Skib regs->tf_es = _udatasel; 540216634Sjkim set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 541114987Speter /* leave user %fs and %gs untouched */ 542114987Speter PROC_LOCK(p); 543123119Speter mtx_lock(&psp->ps_mtx); 544114987Speter} 545114987Speter#endif /* COMPAT_FREEBSD4 */ 546114987Speter 547114987Spetervoid 548151316Sdavidxuia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 549114987Speter{ 550114987Speter struct ia32_sigframe sf, *sfp; 551163018Sdavidxu struct siginfo32 siginfo; 552114987Speter struct proc *p; 553114987Speter struct thread *td; 554114987Speter struct sigacts *psp; 555114987Speter char *sp; 556114987Speter struct trapframe *regs; 557230426Skib char *xfpusave; 558230426Skib size_t xfpusave_len; 559114987Speter int oonstack; 560151316Sdavidxu int sig; 561114987Speter 562163018Sdavidxu siginfo_to_siginfo32(&ksi->ksi_info, &siginfo); 563114987Speter td = curthread; 564114987Speter p = td->td_proc; 565114987Speter PROC_LOCK_ASSERT(p, MA_OWNED); 566151316Sdavidxu sig = siginfo.si_signo; 567114987Speter psp = p->p_sigacts; 568114987Speter#ifdef COMPAT_FREEBSD4 569114987Speter if (SIGISMEMBER(psp->ps_freebsd4, sig)) { 570151316Sdavidxu freebsd4_ia32_sendsig(catcher, ksi, mask); 571114987Speter return; 572114987Speter } 573114987Speter#endif 574220238Skib#ifdef COMPAT_43 575220238Skib if (SIGISMEMBER(psp->ps_osigset, sig)) { 576220238Skib ia32_osendsig(catcher, ksi, mask); 577220238Skib return; 578220238Skib } 579220238Skib#endif 580123119Speter mtx_assert(&psp->ps_mtx, MA_OWNED); 581114987Speter regs = td->td_frame; 582114987Speter oonstack = sigonstack(regs->tf_rsp); 583114987Speter 584230426Skib if (cpu_max_ext_state_size > sizeof(struct savefpu) && use_xsave) { 585230426Skib xfpusave_len = cpu_max_ext_state_size - sizeof(struct savefpu); 586230426Skib xfpusave = __builtin_alloca(xfpusave_len); 587230426Skib } else { 588230426Skib xfpusave_len = 0; 589230426Skib xfpusave = NULL; 590230426Skib } 591230426Skib 592114987Speter /* Save user context. */ 593114987Speter bzero(&sf, sizeof(sf)); 594114987Speter sf.sf_uc.uc_sigmask = *mask; 595124092Sdavidxu sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp; 596124092Sdavidxu sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size; 597124092Sdavidxu sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) 598114987Speter ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 599114987Speter sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 600114987Speter sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi; 601114987Speter sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi; 602114987Speter sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp; 603114987Speter sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */ 604114987Speter sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx; 605114987Speter sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx; 606114987Speter sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx; 607114987Speter sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax; 608114987Speter sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno; 609114987Speter sf.sf_uc.uc_mcontext.mc_err = regs->tf_err; 610114987Speter sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip; 611114987Speter sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs; 612114987Speter sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags; 613114987Speter sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp; 614114987Speter sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss; 615190620Skib sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds; 616190620Skib sf.sf_uc.uc_mcontext.mc_es = regs->tf_es; 617190620Skib sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs; 618190620Skib sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs; 619114987Speter sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */ 620230426Skib ia32_get_fpcontext(td, &sf.sf_uc.uc_mcontext, xfpusave, xfpusave_len); 621114987Speter fpstate_drop(td); 622190620Skib sf.sf_uc.uc_mcontext.mc_fsbase = td->td_pcb->pcb_fsbase; 623190620Skib sf.sf_uc.uc_mcontext.mc_gsbase = td->td_pcb->pcb_gsbase; 624218327Skib bzero(sf.sf_uc.__spare__, sizeof(sf.sf_uc.__spare__)); 625114987Speter 626114987Speter /* Allocate space for the signal handler context. */ 627124092Sdavidxu if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 628230426Skib SIGISMEMBER(psp->ps_sigonstack, sig)) 629294930Sjhb sp = (char *)td->td_sigstk.ss_sp + td->td_sigstk.ss_size; 630230426Skib else 631230426Skib sp = (char *)regs->tf_rsp; 632230426Skib if (xfpusave != NULL) { 633230426Skib sp -= xfpusave_len; 634230426Skib sp = (char *)((unsigned long)sp & ~0x3Ful); 635230426Skib sf.sf_uc.uc_mcontext.mc_xfpustate = (register_t)sp; 636230426Skib } 637230426Skib sp -= sizeof(sf); 638114987Speter /* Align to 16 bytes. */ 639114987Speter sfp = (struct ia32_sigframe *)((uintptr_t)sp & ~0xF); 640114987Speter PROC_UNLOCK(p); 641114987Speter 642114987Speter /* Build the argument list for the signal handler. */ 643114987Speter sf.sf_signum = sig; 644114987Speter sf.sf_ucontext = (register_t)&sfp->sf_uc; 645218327Skib bzero(&sf.sf_si, sizeof(sf.sf_si)); 646126089Speter if (SIGISMEMBER(psp->ps_siginfo, sig)) { 647114987Speter /* Signal handler installed with SA_SIGINFO. */ 648114987Speter sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si; 649114987Speter sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 650114987Speter 651114987Speter /* Fill in POSIX parts */ 652151316Sdavidxu sf.sf_si = siginfo; 653114987Speter sf.sf_si.si_signo = sig; 654114987Speter } else { 655114987Speter /* Old FreeBSD-style arguments. */ 656151316Sdavidxu sf.sf_siginfo = siginfo.si_code; 657151316Sdavidxu sf.sf_addr = (u_int32_t)siginfo.si_addr; 658114987Speter sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 659114987Speter } 660123119Speter mtx_unlock(&psp->ps_mtx); 661114987Speter 662114987Speter /* 663114987Speter * Copy the sigframe out to the user's stack. 664114987Speter */ 665230426Skib if (copyout(&sf, sfp, sizeof(*sfp)) != 0 || 666230426Skib (xfpusave != NULL && copyout(xfpusave, 667230426Skib PTRIN(sf.sf_uc.uc_mcontext.mc_xfpustate), xfpusave_len) 668230426Skib != 0)) { 669114987Speter#ifdef DEBUG 670114987Speter printf("process %ld has trashed its stack\n", (long)p->p_pid); 671114987Speter#endif 672114987Speter PROC_LOCK(p); 673114987Speter sigexit(td, SIGILL); 674114987Speter } 675114987Speter 676114987Speter regs->tf_rsp = (uintptr_t)sfp; 677217151Skib regs->tf_rip = p->p_sysent->sv_sigcode_base; 678177145Skib regs->tf_rflags &= ~(PSL_T | PSL_D); 679114987Speter regs->tf_cs = _ucode32sel; 680114987Speter regs->tf_ss = _udatasel; 681190620Skib regs->tf_ds = _udatasel; 682190620Skib regs->tf_es = _udatasel; 683216634Sjkim set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 684190620Skib /* XXXKIB leave user %fs and %gs untouched */ 685114987Speter PROC_LOCK(p); 686123119Speter mtx_lock(&psp->ps_mtx); 687114987Speter} 688114987Speter 689114987Speter/* 690114987Speter * System call to cleanup state after a signal 691114987Speter * has been taken. Reset signal mask and 692114987Speter * stack state from context left by sendsig (above). 693114987Speter * Return to previous pc and psl as specified by 694114987Speter * context left by sendsig. Check carefully to 695114987Speter * make sure that the user has not modified the 696114987Speter * state to gain improper privileges. 697114987Speter */ 698220238Skib 699220238Skib#ifdef COMPAT_43 700220238Skibint 701220238Skibofreebsd32_sigreturn(struct thread *td, struct ofreebsd32_sigreturn_args *uap) 702220238Skib{ 703220238Skib struct ia32_sigcontext3 sc, *scp; 704220238Skib struct trapframe *regs; 705220238Skib int eflags, error; 706220238Skib ksiginfo_t ksi; 707220238Skib 708220238Skib regs = td->td_frame; 709220238Skib error = copyin(uap->sigcntxp, &sc, sizeof(sc)); 710220238Skib if (error != 0) 711220238Skib return (error); 712220238Skib scp = ≻ 713220238Skib eflags = scp->sc_eflags; 714258135Semaste if (!EFL_SECURE(eflags, regs->tf_rflags)) { 715220238Skib return (EINVAL); 716220238Skib } 717220238Skib if (!CS_SECURE(scp->sc_cs)) { 718220238Skib ksiginfo_init_trap(&ksi); 719220238Skib ksi.ksi_signo = SIGBUS; 720220238Skib ksi.ksi_code = BUS_OBJERR; 721220238Skib ksi.ksi_trapno = T_PROTFLT; 722220238Skib ksi.ksi_addr = (void *)regs->tf_rip; 723220238Skib trapsignal(td, &ksi); 724220238Skib return (EINVAL); 725220238Skib } 726220238Skib regs->tf_ds = scp->sc_ds; 727220238Skib regs->tf_es = scp->sc_es; 728220238Skib regs->tf_fs = scp->sc_fs; 729220238Skib regs->tf_gs = scp->sc_gs; 730220238Skib 731220238Skib regs->tf_rax = scp->sc_eax; 732220238Skib regs->tf_rbx = scp->sc_ebx; 733220238Skib regs->tf_rcx = scp->sc_ecx; 734220238Skib regs->tf_rdx = scp->sc_edx; 735220238Skib regs->tf_rsi = scp->sc_esi; 736220238Skib regs->tf_rdi = scp->sc_edi; 737220238Skib regs->tf_cs = scp->sc_cs; 738220238Skib regs->tf_ss = scp->sc_ss; 739220238Skib regs->tf_rbp = scp->sc_ebp; 740220238Skib regs->tf_rsp = scp->sc_esp; 741220238Skib regs->tf_rip = scp->sc_eip; 742220238Skib regs->tf_rflags = eflags; 743220238Skib 744220238Skib if (scp->sc_onstack & 1) 745220238Skib td->td_sigstk.ss_flags |= SS_ONSTACK; 746220238Skib else 747220238Skib td->td_sigstk.ss_flags &= ~SS_ONSTACK; 748220238Skib 749220238Skib kern_sigprocmask(td, SIG_SETMASK, (sigset_t *)&scp->sc_mask, NULL, 750220238Skib SIGPROCMASK_OLD); 751220238Skib set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 752220238Skib return (EJUSTRETURN); 753220238Skib} 754220238Skib#endif 755220238Skib 756114987Speter#ifdef COMPAT_FREEBSD4 757114987Speter/* 758114987Speter * MPSAFE 759114987Speter */ 760114987Speterint 761119336Speterfreebsd4_freebsd32_sigreturn(td, uap) 762114987Speter struct thread *td; 763119336Speter struct freebsd4_freebsd32_sigreturn_args /* { 764119336Speter const struct freebsd4_freebsd32_ucontext *sigcntxp; 765114987Speter } */ *uap; 766114987Speter{ 767114987Speter struct ia32_ucontext4 uc; 768114987Speter struct trapframe *regs; 769198507Skib struct ia32_ucontext4 *ucp; 770114987Speter int cs, eflags, error; 771151316Sdavidxu ksiginfo_t ksi; 772114987Speter 773114987Speter error = copyin(uap->sigcntxp, &uc, sizeof(uc)); 774114987Speter if (error != 0) 775114987Speter return (error); 776114987Speter ucp = &uc; 777114987Speter regs = td->td_frame; 778114987Speter eflags = ucp->uc_mcontext.mc_eflags; 779114987Speter /* 780114987Speter * Don't allow users to change privileged or reserved flags. 781114987Speter */ 782258135Semaste if (!EFL_SECURE(eflags, regs->tf_rflags)) { 783206553Skib uprintf("pid %d (%s): freebsd4_freebsd32_sigreturn eflags = 0x%x\n", 784206553Skib td->td_proc->p_pid, td->td_name, eflags); 785114987Speter return (EINVAL); 786114987Speter } 787114987Speter 788114987Speter /* 789114987Speter * Don't allow users to load a valid privileged %cs. Let the 790114987Speter * hardware check for invalid selectors, excess privilege in 791114987Speter * other selectors, invalid %eip's and invalid %esp's. 792114987Speter */ 793114987Speter cs = ucp->uc_mcontext.mc_cs; 794114987Speter if (!CS_SECURE(cs)) { 795206553Skib uprintf("pid %d (%s): freebsd4_sigreturn cs = 0x%x\n", 796206553Skib td->td_proc->p_pid, td->td_name, cs); 797151316Sdavidxu ksiginfo_init_trap(&ksi); 798151316Sdavidxu ksi.ksi_signo = SIGBUS; 799151316Sdavidxu ksi.ksi_code = BUS_OBJERR; 800151316Sdavidxu ksi.ksi_trapno = T_PROTFLT; 801151316Sdavidxu ksi.ksi_addr = (void *)regs->tf_rip; 802151316Sdavidxu trapsignal(td, &ksi); 803114987Speter return (EINVAL); 804114987Speter } 805114987Speter 806114987Speter regs->tf_rdi = ucp->uc_mcontext.mc_edi; 807114987Speter regs->tf_rsi = ucp->uc_mcontext.mc_esi; 808114987Speter regs->tf_rbp = ucp->uc_mcontext.mc_ebp; 809114987Speter regs->tf_rbx = ucp->uc_mcontext.mc_ebx; 810114987Speter regs->tf_rdx = ucp->uc_mcontext.mc_edx; 811114987Speter regs->tf_rcx = ucp->uc_mcontext.mc_ecx; 812114987Speter regs->tf_rax = ucp->uc_mcontext.mc_eax; 813114987Speter regs->tf_trapno = ucp->uc_mcontext.mc_trapno; 814114987Speter regs->tf_err = ucp->uc_mcontext.mc_err; 815114987Speter regs->tf_rip = ucp->uc_mcontext.mc_eip; 816114987Speter regs->tf_cs = cs; 817114987Speter regs->tf_rflags = ucp->uc_mcontext.mc_eflags; 818114987Speter regs->tf_rsp = ucp->uc_mcontext.mc_esp; 819114987Speter regs->tf_ss = ucp->uc_mcontext.mc_ss; 820190620Skib regs->tf_ds = ucp->uc_mcontext.mc_ds; 821190620Skib regs->tf_es = ucp->uc_mcontext.mc_es; 822190620Skib regs->tf_fs = ucp->uc_mcontext.mc_fs; 823190620Skib regs->tf_gs = ucp->uc_mcontext.mc_gs; 824114987Speter 825198507Skib kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0); 826216634Sjkim set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 827114987Speter return (EJUSTRETURN); 828114987Speter} 829114987Speter#endif /* COMPAT_FREEBSD4 */ 830114987Speter 831114987Speter/* 832114987Speter * MPSAFE 833114987Speter */ 834114987Speterint 835119336Speterfreebsd32_sigreturn(td, uap) 836114987Speter struct thread *td; 837119336Speter struct freebsd32_sigreturn_args /* { 838119336Speter const struct freebsd32_ucontext *sigcntxp; 839114987Speter } */ *uap; 840114987Speter{ 841114987Speter struct ia32_ucontext uc; 842114987Speter struct trapframe *regs; 843198507Skib struct ia32_ucontext *ucp; 844230426Skib char *xfpustate; 845230426Skib size_t xfpustate_len; 846114987Speter int cs, eflags, error, ret; 847151316Sdavidxu ksiginfo_t ksi; 848114987Speter 849114987Speter error = copyin(uap->sigcntxp, &uc, sizeof(uc)); 850114987Speter if (error != 0) 851114987Speter return (error); 852114987Speter ucp = &uc; 853114987Speter regs = td->td_frame; 854114987Speter eflags = ucp->uc_mcontext.mc_eflags; 855114987Speter /* 856114987Speter * Don't allow users to change privileged or reserved flags. 857114987Speter */ 858258135Semaste if (!EFL_SECURE(eflags, regs->tf_rflags)) { 859206553Skib uprintf("pid %d (%s): freebsd32_sigreturn eflags = 0x%x\n", 860206553Skib td->td_proc->p_pid, td->td_name, eflags); 861114987Speter return (EINVAL); 862114987Speter } 863114987Speter 864114987Speter /* 865114987Speter * Don't allow users to load a valid privileged %cs. Let the 866114987Speter * hardware check for invalid selectors, excess privilege in 867114987Speter * other selectors, invalid %eip's and invalid %esp's. 868114987Speter */ 869114987Speter cs = ucp->uc_mcontext.mc_cs; 870114987Speter if (!CS_SECURE(cs)) { 871206553Skib uprintf("pid %d (%s): sigreturn cs = 0x%x\n", 872206553Skib td->td_proc->p_pid, td->td_name, cs); 873151316Sdavidxu ksiginfo_init_trap(&ksi); 874151316Sdavidxu ksi.ksi_signo = SIGBUS; 875151316Sdavidxu ksi.ksi_code = BUS_OBJERR; 876151316Sdavidxu ksi.ksi_trapno = T_PROTFLT; 877151316Sdavidxu ksi.ksi_addr = (void *)regs->tf_rip; 878151316Sdavidxu trapsignal(td, &ksi); 879114987Speter return (EINVAL); 880114987Speter } 881114987Speter 882230426Skib if ((ucp->uc_mcontext.mc_flags & _MC_HASFPXSTATE) != 0) { 883230426Skib xfpustate_len = uc.uc_mcontext.mc_xfpustate_len; 884230426Skib if (xfpustate_len > cpu_max_ext_state_size - 885230426Skib sizeof(struct savefpu)) { 886230426Skib uprintf("pid %d (%s): sigreturn xfpusave_len = 0x%zx\n", 887230426Skib td->td_proc->p_pid, td->td_name, xfpustate_len); 888230426Skib return (EINVAL); 889230426Skib } 890230426Skib xfpustate = __builtin_alloca(xfpustate_len); 891230426Skib error = copyin(PTRIN(ucp->uc_mcontext.mc_xfpustate), 892230426Skib xfpustate, xfpustate_len); 893230426Skib if (error != 0) { 894230426Skib uprintf( 895230426Skib "pid %d (%s): sigreturn copying xfpustate failed\n", 896230426Skib td->td_proc->p_pid, td->td_name); 897230426Skib return (error); 898230426Skib } 899230426Skib } else { 900230426Skib xfpustate = NULL; 901230426Skib xfpustate_len = 0; 902230426Skib } 903230426Skib ret = ia32_set_fpcontext(td, &ucp->uc_mcontext, xfpustate, 904230426Skib xfpustate_len); 905230426Skib if (ret != 0) { 906230426Skib uprintf("pid %d (%s): sigreturn set_fpcontext err %d\n", 907230426Skib td->td_proc->p_pid, td->td_name, ret); 908114987Speter return (ret); 909230426Skib } 910114987Speter 911114987Speter regs->tf_rdi = ucp->uc_mcontext.mc_edi; 912114987Speter regs->tf_rsi = ucp->uc_mcontext.mc_esi; 913114987Speter regs->tf_rbp = ucp->uc_mcontext.mc_ebp; 914114987Speter regs->tf_rbx = ucp->uc_mcontext.mc_ebx; 915114987Speter regs->tf_rdx = ucp->uc_mcontext.mc_edx; 916114987Speter regs->tf_rcx = ucp->uc_mcontext.mc_ecx; 917114987Speter regs->tf_rax = ucp->uc_mcontext.mc_eax; 918114987Speter regs->tf_trapno = ucp->uc_mcontext.mc_trapno; 919114987Speter regs->tf_err = ucp->uc_mcontext.mc_err; 920114987Speter regs->tf_rip = ucp->uc_mcontext.mc_eip; 921114987Speter regs->tf_cs = cs; 922114987Speter regs->tf_rflags = ucp->uc_mcontext.mc_eflags; 923114987Speter regs->tf_rsp = ucp->uc_mcontext.mc_esp; 924114987Speter regs->tf_ss = ucp->uc_mcontext.mc_ss; 925190620Skib regs->tf_ds = ucp->uc_mcontext.mc_ds; 926190620Skib regs->tf_es = ucp->uc_mcontext.mc_es; 927190620Skib regs->tf_fs = ucp->uc_mcontext.mc_fs; 928190620Skib regs->tf_gs = ucp->uc_mcontext.mc_gs; 929190620Skib regs->tf_flags = TF_HASSEGS; 930114987Speter 931198507Skib kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0); 932216634Sjkim set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 933114987Speter return (EJUSTRETURN); 934114987Speter} 935122303Speter 936122303Speter/* 937122303Speter * Clear registers on exec 938122303Speter */ 939122303Spetervoid 940205642Snwhitehornia32_setregs(struct thread *td, struct image_params *imgp, u_long stack) 941122303Speter{ 942338691Sjhb struct trapframe *regs; 943338691Sjhb struct pcb *pcb; 944338691Sjhb register_t saved_rflags; 945122303Speter 946190620Skib mtx_lock(&dt_lock); 947338691Sjhb regs = td->td_frame; 948338691Sjhb pcb = td->td_pcb; 949338691Sjhb 950190620Skib if (td->td_proc->p_md.md_ldt != NULL) 951190620Skib user_ldt_free(td); 952190620Skib else 953190620Skib mtx_unlock(&dt_lock); 954220238Skib#ifdef COMPAT_43 955220238Skib setup_lcall_gate(); 956220238Skib#endif 957190620Skib 958122303Speter pcb->pcb_fsbase = 0; 959122303Speter pcb->pcb_gsbase = 0; 960189423Sjhb pcb->pcb_initial_fpucw = __INITIAL_FPUCW_I386__; 961122303Speter 962338691Sjhb saved_rflags = regs->tf_rflags & PSL_T; 963122303Speter bzero((char *)regs, sizeof(struct trapframe)); 964205642Snwhitehorn regs->tf_rip = imgp->entry_addr; 965122303Speter regs->tf_rsp = stack; 966338691Sjhb regs->tf_rflags = PSL_USER | saved_rflags; 967122303Speter regs->tf_ss = _udatasel; 968122303Speter regs->tf_cs = _ucode32sel; 969205642Snwhitehorn regs->tf_rbx = imgp->ps_strings; 970190620Skib regs->tf_ds = _udatasel; 971190620Skib regs->tf_es = _udatasel; 972190620Skib regs->tf_fs = _ufssel; 973190620Skib regs->tf_gs = _ugssel; 974190620Skib regs->tf_flags = TF_HASSEGS; 975190620Skib 976122303Speter fpstate_drop(td); 977122303Speter 978122303Speter /* Return via doreti so that we can change to a different %cs */ 979216634Sjkim set_pcb_flags(pcb, PCB_32BIT | PCB_FULL_IRET); 980122303Speter td->td_retval[1] = 0; 981122303Speter} 982