ia32_signal.c revision 216634
1203954Srdivacky/*- 2203954Srdivacky * Copyright (c) 2003 Peter Wemm 3203954Srdivacky * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. 4203954Srdivacky * All rights reserved. 5203954Srdivacky * 6203954Srdivacky * This code is derived from software contributed to Berkeley by 7203954Srdivacky * William Jolitz. 8203954Srdivacky * 9203954Srdivacky * Redistribution and use in source and binary forms, with or without 10203954Srdivacky * modification, are permitted provided that the following conditions 11203954Srdivacky * are met: 12203954Srdivacky * 1. Redistributions of source code must retain the above copyright 13203954Srdivacky * notice, this list of conditions and the following disclaimer. 14203954Srdivacky * 2. Redistributions in binary form must reproduce the above copyright 15203954Srdivacky * notice, this list of conditions and the following disclaimer in the 16203954Srdivacky * documentation and/or other materials provided with the distribution. 17203954Srdivacky * 4. Neither the name of the University nor the names of its contributors 18203954Srdivacky * may be used to endorse or promote products derived from this software 19203954Srdivacky * without specific prior written permission. 20203954Srdivacky * 21203954Srdivacky * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22203954Srdivacky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23203954Srdivacky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24203954Srdivacky * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25203954Srdivacky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26203954Srdivacky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27203954Srdivacky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28203954Srdivacky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29203954Srdivacky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30203954Srdivacky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31203954Srdivacky * SUCH DAMAGE. 32203954Srdivacky */ 33203954Srdivacky 34203954Srdivacky#include <sys/cdefs.h> 35203954Srdivacky__FBSDID("$FreeBSD: head/sys/amd64/ia32/ia32_signal.c 216634 2010-12-22 00:18:42Z jkim $"); 36212904Sdim 37203954Srdivacky#include "opt_compat.h" 38203954Srdivacky 39203954Srdivacky#include <sys/param.h> 40203954Srdivacky#include <sys/exec.h> 41203954Srdivacky#include <sys/fcntl.h> 42203954Srdivacky#include <sys/imgact.h> 43203954Srdivacky#include <sys/kernel.h> 44203954Srdivacky#include <sys/lock.h> 45203954Srdivacky#include <sys/malloc.h> 46203954Srdivacky#include <sys/mutex.h> 47203954Srdivacky#include <sys/mman.h> 48203954Srdivacky#include <sys/namei.h> 49203954Srdivacky#include <sys/pioctl.h> 50203954Srdivacky#include <sys/proc.h> 51203954Srdivacky#include <sys/procfs.h> 52203954Srdivacky#include <sys/resourcevar.h> 53203954Srdivacky#include <sys/systm.h> 54203954Srdivacky#include <sys/signalvar.h> 55203954Srdivacky#include <sys/stat.h> 56203954Srdivacky#include <sys/sx.h> 57212904Sdim#include <sys/syscall.h> 58212904Sdim#include <sys/syscallsubr.h> 59203954Srdivacky#include <sys/sysctl.h> 60203954Srdivacky#include <sys/sysent.h> 61203954Srdivacky#include <sys/vnode.h> 62203954Srdivacky 63203954Srdivacky#include <vm/vm.h> 64203954Srdivacky#include <vm/vm_kern.h> 65203954Srdivacky#include <vm/vm_param.h> 66203954Srdivacky#include <vm/pmap.h> 67203954Srdivacky#include <vm/vm_map.h> 68203954Srdivacky#include <vm/vm_object.h> 69203954Srdivacky#include <vm/vm_extern.h> 70203954Srdivacky 71203954Srdivacky#include <compat/freebsd32/freebsd32_signal.h> 72203954Srdivacky#include <compat/freebsd32/freebsd32_util.h> 73203954Srdivacky#include <compat/freebsd32/freebsd32_proto.h> 74203954Srdivacky#include <compat/ia32/ia32_signal.h> 75203954Srdivacky#include <machine/psl.h> 76203954Srdivacky#include <machine/segments.h> 77203954Srdivacky#include <machine/specialreg.h> 78203954Srdivacky#include <machine/frame.h> 79203954Srdivacky#include <machine/md_var.h> 80203954Srdivacky#include <machine/pcb.h> 81203954Srdivacky#include <machine/cpufunc.h> 82203954Srdivacky 83203954Srdivacky#ifdef COMPAT_FREEBSD4 84203954Srdivackystatic void freebsd4_ia32_sendsig(sig_t, ksiginfo_t *, sigset_t *); 85203954Srdivacky#endif 86203954Srdivackystatic void ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp); 87203954Srdivackystatic int ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp); 88203954Srdivacky 89203954Srdivacky#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) 90203954Srdivacky#define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) 91203954Srdivacky 92203954Srdivackystatic void 93203954Srdivackyia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp) 94203954Srdivacky{ 95203954Srdivacky 96203954Srdivacky /* 97203954Srdivacky * XXX Format of 64bit and 32bit FXSAVE areas differs. FXSAVE 98203954Srdivacky * in 32bit mode saves %cs and %ds, while on 64bit it saves 99203954Srdivacky * 64bit instruction and data pointers. Ignore the difference 100203954Srdivacky * for now, it should be irrelevant for most applications. 101203954Srdivacky */ 102203954Srdivacky mcp->mc_ownedfp = fpugetregs(td); 103203954Srdivacky bcopy(&td->td_pcb->pcb_user_save, &mcp->mc_fpstate, 104212904Sdim sizeof(mcp->mc_fpstate)); 105212904Sdim mcp->mc_fpformat = fpuformat(); 106212904Sdim} 107212904Sdim 108210299Sedstatic int 109203954Srdivackyia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp) 110203954Srdivacky{ 111203954Srdivacky 112203954Srdivacky if (mcp->mc_fpformat == _MC_FPFMT_NODEV) 113203954Srdivacky return (0); 114203954Srdivacky else if (mcp->mc_fpformat != _MC_FPFMT_XMM) 115203954Srdivacky return (EINVAL); 116203954Srdivacky else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) 117203954Srdivacky /* We don't care what state is left in the FPU or PCB. */ 118203954Srdivacky fpstate_drop(td); 119203954Srdivacky else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU || 120203954Srdivacky mcp->mc_ownedfp == _MC_FPOWNED_PCB) { 121203954Srdivacky fpusetregs(td, (struct savefpu *)&mcp->mc_fpstate); 122203954Srdivacky } else 123203954Srdivacky return (EINVAL); 124203954Srdivacky return (0); 125203954Srdivacky} 126203954Srdivacky 127203954Srdivacky/* 128203954Srdivacky * Get machine context. 129203954Srdivacky */ 130203954Srdivackystatic int 131203954Srdivackyia32_get_mcontext(struct thread *td, struct ia32_mcontext *mcp, int flags) 132203954Srdivacky{ 133203954Srdivacky struct pcb *pcb; 134203954Srdivacky struct trapframe *tp; 135203954Srdivacky 136203954Srdivacky pcb = td->td_pcb; 137203954Srdivacky tp = td->td_frame; 138203954Srdivacky 139203954Srdivacky PROC_LOCK(curthread->td_proc); 140203954Srdivacky mcp->mc_onstack = sigonstack(tp->tf_rsp); 141203954Srdivacky PROC_UNLOCK(curthread->td_proc); 142203954Srdivacky /* Entry into kernel always sets TF_HASSEGS */ 143203954Srdivacky mcp->mc_gs = tp->tf_gs; 144203954Srdivacky mcp->mc_fs = tp->tf_fs; 145203954Srdivacky mcp->mc_es = tp->tf_es; 146203954Srdivacky mcp->mc_ds = tp->tf_ds; 147203954Srdivacky mcp->mc_edi = tp->tf_rdi; 148203954Srdivacky mcp->mc_esi = tp->tf_rsi; 149203954Srdivacky mcp->mc_ebp = tp->tf_rbp; 150203954Srdivacky mcp->mc_isp = tp->tf_rsp; 151203954Srdivacky mcp->mc_eflags = tp->tf_rflags; 152203954Srdivacky if (flags & GET_MC_CLEAR_RET) { 153203954Srdivacky mcp->mc_eax = 0; 154203954Srdivacky mcp->mc_edx = 0; 155203954Srdivacky mcp->mc_eflags &= ~PSL_C; 156203954Srdivacky } else { 157203954Srdivacky mcp->mc_eax = tp->tf_rax; 158203954Srdivacky mcp->mc_edx = tp->tf_rdx; 159203954Srdivacky } 160203954Srdivacky mcp->mc_ebx = tp->tf_rbx; 161203954Srdivacky mcp->mc_ecx = tp->tf_rcx; 162203954Srdivacky mcp->mc_eip = tp->tf_rip; 163203954Srdivacky mcp->mc_cs = tp->tf_cs; 164203954Srdivacky mcp->mc_esp = tp->tf_rsp; 165203954Srdivacky mcp->mc_ss = tp->tf_ss; 166203954Srdivacky mcp->mc_len = sizeof(*mcp); 167203954Srdivacky ia32_get_fpcontext(td, mcp); 168203954Srdivacky mcp->mc_fsbase = pcb->pcb_fsbase; 169203954Srdivacky mcp->mc_gsbase = pcb->pcb_gsbase; 170203954Srdivacky set_pcb_flags(pcb, PCB_FULL_IRET); 171203954Srdivacky return (0); 172203954Srdivacky} 173203954Srdivacky 174203954Srdivacky/* 175203954Srdivacky * Set machine context. 176203954Srdivacky * 177203954Srdivacky * However, we don't set any but the user modifiable flags, and we won't 178203954Srdivacky * touch the cs selector. 179203954Srdivacky */ 180203954Srdivackystatic int 181203954Srdivackyia32_set_mcontext(struct thread *td, const struct ia32_mcontext *mcp) 182203954Srdivacky{ 183203954Srdivacky struct trapframe *tp; 184203954Srdivacky long rflags; 185203954Srdivacky int ret; 186203954Srdivacky 187203954Srdivacky tp = td->td_frame; 188203954Srdivacky if (mcp->mc_len != sizeof(*mcp)) 189 return (EINVAL); 190 rflags = (mcp->mc_eflags & PSL_USERCHANGE) | 191 (tp->tf_rflags & ~PSL_USERCHANGE); 192 ret = ia32_set_fpcontext(td, mcp); 193 if (ret != 0) 194 return (ret); 195 tp->tf_gs = mcp->mc_gs; 196 tp->tf_fs = mcp->mc_fs; 197 tp->tf_es = mcp->mc_es; 198 tp->tf_ds = mcp->mc_ds; 199 tp->tf_flags = TF_HASSEGS; 200 tp->tf_rdi = mcp->mc_edi; 201 tp->tf_rsi = mcp->mc_esi; 202 tp->tf_rbp = mcp->mc_ebp; 203 tp->tf_rbx = mcp->mc_ebx; 204 tp->tf_rdx = mcp->mc_edx; 205 tp->tf_rcx = mcp->mc_ecx; 206 tp->tf_rax = mcp->mc_eax; 207 /* trapno, err */ 208 tp->tf_rip = mcp->mc_eip; 209 tp->tf_rflags = rflags; 210 tp->tf_rsp = mcp->mc_esp; 211 tp->tf_ss = mcp->mc_ss; 212 set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 213 return (0); 214} 215 216/* 217 * The first two fields of a ucontext_t are the signal mask and 218 * the machine context. The next field is uc_link; we want to 219 * avoid destroying the link when copying out contexts. 220 */ 221#define UC_COPY_SIZE offsetof(struct ia32_ucontext, uc_link) 222 223int 224freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap) 225{ 226 struct ia32_ucontext uc; 227 int ret; 228 229 if (uap->ucp == NULL) 230 ret = EINVAL; 231 else { 232 ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 233 PROC_LOCK(td->td_proc); 234 uc.uc_sigmask = td->td_sigmask; 235 PROC_UNLOCK(td->td_proc); 236 ret = copyout(&uc, uap->ucp, UC_COPY_SIZE); 237 } 238 return (ret); 239} 240 241int 242freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap) 243{ 244 struct ia32_ucontext uc; 245 int ret; 246 247 if (uap->ucp == NULL) 248 ret = EINVAL; 249 else { 250 ret = copyin(uap->ucp, &uc, UC_COPY_SIZE); 251 if (ret == 0) { 252 ret = ia32_set_mcontext(td, &uc.uc_mcontext); 253 if (ret == 0) { 254 kern_sigprocmask(td, SIG_SETMASK, 255 &uc.uc_sigmask, NULL, 0); 256 } 257 } 258 } 259 return (ret == 0 ? EJUSTRETURN : ret); 260} 261 262int 263freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap) 264{ 265 struct ia32_ucontext uc; 266 int ret; 267 268 if (uap->oucp == NULL || uap->ucp == NULL) 269 ret = EINVAL; 270 else { 271 ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 272 PROC_LOCK(td->td_proc); 273 uc.uc_sigmask = td->td_sigmask; 274 PROC_UNLOCK(td->td_proc); 275 ret = copyout(&uc, uap->oucp, UC_COPY_SIZE); 276 if (ret == 0) { 277 ret = copyin(uap->ucp, &uc, UC_COPY_SIZE); 278 if (ret == 0) { 279 ret = ia32_set_mcontext(td, &uc.uc_mcontext); 280 if (ret == 0) { 281 kern_sigprocmask(td, SIG_SETMASK, 282 &uc.uc_sigmask, NULL, 0); 283 } 284 } 285 } 286 } 287 return (ret == 0 ? EJUSTRETURN : ret); 288} 289 290/* 291 * Send an interrupt to process. 292 * 293 * Stack is set up to allow sigcode stored 294 * at top to call routine, followed by kcall 295 * to sigreturn routine below. After sigreturn 296 * resets the signal mask, the stack, and the 297 * frame pointer, it returns to the user 298 * specified pc, psl. 299 */ 300#ifdef COMPAT_FREEBSD4 301static void 302freebsd4_ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 303{ 304 struct ia32_sigframe4 sf, *sfp; 305 struct siginfo32 siginfo; 306 struct proc *p; 307 struct thread *td; 308 struct sigacts *psp; 309 struct trapframe *regs; 310 int oonstack; 311 int sig; 312 313 td = curthread; 314 p = td->td_proc; 315 siginfo_to_siginfo32(&ksi->ksi_info, &siginfo); 316 317 PROC_LOCK_ASSERT(p, MA_OWNED); 318 sig = siginfo.si_signo; 319 psp = p->p_sigacts; 320 mtx_assert(&psp->ps_mtx, MA_OWNED); 321 regs = td->td_frame; 322 oonstack = sigonstack(regs->tf_rsp); 323 324 /* Save user context. */ 325 bzero(&sf, sizeof(sf)); 326 sf.sf_uc.uc_sigmask = *mask; 327 sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp; 328 sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size; 329 sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) 330 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 331 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 332 sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi; 333 sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi; 334 sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp; 335 sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */ 336 sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx; 337 sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx; 338 sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx; 339 sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax; 340 sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno; 341 sf.sf_uc.uc_mcontext.mc_err = regs->tf_err; 342 sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip; 343 sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs; 344 sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags; 345 sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp; 346 sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss; 347 sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds; 348 sf.sf_uc.uc_mcontext.mc_es = regs->tf_es; 349 sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs; 350 sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs; 351 352 /* Allocate space for the signal handler context. */ 353 if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 354 SIGISMEMBER(psp->ps_sigonstack, sig)) { 355 sfp = (struct ia32_sigframe4 *)(td->td_sigstk.ss_sp + 356 td->td_sigstk.ss_size - sizeof(sf)); 357 } else 358 sfp = (struct ia32_sigframe4 *)regs->tf_rsp - 1; 359 PROC_UNLOCK(p); 360 361 /* Translate the signal if appropriate. */ 362 if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 363 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 364 365 /* Build the argument list for the signal handler. */ 366 sf.sf_signum = sig; 367 sf.sf_ucontext = (register_t)&sfp->sf_uc; 368 if (SIGISMEMBER(psp->ps_siginfo, sig)) { 369 /* Signal handler installed with SA_SIGINFO. */ 370 sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si; 371 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 372 373 /* Fill in POSIX parts */ 374 sf.sf_si = siginfo; 375 sf.sf_si.si_signo = sig; 376 } else { 377 /* Old FreeBSD-style arguments. */ 378 sf.sf_siginfo = siginfo.si_code; 379 sf.sf_addr = (u_int32_t)siginfo.si_addr; 380 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 381 } 382 mtx_unlock(&psp->ps_mtx); 383 384 /* 385 * Copy the sigframe out to the user's stack. 386 */ 387 if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { 388#ifdef DEBUG 389 printf("process %ld has trashed its stack\n", (long)p->p_pid); 390#endif 391 PROC_LOCK(p); 392 sigexit(td, SIGILL); 393 } 394 395 regs->tf_rsp = (uintptr_t)sfp; 396 regs->tf_rip = p->p_sysent->sv_psstrings - sz_freebsd4_ia32_sigcode; 397 regs->tf_rflags &= ~(PSL_T | PSL_D); 398 regs->tf_cs = _ucode32sel; 399 regs->tf_ss = _udatasel; 400 regs->tf_ds = _udatasel; 401 regs->tf_es = _udatasel; 402 set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 403 /* leave user %fs and %gs untouched */ 404 PROC_LOCK(p); 405 mtx_lock(&psp->ps_mtx); 406} 407#endif /* COMPAT_FREEBSD4 */ 408 409void 410ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 411{ 412 struct ia32_sigframe sf, *sfp; 413 struct siginfo32 siginfo; 414 struct proc *p; 415 struct thread *td; 416 struct sigacts *psp; 417 char *sp; 418 struct trapframe *regs; 419 int oonstack; 420 int sig; 421 422 siginfo_to_siginfo32(&ksi->ksi_info, &siginfo); 423 td = curthread; 424 p = td->td_proc; 425 PROC_LOCK_ASSERT(p, MA_OWNED); 426 sig = siginfo.si_signo; 427 psp = p->p_sigacts; 428#ifdef COMPAT_FREEBSD4 429 if (SIGISMEMBER(psp->ps_freebsd4, sig)) { 430 freebsd4_ia32_sendsig(catcher, ksi, mask); 431 return; 432 } 433#endif 434 mtx_assert(&psp->ps_mtx, MA_OWNED); 435 regs = td->td_frame; 436 oonstack = sigonstack(regs->tf_rsp); 437 438 /* Save user context. */ 439 bzero(&sf, sizeof(sf)); 440 sf.sf_uc.uc_sigmask = *mask; 441 sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp; 442 sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size; 443 sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) 444 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 445 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 446 sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi; 447 sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi; 448 sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp; 449 sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */ 450 sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx; 451 sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx; 452 sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx; 453 sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax; 454 sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno; 455 sf.sf_uc.uc_mcontext.mc_err = regs->tf_err; 456 sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip; 457 sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs; 458 sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags; 459 sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp; 460 sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss; 461 sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds; 462 sf.sf_uc.uc_mcontext.mc_es = regs->tf_es; 463 sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs; 464 sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs; 465 sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */ 466 ia32_get_fpcontext(td, &sf.sf_uc.uc_mcontext); 467 fpstate_drop(td); 468 sf.sf_uc.uc_mcontext.mc_fsbase = td->td_pcb->pcb_fsbase; 469 sf.sf_uc.uc_mcontext.mc_gsbase = td->td_pcb->pcb_gsbase; 470 471 /* Allocate space for the signal handler context. */ 472 if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 473 SIGISMEMBER(psp->ps_sigonstack, sig)) { 474 sp = td->td_sigstk.ss_sp + 475 td->td_sigstk.ss_size - sizeof(sf); 476 } else 477 sp = (char *)regs->tf_rsp - sizeof(sf); 478 /* Align to 16 bytes. */ 479 sfp = (struct ia32_sigframe *)((uintptr_t)sp & ~0xF); 480 PROC_UNLOCK(p); 481 482 /* Translate the signal if appropriate. */ 483 if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 484 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 485 486 /* Build the argument list for the signal handler. */ 487 sf.sf_signum = sig; 488 sf.sf_ucontext = (register_t)&sfp->sf_uc; 489 if (SIGISMEMBER(psp->ps_siginfo, sig)) { 490 /* Signal handler installed with SA_SIGINFO. */ 491 sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si; 492 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 493 494 /* Fill in POSIX parts */ 495 sf.sf_si = siginfo; 496 sf.sf_si.si_signo = sig; 497 } else { 498 /* Old FreeBSD-style arguments. */ 499 sf.sf_siginfo = siginfo.si_code; 500 sf.sf_addr = (u_int32_t)siginfo.si_addr; 501 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 502 } 503 mtx_unlock(&psp->ps_mtx); 504 505 /* 506 * Copy the sigframe out to the user's stack. 507 */ 508 if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { 509#ifdef DEBUG 510 printf("process %ld has trashed its stack\n", (long)p->p_pid); 511#endif 512 PROC_LOCK(p); 513 sigexit(td, SIGILL); 514 } 515 516 regs->tf_rsp = (uintptr_t)sfp; 517 regs->tf_rip = p->p_sysent->sv_psstrings - *(p->p_sysent->sv_szsigcode); 518 regs->tf_rflags &= ~(PSL_T | PSL_D); 519 regs->tf_cs = _ucode32sel; 520 regs->tf_ss = _udatasel; 521 regs->tf_ds = _udatasel; 522 regs->tf_es = _udatasel; 523 set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 524 /* XXXKIB leave user %fs and %gs untouched */ 525 PROC_LOCK(p); 526 mtx_lock(&psp->ps_mtx); 527} 528 529/* 530 * System call to cleanup state after a signal 531 * has been taken. Reset signal mask and 532 * stack state from context left by sendsig (above). 533 * Return to previous pc and psl as specified by 534 * context left by sendsig. Check carefully to 535 * make sure that the user has not modified the 536 * state to gain improper privileges. 537 */ 538#ifdef COMPAT_FREEBSD4 539/* 540 * MPSAFE 541 */ 542int 543freebsd4_freebsd32_sigreturn(td, uap) 544 struct thread *td; 545 struct freebsd4_freebsd32_sigreturn_args /* { 546 const struct freebsd4_freebsd32_ucontext *sigcntxp; 547 } */ *uap; 548{ 549 struct ia32_ucontext4 uc; 550 struct trapframe *regs; 551 struct ia32_ucontext4 *ucp; 552 int cs, eflags, error; 553 ksiginfo_t ksi; 554 555 error = copyin(uap->sigcntxp, &uc, sizeof(uc)); 556 if (error != 0) 557 return (error); 558 ucp = &uc; 559 regs = td->td_frame; 560 eflags = ucp->uc_mcontext.mc_eflags; 561 /* 562 * Don't allow users to change privileged or reserved flags. 563 */ 564 /* 565 * XXX do allow users to change the privileged flag PSL_RF. 566 * The cpu sets PSL_RF in tf_eflags for faults. Debuggers 567 * should sometimes set it there too. tf_eflags is kept in 568 * the signal context during signal handling and there is no 569 * other place to remember it, so the PSL_RF bit may be 570 * corrupted by the signal handler without us knowing. 571 * Corruption of the PSL_RF bit at worst causes one more or 572 * one less debugger trap, so allowing it is fairly harmless. 573 */ 574 if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) { 575 uprintf("pid %d (%s): freebsd4_freebsd32_sigreturn eflags = 0x%x\n", 576 td->td_proc->p_pid, td->td_name, eflags); 577 return (EINVAL); 578 } 579 580 /* 581 * Don't allow users to load a valid privileged %cs. Let the 582 * hardware check for invalid selectors, excess privilege in 583 * other selectors, invalid %eip's and invalid %esp's. 584 */ 585 cs = ucp->uc_mcontext.mc_cs; 586 if (!CS_SECURE(cs)) { 587 uprintf("pid %d (%s): freebsd4_sigreturn cs = 0x%x\n", 588 td->td_proc->p_pid, td->td_name, cs); 589 ksiginfo_init_trap(&ksi); 590 ksi.ksi_signo = SIGBUS; 591 ksi.ksi_code = BUS_OBJERR; 592 ksi.ksi_trapno = T_PROTFLT; 593 ksi.ksi_addr = (void *)regs->tf_rip; 594 trapsignal(td, &ksi); 595 return (EINVAL); 596 } 597 598 regs->tf_rdi = ucp->uc_mcontext.mc_edi; 599 regs->tf_rsi = ucp->uc_mcontext.mc_esi; 600 regs->tf_rbp = ucp->uc_mcontext.mc_ebp; 601 regs->tf_rbx = ucp->uc_mcontext.mc_ebx; 602 regs->tf_rdx = ucp->uc_mcontext.mc_edx; 603 regs->tf_rcx = ucp->uc_mcontext.mc_ecx; 604 regs->tf_rax = ucp->uc_mcontext.mc_eax; 605 regs->tf_trapno = ucp->uc_mcontext.mc_trapno; 606 regs->tf_err = ucp->uc_mcontext.mc_err; 607 regs->tf_rip = ucp->uc_mcontext.mc_eip; 608 regs->tf_cs = cs; 609 regs->tf_rflags = ucp->uc_mcontext.mc_eflags; 610 regs->tf_rsp = ucp->uc_mcontext.mc_esp; 611 regs->tf_ss = ucp->uc_mcontext.mc_ss; 612 regs->tf_ds = ucp->uc_mcontext.mc_ds; 613 regs->tf_es = ucp->uc_mcontext.mc_es; 614 regs->tf_fs = ucp->uc_mcontext.mc_fs; 615 regs->tf_gs = ucp->uc_mcontext.mc_gs; 616 617 kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0); 618 set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 619 return (EJUSTRETURN); 620} 621#endif /* COMPAT_FREEBSD4 */ 622 623/* 624 * MPSAFE 625 */ 626int 627freebsd32_sigreturn(td, uap) 628 struct thread *td; 629 struct freebsd32_sigreturn_args /* { 630 const struct freebsd32_ucontext *sigcntxp; 631 } */ *uap; 632{ 633 struct ia32_ucontext uc; 634 struct trapframe *regs; 635 struct ia32_ucontext *ucp; 636 int cs, eflags, error, ret; 637 ksiginfo_t ksi; 638 639 error = copyin(uap->sigcntxp, &uc, sizeof(uc)); 640 if (error != 0) 641 return (error); 642 ucp = &uc; 643 regs = td->td_frame; 644 eflags = ucp->uc_mcontext.mc_eflags; 645 /* 646 * Don't allow users to change privileged or reserved flags. 647 */ 648 /* 649 * XXX do allow users to change the privileged flag PSL_RF. 650 * The cpu sets PSL_RF in tf_eflags for faults. Debuggers 651 * should sometimes set it there too. tf_eflags is kept in 652 * the signal context during signal handling and there is no 653 * other place to remember it, so the PSL_RF bit may be 654 * corrupted by the signal handler without us knowing. 655 * Corruption of the PSL_RF bit at worst causes one more or 656 * one less debugger trap, so allowing it is fairly harmless. 657 */ 658 if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) { 659 uprintf("pid %d (%s): freebsd32_sigreturn eflags = 0x%x\n", 660 td->td_proc->p_pid, td->td_name, eflags); 661 return (EINVAL); 662 } 663 664 /* 665 * Don't allow users to load a valid privileged %cs. Let the 666 * hardware check for invalid selectors, excess privilege in 667 * other selectors, invalid %eip's and invalid %esp's. 668 */ 669 cs = ucp->uc_mcontext.mc_cs; 670 if (!CS_SECURE(cs)) { 671 uprintf("pid %d (%s): sigreturn cs = 0x%x\n", 672 td->td_proc->p_pid, td->td_name, cs); 673 ksiginfo_init_trap(&ksi); 674 ksi.ksi_signo = SIGBUS; 675 ksi.ksi_code = BUS_OBJERR; 676 ksi.ksi_trapno = T_PROTFLT; 677 ksi.ksi_addr = (void *)regs->tf_rip; 678 trapsignal(td, &ksi); 679 return (EINVAL); 680 } 681 682 ret = ia32_set_fpcontext(td, &ucp->uc_mcontext); 683 if (ret != 0) 684 return (ret); 685 686 regs->tf_rdi = ucp->uc_mcontext.mc_edi; 687 regs->tf_rsi = ucp->uc_mcontext.mc_esi; 688 regs->tf_rbp = ucp->uc_mcontext.mc_ebp; 689 regs->tf_rbx = ucp->uc_mcontext.mc_ebx; 690 regs->tf_rdx = ucp->uc_mcontext.mc_edx; 691 regs->tf_rcx = ucp->uc_mcontext.mc_ecx; 692 regs->tf_rax = ucp->uc_mcontext.mc_eax; 693 regs->tf_trapno = ucp->uc_mcontext.mc_trapno; 694 regs->tf_err = ucp->uc_mcontext.mc_err; 695 regs->tf_rip = ucp->uc_mcontext.mc_eip; 696 regs->tf_cs = cs; 697 regs->tf_rflags = ucp->uc_mcontext.mc_eflags; 698 regs->tf_rsp = ucp->uc_mcontext.mc_esp; 699 regs->tf_ss = ucp->uc_mcontext.mc_ss; 700 regs->tf_ds = ucp->uc_mcontext.mc_ds; 701 regs->tf_es = ucp->uc_mcontext.mc_es; 702 regs->tf_fs = ucp->uc_mcontext.mc_fs; 703 regs->tf_gs = ucp->uc_mcontext.mc_gs; 704 regs->tf_flags = TF_HASSEGS; 705 706 kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0); 707 set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 708 return (EJUSTRETURN); 709} 710 711/* 712 * Clear registers on exec 713 */ 714void 715ia32_setregs(struct thread *td, struct image_params *imgp, u_long stack) 716{ 717 struct trapframe *regs = td->td_frame; 718 struct pcb *pcb = td->td_pcb; 719 720 mtx_lock(&dt_lock); 721 if (td->td_proc->p_md.md_ldt != NULL) 722 user_ldt_free(td); 723 else 724 mtx_unlock(&dt_lock); 725 726 pcb->pcb_fsbase = 0; 727 pcb->pcb_gsbase = 0; 728 pcb->pcb_initial_fpucw = __INITIAL_FPUCW_I386__; 729 730 bzero((char *)regs, sizeof(struct trapframe)); 731 regs->tf_rip = imgp->entry_addr; 732 regs->tf_rsp = stack; 733 regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T); 734 regs->tf_ss = _udatasel; 735 regs->tf_cs = _ucode32sel; 736 regs->tf_rbx = imgp->ps_strings; 737 regs->tf_ds = _udatasel; 738 regs->tf_es = _udatasel; 739 regs->tf_fs = _ufssel; 740 regs->tf_gs = _ugssel; 741 regs->tf_flags = TF_HASSEGS; 742 743 load_cr0(rcr0() | CR0_MP | CR0_TS); 744 fpstate_drop(td); 745 746 /* Return via doreti so that we can change to a different %cs */ 747 set_pcb_flags(pcb, PCB_32BIT | PCB_FULL_IRET); 748 clear_pcb_flags(pcb, PCB_GS32BIT); 749 td->td_retval[1] = 0; 750} 751