int set_regs(struct lwp *lp, struct reg *regs) { struct trapframe *tp; tp = lp->lwp_md.md_regs; if (!EFL_SECURE(regs->r_eflags, tp->tf_eflags) || !CS_SECURE(regs->r_cs)) return (EINVAL); tp->tf_gs = regs->r_gs; tp->tf_fs = regs->r_fs; tp->tf_es = regs->r_es; tp->tf_ds = regs->r_ds; tp->tf_edi = regs->r_edi; tp->tf_esi = regs->r_esi; tp->tf_ebp = regs->r_ebp; tp->tf_ebx = regs->r_ebx; tp->tf_edx = regs->r_edx; tp->tf_ecx = regs->r_ecx; tp->tf_eax = regs->r_eax; tp->tf_eip = regs->r_eip; tp->tf_cs = regs->r_cs; tp->tf_eflags = regs->r_eflags; tp->tf_esp = regs->r_esp; tp->tf_ss = regs->r_ss; return (0); }
int set_regs32(struct thread *td, struct reg32 *regs) { struct pcb *pcb; struct trapframe *tp; tp = td->td_frame; if (!EFL_SECURE(regs->r_eflags, tp->tf_rflags) || !CS_SECURE(regs->r_cs)) return (EINVAL); pcb = td->td_pcb; tp->tf_gs = regs->r_gs; tp->tf_fs = regs->r_fs; tp->tf_es = regs->r_es; tp->tf_ds = regs->r_ds; set_pcb_flags(pcb, PCB_FULL_IRET); tp->tf_flags = TF_HASSEGS; tp->tf_rdi = regs->r_edi; tp->tf_rsi = regs->r_esi; tp->tf_rbp = regs->r_ebp; tp->tf_rbx = regs->r_ebx; tp->tf_rdx = regs->r_edx; tp->tf_rcx = regs->r_ecx; tp->tf_rax = regs->r_eax; tp->tf_rip = regs->r_eip; tp->tf_cs = regs->r_cs; tp->tf_rflags = regs->r_eflags; tp->tf_rsp = regs->r_esp; tp->tf_ss = regs->r_ss; return (0); }
int ofreebsd32_sigreturn(struct thread *td, struct ofreebsd32_sigreturn_args *uap) { struct ia32_sigcontext3 sc, *scp; struct trapframe *regs; int eflags, error; ksiginfo_t ksi; regs = td->td_frame; error = copyin(uap->sigcntxp, &sc, sizeof(sc)); if (error != 0) return (error); scp = ≻ eflags = scp->sc_eflags; if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) { return (EINVAL); } if (!CS_SECURE(scp->sc_cs)) { ksiginfo_init_trap(&ksi); ksi.ksi_signo = SIGBUS; ksi.ksi_code = BUS_OBJERR; ksi.ksi_trapno = T_PROTFLT; ksi.ksi_addr = (void *)regs->tf_rip; trapsignal(td, &ksi); return (EINVAL); } regs->tf_ds = scp->sc_ds; regs->tf_es = scp->sc_es; regs->tf_fs = scp->sc_fs; regs->tf_gs = scp->sc_gs; regs->tf_rax = scp->sc_eax; regs->tf_rbx = scp->sc_ebx; regs->tf_rcx = scp->sc_ecx; regs->tf_rdx = scp->sc_edx; regs->tf_rsi = scp->sc_esi; regs->tf_rdi = scp->sc_edi; regs->tf_cs = scp->sc_cs; regs->tf_ss = scp->sc_ss; regs->tf_rbp = scp->sc_ebp; regs->tf_rsp = scp->sc_esp; regs->tf_rip = scp->sc_eip; regs->tf_rflags = eflags; if (scp->sc_onstack & 1) td->td_sigstk.ss_flags |= SS_ONSTACK; else td->td_sigstk.ss_flags &= ~SS_ONSTACK; kern_sigprocmask(td, SIG_SETMASK, (sigset_t *)&scp->sc_mask, NULL, SIGPROCMASK_OLD); set_pcb_flags(td->td_pcb, PCB_FULL_IRET); return (EJUSTRETURN); }
int sys_sigreturn(struct sigreturn_args *uap) { struct lwp *lp = curthread->td_lwp; struct trapframe *regs; ucontext_t ucp; int cs; int eflags; int error; error = copyin(uap->sigcntxp, &ucp, sizeof(ucp)); if (error) return (error); regs = lp->lwp_md.md_regs; eflags = ucp.uc_mcontext.mc_eflags; #if 0 if (eflags & PSL_VM) { struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs; struct vm86_kernel *vm86; /* * if pcb_ext == 0 or vm86_inited == 0, the user hasn't * set up the vm86 area, and we can't enter vm86 mode. */ if (lp->lwp_thread->td_pcb->pcb_ext == 0) return (EINVAL); vm86 = &lp->lwp_thread->td_pcb->pcb_ext->ext_vm86; if (vm86->vm86_inited == 0) return (EINVAL); /* go back to user mode if both flags are set */ if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) trapsignal(lp->lwp_proc, SIGBUS, 0); if (vm86->vm86_has_vme) { eflags = (tf->tf_eflags & ~VME_USERCHANGE) | (eflags & VME_USERCHANGE) | PSL_VM; } else { vm86->vm86_eflags = eflags; /* save VIF, VIP */ eflags = (tf->tf_eflags & ~VM_USERCHANGE) | (eflags & VM_USERCHANGE) | PSL_VM; } bcopy(&ucp.uc_mcontext.mc_gs, tf, sizeof(struct trapframe)); tf->tf_eflags = eflags; tf->tf_vm86_ds = tf->tf_ds; tf->tf_vm86_es = tf->tf_es; tf->tf_vm86_fs = tf->tf_fs; tf->tf_vm86_gs = tf->tf_gs; tf->tf_ds = _udatasel; tf->tf_es = _udatasel; #if 0 tf->tf_fs = _udatasel; tf->tf_gs = _udatasel; #endif } else #endif { /* * Don't allow users to change privileged or reserved flags. */ /* * XXX do allow users to change the privileged flag PSL_RF. * The cpu sets PSL_RF in tf_eflags for faults. Debuggers * should sometimes set it there too. tf_eflags is kept in * the signal context during signal handling and there is no * other place to remember it, so the PSL_RF bit may be * corrupted by the signal handler without us knowing. * Corruption of the PSL_RF bit at worst causes one more or * one less debugger trap, so allowing it is fairly harmless. */ if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) { kprintf("sigreturn: eflags = 0x%x\n", eflags); return(EINVAL); } /* * Don't allow users to load a valid privileged %cs. Let the * hardware check for invalid selectors, excess privilege in * other selectors, invalid %eip's and invalid %esp's. */ cs = ucp.uc_mcontext.mc_cs; if (!CS_SECURE(cs)) { kprintf("sigreturn: cs = 0x%x\n", cs); trapsignal(lp, SIGBUS, T_PROTFLT); return(EINVAL); } bcopy(&ucp.uc_mcontext.mc_gs, regs, sizeof(struct trapframe)); } /* * Restore the FPU state from the frame */ crit_enter(); npxpop(&ucp.uc_mcontext); if (ucp.uc_mcontext.mc_onstack & 1) lp->lwp_sigstk.ss_flags |= SS_ONSTACK; else lp->lwp_sigstk.ss_flags &= ~SS_ONSTACK; lp->lwp_sigmask = ucp.uc_sigmask; SIG_CANTMASK(lp->lwp_sigmask); crit_exit(); return(EJUSTRETURN); }