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$"); 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 121230426Skibia32_set_fpcontext(struct thread *td, const 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 200150631Speteria32_set_mcontext(struct thread *td, const 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 { 263150631Speter ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 264150631Speter PROC_LOCK(td->td_proc); 265150631Speter uc.uc_sigmask = td->td_sigmask; 266150631Speter PROC_UNLOCK(td->td_proc); 267218327Skib bzero(&uc.__spare__, sizeof(uc.__spare__)); 268150631Speter ret = copyout(&uc, uap->ucp, UC_COPY_SIZE); 269150631Speter } 270150631Speter return (ret); 271150631Speter} 272150631Speter 273150631Speterint 274150631Speterfreebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap) 275150631Speter{ 276150631Speter struct ia32_ucontext uc; 277150631Speter int ret; 278150631Speter 279150631Speter if (uap->ucp == NULL) 280150631Speter ret = EINVAL; 281150631Speter else { 282150631Speter ret = copyin(uap->ucp, &uc, UC_COPY_SIZE); 283150631Speter if (ret == 0) { 284150631Speter ret = ia32_set_mcontext(td, &uc.uc_mcontext); 285150631Speter if (ret == 0) { 286198507Skib kern_sigprocmask(td, SIG_SETMASK, 287198507Skib &uc.uc_sigmask, NULL, 0); 288150631Speter } 289150631Speter } 290150631Speter } 291150631Speter return (ret == 0 ? EJUSTRETURN : ret); 292150631Speter} 293150631Speter 294150631Speterint 295150631Speterfreebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap) 296150631Speter{ 297150631Speter struct ia32_ucontext uc; 298150631Speter int ret; 299150631Speter 300150631Speter if (uap->oucp == NULL || uap->ucp == NULL) 301150631Speter ret = EINVAL; 302150631Speter else { 303150631Speter ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 304150631Speter PROC_LOCK(td->td_proc); 305150631Speter uc.uc_sigmask = td->td_sigmask; 306150631Speter PROC_UNLOCK(td->td_proc); 307150631Speter ret = copyout(&uc, uap->oucp, UC_COPY_SIZE); 308150631Speter if (ret == 0) { 309150631Speter ret = copyin(uap->ucp, &uc, UC_COPY_SIZE); 310150631Speter if (ret == 0) { 311150631Speter ret = ia32_set_mcontext(td, &uc.uc_mcontext); 312150631Speter if (ret == 0) { 313198507Skib kern_sigprocmask(td, SIG_SETMASK, 314198507Skib &uc.uc_sigmask, NULL, 0); 315150631Speter } 316150631Speter } 317150631Speter } 318150631Speter } 319150631Speter return (ret == 0 ? EJUSTRETURN : ret); 320150631Speter} 321150631Speter 322150631Speter/* 323114987Speter * Send an interrupt to process. 324114987Speter * 325114987Speter * Stack is set up to allow sigcode stored 326114987Speter * at top to call routine, followed by kcall 327114987Speter * to sigreturn routine below. After sigreturn 328114987Speter * resets the signal mask, the stack, and the 329114987Speter * frame pointer, it returns to the user 330114987Speter * specified pc, psl. 331114987Speter */ 332220238Skib 333220238Skib#ifdef COMPAT_43 334220238Skibstatic void 335220238Skibia32_osendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 336220238Skib{ 337220238Skib struct ia32_sigframe3 sf, *fp; 338220238Skib struct proc *p; 339220238Skib struct thread *td; 340220238Skib struct sigacts *psp; 341220238Skib struct trapframe *regs; 342220238Skib int sig; 343220238Skib int oonstack; 344220238Skib 345220238Skib td = curthread; 346220238Skib p = td->td_proc; 347220238Skib PROC_LOCK_ASSERT(p, MA_OWNED); 348220238Skib sig = ksi->ksi_signo; 349220238Skib psp = p->p_sigacts; 350220238Skib mtx_assert(&psp->ps_mtx, MA_OWNED); 351220238Skib regs = td->td_frame; 352220238Skib oonstack = sigonstack(regs->tf_rsp); 353220238Skib 354220238Skib /* Allocate space for the signal handler context. */ 355220238Skib if ((td->td_pflags & TDP_ALTSTACK) && !oonstack && 356220238Skib SIGISMEMBER(psp->ps_sigonstack, sig)) { 357220238Skib fp = (struct ia32_sigframe3 *)(td->td_sigstk.ss_sp + 358220238Skib td->td_sigstk.ss_size - sizeof(sf)); 359220238Skib td->td_sigstk.ss_flags |= SS_ONSTACK; 360220238Skib } else 361220238Skib fp = (struct ia32_sigframe3 *)regs->tf_rsp - 1; 362220238Skib 363220238Skib /* Translate the signal if appropriate. */ 364220238Skib if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 365220238Skib sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 366220238Skib 367220238Skib /* Build the argument list for the signal handler. */ 368220238Skib sf.sf_signum = sig; 369220238Skib sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc; 370220238Skib if (SIGISMEMBER(psp->ps_siginfo, sig)) { 371220238Skib /* Signal handler installed with SA_SIGINFO. */ 372220238Skib sf.sf_arg2 = (register_t)&fp->sf_siginfo; 373220238Skib sf.sf_siginfo.si_signo = sig; 374220238Skib sf.sf_siginfo.si_code = ksi->ksi_code; 375220238Skib sf.sf_ah = (uintptr_t)catcher; 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)) { 495124092Sdavidxu sfp = (struct ia32_sigframe4 *)(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 /* Translate the signal if appropriate. */ 502114987Speter if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 503114987Speter sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 504114987Speter 505114987Speter /* Build the argument list for the signal handler. */ 506114987Speter sf.sf_signum = sig; 507114987Speter sf.sf_ucontext = (register_t)&sfp->sf_uc; 508218327Skib bzero(&sf.sf_si, sizeof(sf.sf_si)); 509126089Speter if (SIGISMEMBER(psp->ps_siginfo, sig)) { 510114987Speter /* Signal handler installed with SA_SIGINFO. */ 511114987Speter sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si; 512114987Speter sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 513114987Speter 514114987Speter /* Fill in POSIX parts */ 515151316Sdavidxu sf.sf_si = siginfo; 516114987Speter sf.sf_si.si_signo = sig; 517114987Speter } else { 518114987Speter /* Old FreeBSD-style arguments. */ 519151316Sdavidxu sf.sf_siginfo = siginfo.si_code; 520151316Sdavidxu sf.sf_addr = (u_int32_t)siginfo.si_addr; 521114987Speter sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 522114987Speter } 523123119Speter mtx_unlock(&psp->ps_mtx); 524114987Speter 525114987Speter /* 526114987Speter * Copy the sigframe out to the user's stack. 527114987Speter */ 528114987Speter if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { 529114987Speter#ifdef DEBUG 530114987Speter printf("process %ld has trashed its stack\n", (long)p->p_pid); 531114987Speter#endif 532114987Speter PROC_LOCK(p); 533114987Speter sigexit(td, SIGILL); 534114987Speter } 535114987Speter 536114987Speter regs->tf_rsp = (uintptr_t)sfp; 537217151Skib regs->tf_rip = p->p_sysent->sv_sigcode_base + sz_ia32_sigcode - 538217151Skib sz_freebsd4_ia32_sigcode; 539177145Skib regs->tf_rflags &= ~(PSL_T | PSL_D); 540114987Speter regs->tf_cs = _ucode32sel; 541114987Speter regs->tf_ss = _udatasel; 542190620Skib regs->tf_ds = _udatasel; 543190620Skib regs->tf_es = _udatasel; 544216634Sjkim set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 545114987Speter /* leave user %fs and %gs untouched */ 546114987Speter PROC_LOCK(p); 547123119Speter mtx_lock(&psp->ps_mtx); 548114987Speter} 549114987Speter#endif /* COMPAT_FREEBSD4 */ 550114987Speter 551114987Spetervoid 552151316Sdavidxuia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 553114987Speter{ 554114987Speter struct ia32_sigframe sf, *sfp; 555163018Sdavidxu struct siginfo32 siginfo; 556114987Speter struct proc *p; 557114987Speter struct thread *td; 558114987Speter struct sigacts *psp; 559114987Speter char *sp; 560114987Speter struct trapframe *regs; 561230426Skib char *xfpusave; 562230426Skib size_t xfpusave_len; 563114987Speter int oonstack; 564151316Sdavidxu int sig; 565114987Speter 566163018Sdavidxu siginfo_to_siginfo32(&ksi->ksi_info, &siginfo); 567114987Speter td = curthread; 568114987Speter p = td->td_proc; 569114987Speter PROC_LOCK_ASSERT(p, MA_OWNED); 570151316Sdavidxu sig = siginfo.si_signo; 571114987Speter psp = p->p_sigacts; 572114987Speter#ifdef COMPAT_FREEBSD4 573114987Speter if (SIGISMEMBER(psp->ps_freebsd4, sig)) { 574151316Sdavidxu freebsd4_ia32_sendsig(catcher, ksi, mask); 575114987Speter return; 576114987Speter } 577114987Speter#endif 578220238Skib#ifdef COMPAT_43 579220238Skib if (SIGISMEMBER(psp->ps_osigset, sig)) { 580220238Skib ia32_osendsig(catcher, ksi, mask); 581220238Skib return; 582220238Skib } 583220238Skib#endif 584123119Speter mtx_assert(&psp->ps_mtx, MA_OWNED); 585114987Speter regs = td->td_frame; 586114987Speter oonstack = sigonstack(regs->tf_rsp); 587114987Speter 588230426Skib if (cpu_max_ext_state_size > sizeof(struct savefpu) && use_xsave) { 589230426Skib xfpusave_len = cpu_max_ext_state_size - sizeof(struct savefpu); 590230426Skib xfpusave = __builtin_alloca(xfpusave_len); 591230426Skib } else { 592230426Skib xfpusave_len = 0; 593230426Skib xfpusave = NULL; 594230426Skib } 595230426Skib 596114987Speter /* Save user context. */ 597114987Speter bzero(&sf, sizeof(sf)); 598114987Speter sf.sf_uc.uc_sigmask = *mask; 599124092Sdavidxu sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp; 600124092Sdavidxu sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size; 601124092Sdavidxu sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) 602114987Speter ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 603114987Speter sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 604114987Speter sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi; 605114987Speter sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi; 606114987Speter sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp; 607114987Speter sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */ 608114987Speter sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx; 609114987Speter sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx; 610114987Speter sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx; 611114987Speter sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax; 612114987Speter sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno; 613114987Speter sf.sf_uc.uc_mcontext.mc_err = regs->tf_err; 614114987Speter sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip; 615114987Speter sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs; 616114987Speter sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags; 617114987Speter sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp; 618114987Speter sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss; 619190620Skib sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds; 620190620Skib sf.sf_uc.uc_mcontext.mc_es = regs->tf_es; 621190620Skib sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs; 622190620Skib sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs; 623114987Speter sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */ 624230426Skib ia32_get_fpcontext(td, &sf.sf_uc.uc_mcontext, xfpusave, xfpusave_len); 625114987Speter fpstate_drop(td); 626190620Skib sf.sf_uc.uc_mcontext.mc_fsbase = td->td_pcb->pcb_fsbase; 627190620Skib sf.sf_uc.uc_mcontext.mc_gsbase = td->td_pcb->pcb_gsbase; 628218327Skib bzero(sf.sf_uc.__spare__, sizeof(sf.sf_uc.__spare__)); 629114987Speter 630114987Speter /* Allocate space for the signal handler context. */ 631124092Sdavidxu if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 632230426Skib SIGISMEMBER(psp->ps_sigonstack, sig)) 633230426Skib sp = td->td_sigstk.ss_sp + td->td_sigstk.ss_size; 634230426Skib else 635230426Skib sp = (char *)regs->tf_rsp; 636230426Skib if (xfpusave != NULL) { 637230426Skib sp -= xfpusave_len; 638230426Skib sp = (char *)((unsigned long)sp & ~0x3Ful); 639230426Skib sf.sf_uc.uc_mcontext.mc_xfpustate = (register_t)sp; 640230426Skib } 641230426Skib sp -= sizeof(sf); 642114987Speter /* Align to 16 bytes. */ 643114987Speter sfp = (struct ia32_sigframe *)((uintptr_t)sp & ~0xF); 644114987Speter PROC_UNLOCK(p); 645114987Speter 646114987Speter /* Translate the signal if appropriate. */ 647114987Speter if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 648114987Speter sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 649114987Speter 650114987Speter /* Build the argument list for the signal handler. */ 651114987Speter sf.sf_signum = sig; 652114987Speter sf.sf_ucontext = (register_t)&sfp->sf_uc; 653218327Skib bzero(&sf.sf_si, sizeof(sf.sf_si)); 654126089Speter if (SIGISMEMBER(psp->ps_siginfo, sig)) { 655114987Speter /* Signal handler installed with SA_SIGINFO. */ 656114987Speter sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si; 657114987Speter sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 658114987Speter 659114987Speter /* Fill in POSIX parts */ 660151316Sdavidxu sf.sf_si = siginfo; 661114987Speter sf.sf_si.si_signo = sig; 662114987Speter } else { 663114987Speter /* Old FreeBSD-style arguments. */ 664151316Sdavidxu sf.sf_siginfo = siginfo.si_code; 665151316Sdavidxu sf.sf_addr = (u_int32_t)siginfo.si_addr; 666114987Speter sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 667114987Speter } 668123119Speter mtx_unlock(&psp->ps_mtx); 669114987Speter 670114987Speter /* 671114987Speter * Copy the sigframe out to the user's stack. 672114987Speter */ 673230426Skib if (copyout(&sf, sfp, sizeof(*sfp)) != 0 || 674230426Skib (xfpusave != NULL && copyout(xfpusave, 675230426Skib PTRIN(sf.sf_uc.uc_mcontext.mc_xfpustate), xfpusave_len) 676230426Skib != 0)) { 677114987Speter#ifdef DEBUG 678114987Speter printf("process %ld has trashed its stack\n", (long)p->p_pid); 679114987Speter#endif 680114987Speter PROC_LOCK(p); 681114987Speter sigexit(td, SIGILL); 682114987Speter } 683114987Speter 684114987Speter regs->tf_rsp = (uintptr_t)sfp; 685217151Skib regs->tf_rip = p->p_sysent->sv_sigcode_base; 686177145Skib regs->tf_rflags &= ~(PSL_T | PSL_D); 687114987Speter regs->tf_cs = _ucode32sel; 688114987Speter regs->tf_ss = _udatasel; 689190620Skib regs->tf_ds = _udatasel; 690190620Skib regs->tf_es = _udatasel; 691216634Sjkim set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 692190620Skib /* XXXKIB leave user %fs and %gs untouched */ 693114987Speter PROC_LOCK(p); 694123119Speter mtx_lock(&psp->ps_mtx); 695114987Speter} 696114987Speter 697114987Speter/* 698114987Speter * System call to cleanup state after a signal 699114987Speter * has been taken. Reset signal mask and 700114987Speter * stack state from context left by sendsig (above). 701114987Speter * Return to previous pc and psl as specified by 702114987Speter * context left by sendsig. Check carefully to 703114987Speter * make sure that the user has not modified the 704114987Speter * state to gain improper privileges. 705114987Speter */ 706220238Skib 707220238Skib#ifdef COMPAT_43 708220238Skibint 709220238Skibofreebsd32_sigreturn(struct thread *td, struct ofreebsd32_sigreturn_args *uap) 710220238Skib{ 711220238Skib struct ia32_sigcontext3 sc, *scp; 712220238Skib struct trapframe *regs; 713220238Skib int eflags, error; 714220238Skib ksiginfo_t ksi; 715220238Skib 716220238Skib regs = td->td_frame; 717220238Skib error = copyin(uap->sigcntxp, &sc, sizeof(sc)); 718220238Skib if (error != 0) 719220238Skib return (error); 720220238Skib scp = ≻ 721220238Skib eflags = scp->sc_eflags; 722258559Semaste if (!EFL_SECURE(eflags, regs->tf_rflags)) { 723220238Skib return (EINVAL); 724220238Skib } 725220238Skib if (!CS_SECURE(scp->sc_cs)) { 726220238Skib ksiginfo_init_trap(&ksi); 727220238Skib ksi.ksi_signo = SIGBUS; 728220238Skib ksi.ksi_code = BUS_OBJERR; 729220238Skib ksi.ksi_trapno = T_PROTFLT; 730220238Skib ksi.ksi_addr = (void *)regs->tf_rip; 731220238Skib trapsignal(td, &ksi); 732220238Skib return (EINVAL); 733220238Skib } 734220238Skib regs->tf_ds = scp->sc_ds; 735220238Skib regs->tf_es = scp->sc_es; 736220238Skib regs->tf_fs = scp->sc_fs; 737220238Skib regs->tf_gs = scp->sc_gs; 738220238Skib 739220238Skib regs->tf_rax = scp->sc_eax; 740220238Skib regs->tf_rbx = scp->sc_ebx; 741220238Skib regs->tf_rcx = scp->sc_ecx; 742220238Skib regs->tf_rdx = scp->sc_edx; 743220238Skib regs->tf_rsi = scp->sc_esi; 744220238Skib regs->tf_rdi = scp->sc_edi; 745220238Skib regs->tf_cs = scp->sc_cs; 746220238Skib regs->tf_ss = scp->sc_ss; 747220238Skib regs->tf_rbp = scp->sc_ebp; 748220238Skib regs->tf_rsp = scp->sc_esp; 749220238Skib regs->tf_rip = scp->sc_eip; 750220238Skib regs->tf_rflags = eflags; 751220238Skib 752220238Skib if (scp->sc_onstack & 1) 753220238Skib td->td_sigstk.ss_flags |= SS_ONSTACK; 754220238Skib else 755220238Skib td->td_sigstk.ss_flags &= ~SS_ONSTACK; 756220238Skib 757220238Skib kern_sigprocmask(td, SIG_SETMASK, (sigset_t *)&scp->sc_mask, NULL, 758220238Skib SIGPROCMASK_OLD); 759220238Skib set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 760220238Skib return (EJUSTRETURN); 761220238Skib} 762220238Skib#endif 763220238Skib 764114987Speter#ifdef COMPAT_FREEBSD4 765114987Speter/* 766114987Speter * MPSAFE 767114987Speter */ 768114987Speterint 769119336Speterfreebsd4_freebsd32_sigreturn(td, uap) 770114987Speter struct thread *td; 771119336Speter struct freebsd4_freebsd32_sigreturn_args /* { 772119336Speter const struct freebsd4_freebsd32_ucontext *sigcntxp; 773114987Speter } */ *uap; 774114987Speter{ 775114987Speter struct ia32_ucontext4 uc; 776114987Speter struct trapframe *regs; 777198507Skib struct ia32_ucontext4 *ucp; 778114987Speter int cs, eflags, error; 779151316Sdavidxu ksiginfo_t ksi; 780114987Speter 781114987Speter error = copyin(uap->sigcntxp, &uc, sizeof(uc)); 782114987Speter if (error != 0) 783114987Speter return (error); 784114987Speter ucp = &uc; 785114987Speter regs = td->td_frame; 786114987Speter eflags = ucp->uc_mcontext.mc_eflags; 787114987Speter /* 788114987Speter * Don't allow users to change privileged or reserved flags. 789114987Speter */ 790258559Semaste if (!EFL_SECURE(eflags, regs->tf_rflags)) { 791206553Skib uprintf("pid %d (%s): freebsd4_freebsd32_sigreturn eflags = 0x%x\n", 792206553Skib td->td_proc->p_pid, td->td_name, eflags); 793114987Speter return (EINVAL); 794114987Speter } 795114987Speter 796114987Speter /* 797114987Speter * Don't allow users to load a valid privileged %cs. Let the 798114987Speter * hardware check for invalid selectors, excess privilege in 799114987Speter * other selectors, invalid %eip's and invalid %esp's. 800114987Speter */ 801114987Speter cs = ucp->uc_mcontext.mc_cs; 802114987Speter if (!CS_SECURE(cs)) { 803206553Skib uprintf("pid %d (%s): freebsd4_sigreturn cs = 0x%x\n", 804206553Skib td->td_proc->p_pid, td->td_name, cs); 805151316Sdavidxu ksiginfo_init_trap(&ksi); 806151316Sdavidxu ksi.ksi_signo = SIGBUS; 807151316Sdavidxu ksi.ksi_code = BUS_OBJERR; 808151316Sdavidxu ksi.ksi_trapno = T_PROTFLT; 809151316Sdavidxu ksi.ksi_addr = (void *)regs->tf_rip; 810151316Sdavidxu trapsignal(td, &ksi); 811114987Speter return (EINVAL); 812114987Speter } 813114987Speter 814114987Speter regs->tf_rdi = ucp->uc_mcontext.mc_edi; 815114987Speter regs->tf_rsi = ucp->uc_mcontext.mc_esi; 816114987Speter regs->tf_rbp = ucp->uc_mcontext.mc_ebp; 817114987Speter regs->tf_rbx = ucp->uc_mcontext.mc_ebx; 818114987Speter regs->tf_rdx = ucp->uc_mcontext.mc_edx; 819114987Speter regs->tf_rcx = ucp->uc_mcontext.mc_ecx; 820114987Speter regs->tf_rax = ucp->uc_mcontext.mc_eax; 821114987Speter regs->tf_trapno = ucp->uc_mcontext.mc_trapno; 822114987Speter regs->tf_err = ucp->uc_mcontext.mc_err; 823114987Speter regs->tf_rip = ucp->uc_mcontext.mc_eip; 824114987Speter regs->tf_cs = cs; 825114987Speter regs->tf_rflags = ucp->uc_mcontext.mc_eflags; 826114987Speter regs->tf_rsp = ucp->uc_mcontext.mc_esp; 827114987Speter regs->tf_ss = ucp->uc_mcontext.mc_ss; 828190620Skib regs->tf_ds = ucp->uc_mcontext.mc_ds; 829190620Skib regs->tf_es = ucp->uc_mcontext.mc_es; 830190620Skib regs->tf_fs = ucp->uc_mcontext.mc_fs; 831190620Skib regs->tf_gs = ucp->uc_mcontext.mc_gs; 832114987Speter 833198507Skib kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0); 834216634Sjkim set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 835114987Speter return (EJUSTRETURN); 836114987Speter} 837114987Speter#endif /* COMPAT_FREEBSD4 */ 838114987Speter 839114987Speter/* 840114987Speter * MPSAFE 841114987Speter */ 842114987Speterint 843119336Speterfreebsd32_sigreturn(td, uap) 844114987Speter struct thread *td; 845119336Speter struct freebsd32_sigreturn_args /* { 846119336Speter const struct freebsd32_ucontext *sigcntxp; 847114987Speter } */ *uap; 848114987Speter{ 849114987Speter struct ia32_ucontext uc; 850114987Speter struct trapframe *regs; 851198507Skib struct ia32_ucontext *ucp; 852230426Skib char *xfpustate; 853230426Skib size_t xfpustate_len; 854114987Speter int cs, eflags, error, ret; 855151316Sdavidxu ksiginfo_t ksi; 856114987Speter 857114987Speter error = copyin(uap->sigcntxp, &uc, sizeof(uc)); 858114987Speter if (error != 0) 859114987Speter return (error); 860114987Speter ucp = &uc; 861114987Speter regs = td->td_frame; 862114987Speter eflags = ucp->uc_mcontext.mc_eflags; 863114987Speter /* 864114987Speter * Don't allow users to change privileged or reserved flags. 865114987Speter */ 866258559Semaste if (!EFL_SECURE(eflags, regs->tf_rflags)) { 867206553Skib uprintf("pid %d (%s): freebsd32_sigreturn eflags = 0x%x\n", 868206553Skib td->td_proc->p_pid, td->td_name, eflags); 869114987Speter return (EINVAL); 870114987Speter } 871114987Speter 872114987Speter /* 873114987Speter * Don't allow users to load a valid privileged %cs. Let the 874114987Speter * hardware check for invalid selectors, excess privilege in 875114987Speter * other selectors, invalid %eip's and invalid %esp's. 876114987Speter */ 877114987Speter cs = ucp->uc_mcontext.mc_cs; 878114987Speter if (!CS_SECURE(cs)) { 879206553Skib uprintf("pid %d (%s): sigreturn cs = 0x%x\n", 880206553Skib td->td_proc->p_pid, td->td_name, cs); 881151316Sdavidxu ksiginfo_init_trap(&ksi); 882151316Sdavidxu ksi.ksi_signo = SIGBUS; 883151316Sdavidxu ksi.ksi_code = BUS_OBJERR; 884151316Sdavidxu ksi.ksi_trapno = T_PROTFLT; 885151316Sdavidxu ksi.ksi_addr = (void *)regs->tf_rip; 886151316Sdavidxu trapsignal(td, &ksi); 887114987Speter return (EINVAL); 888114987Speter } 889114987Speter 890230426Skib if ((ucp->uc_mcontext.mc_flags & _MC_HASFPXSTATE) != 0) { 891230426Skib xfpustate_len = uc.uc_mcontext.mc_xfpustate_len; 892230426Skib if (xfpustate_len > cpu_max_ext_state_size - 893230426Skib sizeof(struct savefpu)) { 894230426Skib uprintf("pid %d (%s): sigreturn xfpusave_len = 0x%zx\n", 895230426Skib td->td_proc->p_pid, td->td_name, xfpustate_len); 896230426Skib return (EINVAL); 897230426Skib } 898230426Skib xfpustate = __builtin_alloca(xfpustate_len); 899230426Skib error = copyin(PTRIN(ucp->uc_mcontext.mc_xfpustate), 900230426Skib xfpustate, xfpustate_len); 901230426Skib if (error != 0) { 902230426Skib uprintf( 903230426Skib "pid %d (%s): sigreturn copying xfpustate failed\n", 904230426Skib td->td_proc->p_pid, td->td_name); 905230426Skib return (error); 906230426Skib } 907230426Skib } else { 908230426Skib xfpustate = NULL; 909230426Skib xfpustate_len = 0; 910230426Skib } 911230426Skib ret = ia32_set_fpcontext(td, &ucp->uc_mcontext, xfpustate, 912230426Skib xfpustate_len); 913230426Skib if (ret != 0) { 914230426Skib uprintf("pid %d (%s): sigreturn set_fpcontext err %d\n", 915230426Skib td->td_proc->p_pid, td->td_name, ret); 916114987Speter return (ret); 917230426Skib } 918114987Speter 919114987Speter regs->tf_rdi = ucp->uc_mcontext.mc_edi; 920114987Speter regs->tf_rsi = ucp->uc_mcontext.mc_esi; 921114987Speter regs->tf_rbp = ucp->uc_mcontext.mc_ebp; 922114987Speter regs->tf_rbx = ucp->uc_mcontext.mc_ebx; 923114987Speter regs->tf_rdx = ucp->uc_mcontext.mc_edx; 924114987Speter regs->tf_rcx = ucp->uc_mcontext.mc_ecx; 925114987Speter regs->tf_rax = ucp->uc_mcontext.mc_eax; 926114987Speter regs->tf_trapno = ucp->uc_mcontext.mc_trapno; 927114987Speter regs->tf_err = ucp->uc_mcontext.mc_err; 928114987Speter regs->tf_rip = ucp->uc_mcontext.mc_eip; 929114987Speter regs->tf_cs = cs; 930114987Speter regs->tf_rflags = ucp->uc_mcontext.mc_eflags; 931114987Speter regs->tf_rsp = ucp->uc_mcontext.mc_esp; 932114987Speter regs->tf_ss = ucp->uc_mcontext.mc_ss; 933190620Skib regs->tf_ds = ucp->uc_mcontext.mc_ds; 934190620Skib regs->tf_es = ucp->uc_mcontext.mc_es; 935190620Skib regs->tf_fs = ucp->uc_mcontext.mc_fs; 936190620Skib regs->tf_gs = ucp->uc_mcontext.mc_gs; 937190620Skib regs->tf_flags = TF_HASSEGS; 938114987Speter 939198507Skib kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0); 940216634Sjkim set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 941114987Speter return (EJUSTRETURN); 942114987Speter} 943122303Speter 944122303Speter/* 945122303Speter * Clear registers on exec 946122303Speter */ 947122303Spetervoid 948205642Snwhitehornia32_setregs(struct thread *td, struct image_params *imgp, u_long stack) 949122303Speter{ 950122303Speter struct trapframe *regs = td->td_frame; 951122303Speter struct pcb *pcb = td->td_pcb; 952122303Speter 953190620Skib mtx_lock(&dt_lock); 954190620Skib if (td->td_proc->p_md.md_ldt != NULL) 955190620Skib user_ldt_free(td); 956190620Skib else 957190620Skib mtx_unlock(&dt_lock); 958220238Skib#ifdef COMPAT_43 959220238Skib setup_lcall_gate(); 960220238Skib#endif 961190620Skib 962122303Speter pcb->pcb_fsbase = 0; 963122303Speter pcb->pcb_gsbase = 0; 964189423Sjhb pcb->pcb_initial_fpucw = __INITIAL_FPUCW_I386__; 965122303Speter 966122303Speter bzero((char *)regs, sizeof(struct trapframe)); 967205642Snwhitehorn regs->tf_rip = imgp->entry_addr; 968122303Speter regs->tf_rsp = stack; 969122303Speter regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T); 970122303Speter regs->tf_ss = _udatasel; 971122303Speter regs->tf_cs = _ucode32sel; 972205642Snwhitehorn regs->tf_rbx = imgp->ps_strings; 973190620Skib regs->tf_ds = _udatasel; 974190620Skib regs->tf_es = _udatasel; 975190620Skib regs->tf_fs = _ufssel; 976190620Skib regs->tf_gs = _ugssel; 977190620Skib regs->tf_flags = TF_HASSEGS; 978190620Skib 979122303Speter fpstate_drop(td); 980122303Speter 981122303Speter /* Return via doreti so that we can change to a different %cs */ 982216634Sjkim set_pcb_flags(pcb, PCB_32BIT | PCB_FULL_IRET); 983122303Speter td->td_retval[1] = 0; 984122303Speter} 985