1 /*- 2 * Copyright (c) 2003 Peter Wemm 3 * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * William Jolitz. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include <sys/cdefs.h> 35 __FBSDID("$FreeBSD$"); 36 37 #include "opt_compat.h" 38 39 #include <sys/param.h> 40 #include <sys/exec.h> 41 #include <sys/fcntl.h> 42 #include <sys/imgact.h> 43 #include <sys/kernel.h> 44 #include <sys/lock.h> 45 #include <sys/malloc.h> 46 #include <sys/mutex.h> 47 #include <sys/mman.h> 48 #include <sys/namei.h> 49 #include <sys/pioctl.h> 50 #include <sys/proc.h> 51 #include <sys/procfs.h> 52 #include <sys/resourcevar.h> 53 #include <sys/systm.h> 54 #include <sys/signalvar.h> 55 #include <sys/stat.h> 56 #include <sys/sx.h> 57 #include <sys/syscall.h> 58 #include <sys/syscallsubr.h> 59 #include <sys/sysctl.h> 60 #include <sys/sysent.h> 61 #include <sys/vnode.h> 62 63 #include <vm/vm.h> 64 #include <vm/vm_kern.h> 65 #include <vm/vm_param.h> 66 #include <vm/pmap.h> 67 #include <vm/vm_map.h> 68 #include <vm/vm_object.h> 69 #include <vm/vm_extern.h> 70 71 #include <compat/freebsd32/freebsd32_signal.h> 72 #include <compat/freebsd32/freebsd32_util.h> 73 #include <compat/freebsd32/freebsd32_proto.h> 74 #include <compat/ia32/ia32_signal.h> 75 #include <machine/psl.h> 76 #include <machine/segments.h> 77 #include <machine/specialreg.h> 78 #include <machine/frame.h> 79 #include <machine/md_var.h> 80 #include <machine/pcb.h> 81 #include <machine/cpufunc.h> 82 83 #ifdef COMPAT_FREEBSD4 84 static void freebsd4_ia32_sendsig(sig_t, ksiginfo_t *, sigset_t *); 85 #endif 86 static void ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp); 87 static int ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp); 88 89 #define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) 90 #define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) 91 92 static void 93 ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp) 94 { 95 96 /* 97 * XXX Format of 64bit and 32bit FXSAVE areas differs. FXSAVE 98 * in 32bit mode saves %cs and %ds, while on 64bit it saves 99 * 64bit instruction and data pointers. Ignore the difference 100 * for now, it should be irrelevant for most applications. 101 */ 102 mcp->mc_ownedfp = fpugetuserregs(td, 103 (struct savefpu *)&mcp->mc_fpstate); 104 mcp->mc_fpformat = fpuformat(); 105 } 106 107 static int 108 ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp) 109 { 110 111 if (mcp->mc_fpformat == _MC_FPFMT_NODEV) 112 return (0); 113 else if (mcp->mc_fpformat != _MC_FPFMT_XMM) 114 return (EINVAL); 115 else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) 116 /* We don't care what state is left in the FPU or PCB. */ 117 fpstate_drop(td); 118 else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU || 119 mcp->mc_ownedfp == _MC_FPOWNED_PCB) { 120 fpusetuserregs(td, (struct savefpu *)&mcp->mc_fpstate); 121 } else 122 return (EINVAL); 123 return (0); 124 } 125 126 /* 127 * Get machine context. 128 */ 129 static int 130 ia32_get_mcontext(struct thread *td, struct ia32_mcontext *mcp, int flags) 131 { 132 struct trapframe *tp; 133 134 tp = td->td_frame; 135 136 PROC_LOCK(curthread->td_proc); 137 mcp->mc_onstack = sigonstack(tp->tf_rsp); 138 PROC_UNLOCK(curthread->td_proc); 139 /* Entry into kernel always sets TF_HASSEGS */ 140 mcp->mc_gs = tp->tf_gs; 141 mcp->mc_fs = tp->tf_fs; 142 mcp->mc_es = tp->tf_es; 143 mcp->mc_ds = tp->tf_ds; 144 mcp->mc_edi = tp->tf_rdi; 145 mcp->mc_esi = tp->tf_rsi; 146 mcp->mc_ebp = tp->tf_rbp; 147 mcp->mc_isp = tp->tf_rsp; 148 mcp->mc_eflags = tp->tf_rflags; 149 if (flags & GET_MC_CLEAR_RET) { 150 mcp->mc_eax = 0; 151 mcp->mc_edx = 0; 152 mcp->mc_eflags &= ~PSL_C; 153 } else { 154 mcp->mc_eax = tp->tf_rax; 155 mcp->mc_edx = tp->tf_rdx; 156 } 157 mcp->mc_ebx = tp->tf_rbx; 158 mcp->mc_ecx = tp->tf_rcx; 159 mcp->mc_eip = tp->tf_rip; 160 mcp->mc_cs = tp->tf_cs; 161 mcp->mc_esp = tp->tf_rsp; 162 mcp->mc_ss = tp->tf_ss; 163 mcp->mc_len = sizeof(*mcp); 164 ia32_get_fpcontext(td, mcp); 165 mcp->mc_fsbase = td->td_pcb->pcb_fsbase; 166 mcp->mc_gsbase = td->td_pcb->pcb_gsbase; 167 td->td_pcb->pcb_full_iret = 1; 168 return (0); 169 } 170 171 /* 172 * Set machine context. 173 * 174 * However, we don't set any but the user modifiable flags, and we won't 175 * touch the cs selector. 176 */ 177 static int 178 ia32_set_mcontext(struct thread *td, const struct ia32_mcontext *mcp) 179 { 180 struct trapframe *tp; 181 long rflags; 182 int ret; 183 184 tp = td->td_frame; 185 if (mcp->mc_len != sizeof(*mcp)) 186 return (EINVAL); 187 rflags = (mcp->mc_eflags & PSL_USERCHANGE) | 188 (tp->tf_rflags & ~PSL_USERCHANGE); 189 ret = ia32_set_fpcontext(td, mcp); 190 if (ret != 0) 191 return (ret); 192 tp->tf_gs = mcp->mc_gs; 193 tp->tf_fs = mcp->mc_fs; 194 tp->tf_es = mcp->mc_es; 195 tp->tf_ds = mcp->mc_ds; 196 tp->tf_flags = TF_HASSEGS; 197 tp->tf_rdi = mcp->mc_edi; 198 tp->tf_rsi = mcp->mc_esi; 199 tp->tf_rbp = mcp->mc_ebp; 200 tp->tf_rbx = mcp->mc_ebx; 201 tp->tf_rdx = mcp->mc_edx; 202 tp->tf_rcx = mcp->mc_ecx; 203 tp->tf_rax = mcp->mc_eax; 204 /* trapno, err */ 205 tp->tf_rip = mcp->mc_eip; 206 tp->tf_rflags = rflags; 207 tp->tf_rsp = mcp->mc_esp; 208 tp->tf_ss = mcp->mc_ss; 209 td->td_pcb->pcb_flags |= PCB_FULLCTX; 210 td->td_pcb->pcb_full_iret = 1; 211 return (0); 212 } 213 214 /* 215 * The first two fields of a ucontext_t are the signal mask and 216 * the machine context. The next field is uc_link; we want to 217 * avoid destroying the link when copying out contexts. 218 */ 219 #define UC_COPY_SIZE offsetof(struct ia32_ucontext, uc_link) 220 221 int 222 freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap) 223 { 224 struct ia32_ucontext uc; 225 int ret; 226 227 if (uap->ucp == NULL) 228 ret = EINVAL; 229 else { 230 ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 231 PROC_LOCK(td->td_proc); 232 uc.uc_sigmask = td->td_sigmask; 233 PROC_UNLOCK(td->td_proc); 234 ret = copyout(&uc, uap->ucp, UC_COPY_SIZE); 235 } 236 return (ret); 237 } 238 239 int 240 freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap) 241 { 242 struct ia32_ucontext uc; 243 int ret; 244 245 if (uap->ucp == NULL) 246 ret = EINVAL; 247 else { 248 ret = copyin(uap->ucp, &uc, UC_COPY_SIZE); 249 if (ret == 0) { 250 ret = ia32_set_mcontext(td, &uc.uc_mcontext); 251 if (ret == 0) { 252 kern_sigprocmask(td, SIG_SETMASK, 253 &uc.uc_sigmask, NULL, 0); 254 } 255 } 256 } 257 return (ret == 0 ? EJUSTRETURN : ret); 258 } 259 260 int 261 freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap) 262 { 263 struct ia32_ucontext uc; 264 int ret; 265 266 if (uap->oucp == NULL || uap->ucp == NULL) 267 ret = EINVAL; 268 else { 269 ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 270 PROC_LOCK(td->td_proc); 271 uc.uc_sigmask = td->td_sigmask; 272 PROC_UNLOCK(td->td_proc); 273 ret = copyout(&uc, uap->oucp, UC_COPY_SIZE); 274 if (ret == 0) { 275 ret = copyin(uap->ucp, &uc, UC_COPY_SIZE); 276 if (ret == 0) { 277 ret = ia32_set_mcontext(td, &uc.uc_mcontext); 278 if (ret == 0) { 279 kern_sigprocmask(td, SIG_SETMASK, 280 &uc.uc_sigmask, NULL, 0); 281 } 282 } 283 } 284 } 285 return (ret == 0 ? EJUSTRETURN : ret); 286 } 287 288 /* 289 * Send an interrupt to process. 290 * 291 * Stack is set up to allow sigcode stored 292 * at top to call routine, followed by kcall 293 * to sigreturn routine below. After sigreturn 294 * resets the signal mask, the stack, and the 295 * frame pointer, it returns to the user 296 * specified pc, psl. 297 */ 298 #ifdef COMPAT_FREEBSD4 299 static void 300 freebsd4_ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 301 { 302 struct ia32_sigframe4 sf, *sfp; 303 struct siginfo32 siginfo; 304 struct proc *p; 305 struct thread *td; 306 struct sigacts *psp; 307 struct trapframe *regs; 308 int oonstack; 309 int sig; 310 311 td = curthread; 312 p = td->td_proc; 313 siginfo_to_siginfo32(&ksi->ksi_info, &siginfo); 314 315 PROC_LOCK_ASSERT(p, MA_OWNED); 316 sig = siginfo.si_signo; 317 psp = p->p_sigacts; 318 mtx_assert(&psp->ps_mtx, MA_OWNED); 319 regs = td->td_frame; 320 oonstack = sigonstack(regs->tf_rsp); 321 322 /* Save user context. */ 323 bzero(&sf, sizeof(sf)); 324 sf.sf_uc.uc_sigmask = *mask; 325 sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp; 326 sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size; 327 sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) 328 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 329 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 330 sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi; 331 sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi; 332 sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp; 333 sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */ 334 sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx; 335 sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx; 336 sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx; 337 sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax; 338 sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno; 339 sf.sf_uc.uc_mcontext.mc_err = regs->tf_err; 340 sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip; 341 sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs; 342 sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags; 343 sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp; 344 sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss; 345 sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds; 346 sf.sf_uc.uc_mcontext.mc_es = regs->tf_es; 347 sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs; 348 sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs; 349 350 /* Allocate space for the signal handler context. */ 351 if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 352 SIGISMEMBER(psp->ps_sigonstack, sig)) { 353 sfp = (struct ia32_sigframe4 *)(td->td_sigstk.ss_sp + 354 td->td_sigstk.ss_size - sizeof(sf)); 355 } else 356 sfp = (struct ia32_sigframe4 *)regs->tf_rsp - 1; 357 PROC_UNLOCK(p); 358 359 /* Translate the signal if appropriate. */ 360 if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 361 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 362 363 /* Build the argument list for the signal handler. */ 364 sf.sf_signum = sig; 365 sf.sf_ucontext = (register_t)&sfp->sf_uc; 366 if (SIGISMEMBER(psp->ps_siginfo, sig)) { 367 /* Signal handler installed with SA_SIGINFO. */ 368 sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si; 369 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 370 371 /* Fill in POSIX parts */ 372 sf.sf_si = siginfo; 373 sf.sf_si.si_signo = sig; 374 } else { 375 /* Old FreeBSD-style arguments. */ 376 sf.sf_siginfo = siginfo.si_code; 377 sf.sf_addr = (u_int32_t)siginfo.si_addr; 378 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 379 } 380 mtx_unlock(&psp->ps_mtx); 381 382 /* 383 * Copy the sigframe out to the user's stack. 384 */ 385 if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { 386 #ifdef DEBUG 387 printf("process %ld has trashed its stack\n", (long)p->p_pid); 388 #endif 389 PROC_LOCK(p); 390 sigexit(td, SIGILL); 391 } 392 393 regs->tf_rsp = (uintptr_t)sfp; 394 regs->tf_rip = FREEBSD32_PS_STRINGS - sz_freebsd4_ia32_sigcode; 395 regs->tf_rflags &= ~(PSL_T | PSL_D); 396 regs->tf_cs = _ucode32sel; 397 regs->tf_ss = _udatasel; 398 regs->tf_ds = _udatasel; 399 regs->tf_es = _udatasel; 400 td->td_pcb->pcb_full_iret = 1; 401 /* leave user %fs and %gs untouched */ 402 PROC_LOCK(p); 403 mtx_lock(&psp->ps_mtx); 404 } 405 #endif /* COMPAT_FREEBSD4 */ 406 407 void 408 ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 409 { 410 struct ia32_sigframe sf, *sfp; 411 struct siginfo32 siginfo; 412 struct proc *p; 413 struct thread *td; 414 struct sigacts *psp; 415 char *sp; 416 struct trapframe *regs; 417 int oonstack; 418 int sig; 419 420 siginfo_to_siginfo32(&ksi->ksi_info, &siginfo); 421 td = curthread; 422 p = td->td_proc; 423 PROC_LOCK_ASSERT(p, MA_OWNED); 424 sig = siginfo.si_signo; 425 psp = p->p_sigacts; 426 #ifdef COMPAT_FREEBSD4 427 if (SIGISMEMBER(psp->ps_freebsd4, sig)) { 428 freebsd4_ia32_sendsig(catcher, ksi, mask); 429 return; 430 } 431 #endif 432 mtx_assert(&psp->ps_mtx, MA_OWNED); 433 regs = td->td_frame; 434 oonstack = sigonstack(regs->tf_rsp); 435 436 /* Save user context. */ 437 bzero(&sf, sizeof(sf)); 438 sf.sf_uc.uc_sigmask = *mask; 439 sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp; 440 sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size; 441 sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) 442 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 443 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 444 sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi; 445 sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi; 446 sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp; 447 sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */ 448 sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx; 449 sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx; 450 sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx; 451 sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax; 452 sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno; 453 sf.sf_uc.uc_mcontext.mc_err = regs->tf_err; 454 sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip; 455 sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs; 456 sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags; 457 sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp; 458 sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss; 459 sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds; 460 sf.sf_uc.uc_mcontext.mc_es = regs->tf_es; 461 sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs; 462 sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs; 463 sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */ 464 ia32_get_fpcontext(td, &sf.sf_uc.uc_mcontext); 465 fpstate_drop(td); 466 sf.sf_uc.uc_mcontext.mc_fsbase = td->td_pcb->pcb_fsbase; 467 sf.sf_uc.uc_mcontext.mc_gsbase = td->td_pcb->pcb_gsbase; 468 469 /* Allocate space for the signal handler context. */ 470 if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 471 SIGISMEMBER(psp->ps_sigonstack, sig)) { 472 sp = td->td_sigstk.ss_sp + 473 td->td_sigstk.ss_size - sizeof(sf); 474 } else 475 sp = (char *)regs->tf_rsp - sizeof(sf); 476 /* Align to 16 bytes. */ 477 sfp = (struct ia32_sigframe *)((uintptr_t)sp & ~0xF); 478 PROC_UNLOCK(p); 479 480 /* Translate the signal if appropriate. */ 481 if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 482 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 483 484 /* Build the argument list for the signal handler. */ 485 sf.sf_signum = sig; 486 sf.sf_ucontext = (register_t)&sfp->sf_uc; 487 if (SIGISMEMBER(psp->ps_siginfo, sig)) { 488 /* Signal handler installed with SA_SIGINFO. */ 489 sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si; 490 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 491 492 /* Fill in POSIX parts */ 493 sf.sf_si = siginfo; 494 sf.sf_si.si_signo = sig; 495 } else { 496 /* Old FreeBSD-style arguments. */ 497 sf.sf_siginfo = siginfo.si_code; 498 sf.sf_addr = (u_int32_t)siginfo.si_addr; 499 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 500 } 501 mtx_unlock(&psp->ps_mtx); 502 503 /* 504 * Copy the sigframe out to the user's stack. 505 */ 506 if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { 507 #ifdef DEBUG 508 printf("process %ld has trashed its stack\n", (long)p->p_pid); 509 #endif 510 PROC_LOCK(p); 511 sigexit(td, SIGILL); 512 } 513 514 regs->tf_rsp = (uintptr_t)sfp; 515 regs->tf_rip = FREEBSD32_PS_STRINGS - *(p->p_sysent->sv_szsigcode); 516 regs->tf_rflags &= ~(PSL_T | PSL_D); 517 regs->tf_cs = _ucode32sel; 518 regs->tf_ss = _udatasel; 519 regs->tf_ds = _udatasel; 520 regs->tf_es = _udatasel; 521 td->td_pcb->pcb_full_iret = 1; 522 /* XXXKIB leave user %fs and %gs untouched */ 523 PROC_LOCK(p); 524 mtx_lock(&psp->ps_mtx); 525 } 526 527 /* 528 * System call to cleanup state after a signal 529 * has been taken. Reset signal mask and 530 * stack state from context left by sendsig (above). 531 * Return to previous pc and psl as specified by 532 * context left by sendsig. Check carefully to 533 * make sure that the user has not modified the 534 * state to gain improper privileges. 535 */ 536 #ifdef COMPAT_FREEBSD4 537 /* 538 * MPSAFE 539 */ 540 int 541 freebsd4_freebsd32_sigreturn(td, uap) 542 struct thread *td; 543 struct freebsd4_freebsd32_sigreturn_args /* { 544 const struct freebsd4_freebsd32_ucontext *sigcntxp; 545 } */ *uap; 546 { 547 struct ia32_ucontext4 uc; 548 struct trapframe *regs; 549 struct ia32_ucontext4 *ucp; 550 int cs, eflags, error; 551 ksiginfo_t ksi; 552 553 error = copyin(uap->sigcntxp, &uc, sizeof(uc)); 554 if (error != 0) 555 return (error); 556 ucp = &uc; 557 regs = td->td_frame; 558 eflags = ucp->uc_mcontext.mc_eflags; 559 /* 560 * Don't allow users to change privileged or reserved flags. 561 */ 562 /* 563 * XXX do allow users to change the privileged flag PSL_RF. 564 * The cpu sets PSL_RF in tf_eflags for faults. Debuggers 565 * should sometimes set it there too. tf_eflags is kept in 566 * the signal context during signal handling and there is no 567 * other place to remember it, so the PSL_RF bit may be 568 * corrupted by the signal handler without us knowing. 569 * Corruption of the PSL_RF bit at worst causes one more or 570 * one less debugger trap, so allowing it is fairly harmless. 571 */ 572 if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) { 573 uprintf("pid %d (%s): freebsd4_freebsd32_sigreturn eflags = 0x%x\n", 574 td->td_proc->p_pid, td->td_name, eflags); 575 return (EINVAL); 576 } 577 578 /* 579 * Don't allow users to load a valid privileged %cs. Let the 580 * hardware check for invalid selectors, excess privilege in 581 * other selectors, invalid %eip's and invalid %esp's. 582 */ 583 cs = ucp->uc_mcontext.mc_cs; 584 if (!CS_SECURE(cs)) { 585 uprintf("pid %d (%s): freebsd4_sigreturn cs = 0x%x\n", 586 td->td_proc->p_pid, td->td_name, cs); 587 ksiginfo_init_trap(&ksi); 588 ksi.ksi_signo = SIGBUS; 589 ksi.ksi_code = BUS_OBJERR; 590 ksi.ksi_trapno = T_PROTFLT; 591 ksi.ksi_addr = (void *)regs->tf_rip; 592 trapsignal(td, &ksi); 593 return (EINVAL); 594 } 595 596 regs->tf_rdi = ucp->uc_mcontext.mc_edi; 597 regs->tf_rsi = ucp->uc_mcontext.mc_esi; 598 regs->tf_rbp = ucp->uc_mcontext.mc_ebp; 599 regs->tf_rbx = ucp->uc_mcontext.mc_ebx; 600 regs->tf_rdx = ucp->uc_mcontext.mc_edx; 601 regs->tf_rcx = ucp->uc_mcontext.mc_ecx; 602 regs->tf_rax = ucp->uc_mcontext.mc_eax; 603 regs->tf_trapno = ucp->uc_mcontext.mc_trapno; 604 regs->tf_err = ucp->uc_mcontext.mc_err; 605 regs->tf_rip = ucp->uc_mcontext.mc_eip; 606 regs->tf_cs = cs; 607 regs->tf_rflags = ucp->uc_mcontext.mc_eflags; 608 regs->tf_rsp = ucp->uc_mcontext.mc_esp; 609 regs->tf_ss = ucp->uc_mcontext.mc_ss; 610 regs->tf_ds = ucp->uc_mcontext.mc_ds; 611 regs->tf_es = ucp->uc_mcontext.mc_es; 612 regs->tf_fs = ucp->uc_mcontext.mc_fs; 613 regs->tf_gs = ucp->uc_mcontext.mc_gs; 614 615 kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0); 616 td->td_pcb->pcb_full_iret = 1; 617 return (EJUSTRETURN); 618 } 619 #endif /* COMPAT_FREEBSD4 */ 620 621 /* 622 * MPSAFE 623 */ 624 int 625 freebsd32_sigreturn(td, uap) 626 struct thread *td; 627 struct freebsd32_sigreturn_args /* { 628 const struct freebsd32_ucontext *sigcntxp; 629 } */ *uap; 630 { 631 struct ia32_ucontext uc; 632 struct trapframe *regs; 633 struct ia32_ucontext *ucp; 634 int cs, eflags, error, ret; 635 ksiginfo_t ksi; 636 637 error = copyin(uap->sigcntxp, &uc, sizeof(uc)); 638 if (error != 0) 639 return (error); 640 ucp = &uc; 641 regs = td->td_frame; 642 eflags = ucp->uc_mcontext.mc_eflags; 643 /* 644 * Don't allow users to change privileged or reserved flags. 645 */ 646 /* 647 * XXX do allow users to change the privileged flag PSL_RF. 648 * The cpu sets PSL_RF in tf_eflags for faults. Debuggers 649 * should sometimes set it there too. tf_eflags is kept in 650 * the signal context during signal handling and there is no 651 * other place to remember it, so the PSL_RF bit may be 652 * corrupted by the signal handler without us knowing. 653 * Corruption of the PSL_RF bit at worst causes one more or 654 * one less debugger trap, so allowing it is fairly harmless. 655 */ 656 if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) { 657 uprintf("pid %d (%s): freebsd32_sigreturn eflags = 0x%x\n", 658 td->td_proc->p_pid, td->td_name, eflags); 659 return (EINVAL); 660 } 661 662 /* 663 * Don't allow users to load a valid privileged %cs. Let the 664 * hardware check for invalid selectors, excess privilege in 665 * other selectors, invalid %eip's and invalid %esp's. 666 */ 667 cs = ucp->uc_mcontext.mc_cs; 668 if (!CS_SECURE(cs)) { 669 uprintf("pid %d (%s): sigreturn cs = 0x%x\n", 670 td->td_proc->p_pid, td->td_name, cs); 671 ksiginfo_init_trap(&ksi); 672 ksi.ksi_signo = SIGBUS; 673 ksi.ksi_code = BUS_OBJERR; 674 ksi.ksi_trapno = T_PROTFLT; 675 ksi.ksi_addr = (void *)regs->tf_rip; 676 trapsignal(td, &ksi); 677 return (EINVAL); 678 } 679 680 ret = ia32_set_fpcontext(td, &ucp->uc_mcontext); 681 if (ret != 0) 682 return (ret); 683 684 regs->tf_rdi = ucp->uc_mcontext.mc_edi; 685 regs->tf_rsi = ucp->uc_mcontext.mc_esi; 686 regs->tf_rbp = ucp->uc_mcontext.mc_ebp; 687 regs->tf_rbx = ucp->uc_mcontext.mc_ebx; 688 regs->tf_rdx = ucp->uc_mcontext.mc_edx; 689 regs->tf_rcx = ucp->uc_mcontext.mc_ecx; 690 regs->tf_rax = ucp->uc_mcontext.mc_eax; 691 regs->tf_trapno = ucp->uc_mcontext.mc_trapno; 692 regs->tf_err = ucp->uc_mcontext.mc_err; 693 regs->tf_rip = ucp->uc_mcontext.mc_eip; 694 regs->tf_cs = cs; 695 regs->tf_rflags = ucp->uc_mcontext.mc_eflags; 696 regs->tf_rsp = ucp->uc_mcontext.mc_esp; 697 regs->tf_ss = ucp->uc_mcontext.mc_ss; 698 regs->tf_ds = ucp->uc_mcontext.mc_ds; 699 regs->tf_es = ucp->uc_mcontext.mc_es; 700 regs->tf_fs = ucp->uc_mcontext.mc_fs; 701 regs->tf_gs = ucp->uc_mcontext.mc_gs; 702 regs->tf_flags = TF_HASSEGS; 703 704 kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0); 705 td->td_pcb->pcb_full_iret = 1; 706 return (EJUSTRETURN); 707 } 708 709 /* 710 * Clear registers on exec 711 */ 712 void 713 ia32_setregs(struct thread *td, struct image_params *imgp, u_long stack) 714 { 715 struct trapframe *regs = td->td_frame; 716 struct pcb *pcb = td->td_pcb; 717 718 mtx_lock(&dt_lock); 719 if (td->td_proc->p_md.md_ldt != NULL) 720 user_ldt_free(td); 721 else 722 mtx_unlock(&dt_lock); 723 724 pcb->pcb_fsbase = 0; 725 pcb->pcb_gsbase = 0; 726 pcb->pcb_initial_fpucw = __INITIAL_FPUCW_I386__; 727 728 bzero((char *)regs, sizeof(struct trapframe)); 729 regs->tf_rip = imgp->entry_addr; 730 regs->tf_rsp = stack; 731 regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T); 732 regs->tf_ss = _udatasel; 733 regs->tf_cs = _ucode32sel; 734 regs->tf_rbx = imgp->ps_strings; 735 regs->tf_ds = _udatasel; 736 regs->tf_es = _udatasel; 737 regs->tf_fs = _ufssel; 738 regs->tf_gs = _ugssel; 739 regs->tf_flags = TF_HASSEGS; 740 741 load_cr0(rcr0() | CR0_MP | CR0_TS); 742 fpstate_drop(td); 743 744 /* Return via doreti so that we can change to a different %cs */ 745 pcb->pcb_flags |= PCB_FULLCTX | PCB_32BIT; 746 pcb->pcb_flags &= ~PCB_GS32BIT; 747 td->td_pcb->pcb_full_iret = 1; 748 td->td_retval[1] = 0; 749 } 750