From 82d2a417f9f83101d1887aa1f696d8855b15cb8e Mon Sep 17 00:00:00 2001 From: marcel Date: Thu, 7 Oct 1999 12:40:34 +0000 Subject: Simplification of the signal trampoline and other cleanups. o Remove unused defines from genassym.c that were needed by the trampoline. o Add load_gs_param function to support.s that catches a fault when %gs is loaded with an invalid descriptor. The function returns EFAULT in that case. o Remove struct trapframe from mcontext_t and replace it with the list of registers. o Modify sendsig and sigreturn accordingly. This commit contains a patch by bde. Reviewed by: luoqi, jdp --- sys/amd64/amd64/genassym.c | 10 -------- sys/amd64/amd64/locore.S | 29 +++-------------------- sys/amd64/amd64/locore.s | 29 +++-------------------- sys/amd64/amd64/machdep.c | 56 ++++++++++++++++++++++---------------------- sys/amd64/amd64/support.S | 15 ++++++++++++ sys/amd64/amd64/support.s | 15 ++++++++++++ sys/amd64/include/md_var.h | 1 + sys/amd64/include/sigframe.h | 3 +-- sys/amd64/include/ucontext.h | 21 +++++++++++++++-- sys/i386/i386/genassym.c | 10 -------- sys/i386/i386/locore.s | 29 +++-------------------- sys/i386/i386/machdep.c | 56 ++++++++++++++++++++++---------------------- sys/i386/i386/support.s | 15 ++++++++++++ sys/i386/include/md_var.h | 1 + sys/i386/include/sigframe.h | 3 +-- sys/i386/include/ucontext.h | 21 +++++++++++++++-- 16 files changed, 152 insertions(+), 162 deletions(-) diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c index 8299177..b95a9a7 100644 --- a/sys/amd64/amd64/genassym.c +++ b/sys/amd64/amd64/genassym.c @@ -148,18 +148,8 @@ main() printf("#define\tTF_EFLAGS %#x\n", OS(trapframe, tf_eflags)); printf("#define\tSIGF_HANDLER %#x\n", OS(sigframe, sf_ahu.sf_handler)); - printf("#define\tSIGF_SIGRET %#x\n", OS(sigframe, sf_sigreturn)); - printf("#define\tSIGF_SC %#x\n", OS(osigframe, sf_siginfo.si_sc)); printf("#define\tSIGF_UC %#x\n", OS(sigframe, sf_uc)); - printf("#define\tSC_PS %#x\n", OS(osigcontext, sc_ps)); - printf("#define\tSC_FS %#x\n", OS(osigcontext, sc_fs)); - printf("#define\tSC_GS %#x\n", OS(osigcontext, sc_gs)); - - printf("#define\tUC_EFLAGS %#x\n", - OS(__ucontext, uc_mcontext.mc_tf.tf_eflags)); - printf("#define\tUC_GS %#x\n", OS(__ucontext, uc_mcontext.mc_gs)); - printf("#define\tB_READ %#x\n", B_READ); printf("#define\tENOENT %d\n", ENOENT); printf("#define\tEFAULT %d\n", EFAULT); diff --git a/sys/amd64/amd64/locore.S b/sys/amd64/amd64/locore.S index e87c275..a1b6ff7 100644 --- a/sys/amd64/amd64/locore.S +++ b/sys/amd64/amd64/locore.S @@ -415,37 +415,14 @@ NON_GPROF_ENTRY(prepare_usermode) */ NON_GPROF_ENTRY(sigcode) call SIGF_HANDLER(%esp) /* call signal handler */ - movl SIGF_SIGRET(%esp),%eax /* Get sigreturn cookie */ - cmpl $0x0ABCDEF0,%eax /* New one? */ - jne 3f -/* New signalling code */ - lea SIGF_UC(%esp),%eax /* get ucontext */ + lea SIGF_UC(%esp),%eax /* get ucontext_t */ pushl %eax - testl $PSL_VM,UC_EFLAGS(%eax) - jne 1f - movl UC_GS(%eax),%gs /* restore %gs */ -1: - movl $SYS_sigreturn,%eax - pushl %eax /* junk to fake return addr. */ - int $0x80 /* enter kernel with args */ - /* on stack */ -2: - jmp 2b -/* Old signalling code */ -3: - lea SIGF_SC(%esp),%eax /* get sigcontext */ - pushl %eax - testl $PSL_VM,SC_PS(%eax) - jne 4f - movl SC_GS(%eax),%gs /* restore %gs */ -4: movl $SYS_osigreturn,%eax pushl %eax /* junk to fake return addr. */ int $0x80 /* enter kernel with args */ /* on stack */ -5: - jmp 5b - +1: + jmp 1b ALIGN_TEXT _esigcode: diff --git a/sys/amd64/amd64/locore.s b/sys/amd64/amd64/locore.s index e87c275..a1b6ff7 100644 --- a/sys/amd64/amd64/locore.s +++ b/sys/amd64/amd64/locore.s @@ -415,37 +415,14 @@ NON_GPROF_ENTRY(prepare_usermode) */ NON_GPROF_ENTRY(sigcode) call SIGF_HANDLER(%esp) /* call signal handler */ - movl SIGF_SIGRET(%esp),%eax /* Get sigreturn cookie */ - cmpl $0x0ABCDEF0,%eax /* New one? */ - jne 3f -/* New signalling code */ - lea SIGF_UC(%esp),%eax /* get ucontext */ + lea SIGF_UC(%esp),%eax /* get ucontext_t */ pushl %eax - testl $PSL_VM,UC_EFLAGS(%eax) - jne 1f - movl UC_GS(%eax),%gs /* restore %gs */ -1: - movl $SYS_sigreturn,%eax - pushl %eax /* junk to fake return addr. */ - int $0x80 /* enter kernel with args */ - /* on stack */ -2: - jmp 2b -/* Old signalling code */ -3: - lea SIGF_SC(%esp),%eax /* get sigcontext */ - pushl %eax - testl $PSL_VM,SC_PS(%eax) - jne 4f - movl SC_GS(%eax),%gs /* restore %gs */ -4: movl $SYS_osigreturn,%eax pushl %eax /* junk to fake return addr. */ int $0x80 /* enter kernel with args */ /* on stack */ -5: - jmp 5b - +1: + jmp 1b ALIGN_TEXT _esigcode: diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 1ef6fb0..a682098 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -599,6 +599,7 @@ osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) regs->tf_ds = _udatasel; regs->tf_es = _udatasel; regs->tf_fs = _udatasel; + load_gs(_udatasel); regs->tf_ss = _udatasel; } @@ -631,8 +632,8 @@ sendsig(catcher, sig, mask, code) sf.sf_uc.uc_sigmask = *mask; sf.sf_uc.uc_stack = psp->ps_sigstk; sf.sf_uc.uc_mcontext.mc_onstack = onstack; - sf.sf_uc.uc_mcontext.mc_tf = *regs; sf.sf_uc.uc_mcontext.mc_gs = rgs(); + bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(struct trapframe)); /* Allocate and validate space for the signal handler context. */ if ((psp->ps_flags & SAS_ALTSTACK) != 0 && !onstack && @@ -702,12 +703,12 @@ sendsig(catcher, sig, mask, code) struct vm86_kernel *vm86 = &p->p_addr->u_pcb.pcb_ext->ext_vm86; sf.sf_uc.uc_mcontext.mc_gs = tf->tf_vm86_gs; - sf.sf_uc.uc_mcontext.mc_tf.tf_fs = tf->tf_vm86_fs; - sf.sf_uc.uc_mcontext.mc_tf.tf_es = tf->tf_vm86_es; - sf.sf_uc.uc_mcontext.mc_tf.tf_ds = tf->tf_vm86_ds; + sf.sf_uc.uc_mcontext.mc_fs = tf->tf_vm86_fs; + sf.sf_uc.uc_mcontext.mc_es = tf->tf_vm86_es; + sf.sf_uc.uc_mcontext.mc_ds = tf->tf_vm86_ds; if (vm86->vm86_has_vme == 0) - sf.sf_uc.uc_mcontext.mc_tf.tf_eflags = + sf.sf_uc.uc_mcontext.mc_eflags = (tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) | (vm86->vm86_eflags & (PSL_VIF | PSL_VIP)); @@ -725,8 +726,6 @@ sendsig(catcher, sig, mask, code) tf->tf_eflags &= ~(PSL_VM|PSL_NT|PSL_T|PSL_VIF|PSL_VIP); } - sf.sf_sigreturn = 0x0ABCDEF0; - /* * Copy the sigframe out to the user's stack. */ @@ -744,6 +743,7 @@ sendsig(catcher, sig, mask, code) regs->tf_ds = _udatasel; regs->tf_es = _udatasel; regs->tf_fs = _udatasel; + load_gs(_udatasel); regs->tf_ss = _udatasel; } @@ -767,21 +767,15 @@ osigreturn(p, uap) } */ *uap; { register struct osigcontext *scp; - register struct osigframe *fp; register struct trapframe *regs = p->p_md.md_regs; int eflags; - /* - * (XXX old comment) regs->tf_esp points to the return address. - * The user scp pointer is above that. - * The return address is faked in the signal trampoline code - * for consistency. - */ + if ((p->p_flag & P_NEWSIGSET) != 0) + return sigreturn(p, (struct sigreturn_args *)uap); + scp = uap->sigcntxp; - fp = (struct osigframe *) - ((caddr_t)scp - offsetof(struct osigframe, sf_siginfo.si_sc)); - if (useracc((caddr_t)fp, sizeof (struct osigframe), B_WRITE) == 0) + if (useracc((caddr_t)scp, sizeof (struct osigcontext), B_WRITE) == 0) return(EFAULT); eflags = scp->sc_ps; @@ -847,6 +841,10 @@ osigreturn(p, uap) regs->tf_ds = scp->sc_ds; regs->tf_es = scp->sc_es; regs->tf_fs = scp->sc_fs; + if (load_gs_param(scp->sc_gs)) { + trapsignal(p, SIGBUS, T_SEGNPFLT); + return (EFAULT); + } } /* restore scratch registers */ @@ -860,9 +858,6 @@ osigreturn(p, uap) regs->tf_ss = scp->sc_ss; regs->tf_isp = scp->sc_isp; - if (useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0) - return(EINVAL); - if (scp->sc_onstack & 01) p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK; else @@ -888,9 +883,11 @@ sigreturn(p, uap) ucontext_t *ucp; int cs, eflags; + p->p_flag |= P_NEWSIGSET; + regs = p->p_md.md_regs; ucp = uap->sigcntxp; - eflags = ucp->uc_mcontext.mc_tf.tf_eflags; + eflags = ucp->uc_mcontext.mc_eflags; if (useracc((caddr_t)ucp, sizeof(ucontext_t), B_WRITE) == 0) return(EFAULT); @@ -920,7 +917,7 @@ sigreturn(p, uap) vm86->vm86_eflags = eflags; /* save VIF, VIP */ eflags = (tf->tf_eflags & ~VM_USERCHANGE) | (eflags & VM_USERCHANGE) | PSL_VM; } - *regs = ucp->uc_mcontext.mc_tf; + bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(struct trapframe)); tf->tf_vm86_ds = tf->tf_ds; tf->tf_vm86_es = tf->tf_es; tf->tf_vm86_fs = tf->tf_fs; @@ -952,14 +949,17 @@ sigreturn(p, uap) * hardware check for invalid selectors, excess privilege in * other selectors, invalid %eip's and invalid %esp's. */ - cs = ucp->uc_mcontext.mc_tf.tf_cs; + cs = ucp->uc_mcontext.mc_cs; if (!CS_SECURE(cs)) { printf("sigreturn: cs = 0x%x\n", cs); trapsignal(p, SIGBUS, T_PROTFLT); return(EINVAL); } - - *regs = ucp->uc_mcontext.mc_tf; + bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(struct trapframe)); + if (load_gs_param(ucp->uc_mcontext.mc_gs)) { + trapsignal(p, SIGBUS, T_SEGNPFLT); + return (EFAULT); + } } if (ucp->uc_mcontext.mc_onstack & 1) @@ -1033,10 +1033,10 @@ setregs(p, entry, stack, ps_strings) regs->tf_ebx = ps_strings; /* reset %gs as well */ - pcb->pcb_gs = _udatasel; - if (pcb == curpcb) { + if (pcb == curpcb) load_gs(_udatasel); - } + else + pcb->pcb_gs = _udatasel; /* * Initialize the math emulator (if any) for the current process. diff --git a/sys/amd64/amd64/support.S b/sys/amd64/amd64/support.S index ae99af9..6a6e9fc 100644 --- a/sys/amd64/amd64/support.S +++ b/sys/amd64/amd64/support.S @@ -1586,6 +1586,21 @@ ENTRY(load_cr4) movl %eax,%cr4 ret +/* int load_gs_param(caddr_t gs) */ +ENTRY(load_gs_param) + movl _curpcb,%ecx + movl $load_gs_param_fault,PCB_ONFAULT(%ecx) + movl 4(%esp),%eax + movl %eax,%gs + xor %eax,%eax + movl %eax,PCB_ONFAULT(%ecx) + ret +load_gs_param_fault: + movl _curpcb,%ecx + movl $0,PCB_ONFAULT(%ecx) + movl $EFAULT,%eax + ret + /*****************************************************************************/ /* setjump, longjump */ /*****************************************************************************/ diff --git a/sys/amd64/amd64/support.s b/sys/amd64/amd64/support.s index ae99af9..6a6e9fc 100644 --- a/sys/amd64/amd64/support.s +++ b/sys/amd64/amd64/support.s @@ -1586,6 +1586,21 @@ ENTRY(load_cr4) movl %eax,%cr4 ret +/* int load_gs_param(caddr_t gs) */ +ENTRY(load_gs_param) + movl _curpcb,%ecx + movl $load_gs_param_fault,PCB_ONFAULT(%ecx) + movl 4(%esp),%eax + movl %eax,%gs + xor %eax,%eax + movl %eax,PCB_ONFAULT(%ecx) + ret +load_gs_param_fault: + movl _curpcb,%ecx + movl $0,PCB_ONFAULT(%ecx) + movl $EFAULT,%eax + ret + /*****************************************************************************/ /* setjump, longjump */ /*****************************************************************************/ diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h index 755e1e7..d9a43fa 100644 --- a/sys/amd64/include/md_var.h +++ b/sys/amd64/include/md_var.h @@ -91,6 +91,7 @@ int i586_copyout __P((const void *kaddr, void *udaddr, size_t len)); void i686_pagezero __P((void *addr)); int is_physical_memory __P((vm_offset_t addr)); u_long kvtop __P((void *addr)); +int load_gs_param __P((u_int sel)); void setidt __P((int idx, alias_for_inthand_t *func, int typ, int dpl, int selec)); void swi_vm __P((void)); diff --git a/sys/amd64/include/sigframe.h b/sys/amd64/include/sigframe.h index ac64ddb..e7b47fa 100644 --- a/sys/amd64/include/sigframe.h +++ b/sys/amd64/include/sigframe.h @@ -86,9 +86,8 @@ struct sigframe { __siginfohandler_t *sf_action; __sighandler_t *sf_handler; } sf_ahu; - register_t sf_sigreturn; /* sigreturn to use */ - siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case) */ ucontext_t sf_uc; /* = *sf_ucontext */ + siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case) */ }; #endif /* !_MACHINE_SIGFRAME_H_ */ diff --git a/sys/amd64/include/ucontext.h b/sys/amd64/include/ucontext.h index 0d72716..6397a31 100644 --- a/sys/amd64/include/ucontext.h +++ b/sys/amd64/include/ucontext.h @@ -35,13 +35,30 @@ typedef struct __mcontext { /* - * The first 3 fields must match the definition of + * The first 20 fields must match the definition of * sigcontext. So that we can support sigcontext * and ucontext_t at the same time. */ int mc_onstack; /* XXX - sigcontext compat. */ int mc_gs; - struct trapframe mc_tf; + int mc_fs; + int mc_es; + int mc_ds; + int mc_edi; + int mc_esi; + int mc_ebp; + int mc_isp; + int mc_ebx; + int mc_edx; + int mc_ecx; + int mc_eax; + int mc_trapno; + int mc_err; + int mc_eip; + int mc_cs; + int mc_eflags; + int mc_esp; /* machine state */ + int mc_ss; int mc_fpregs[28]; /* env87 + fpacc87 + u_long */ int __spare__[17]; diff --git a/sys/i386/i386/genassym.c b/sys/i386/i386/genassym.c index 8299177..b95a9a7 100644 --- a/sys/i386/i386/genassym.c +++ b/sys/i386/i386/genassym.c @@ -148,18 +148,8 @@ main() printf("#define\tTF_EFLAGS %#x\n", OS(trapframe, tf_eflags)); printf("#define\tSIGF_HANDLER %#x\n", OS(sigframe, sf_ahu.sf_handler)); - printf("#define\tSIGF_SIGRET %#x\n", OS(sigframe, sf_sigreturn)); - printf("#define\tSIGF_SC %#x\n", OS(osigframe, sf_siginfo.si_sc)); printf("#define\tSIGF_UC %#x\n", OS(sigframe, sf_uc)); - printf("#define\tSC_PS %#x\n", OS(osigcontext, sc_ps)); - printf("#define\tSC_FS %#x\n", OS(osigcontext, sc_fs)); - printf("#define\tSC_GS %#x\n", OS(osigcontext, sc_gs)); - - printf("#define\tUC_EFLAGS %#x\n", - OS(__ucontext, uc_mcontext.mc_tf.tf_eflags)); - printf("#define\tUC_GS %#x\n", OS(__ucontext, uc_mcontext.mc_gs)); - printf("#define\tB_READ %#x\n", B_READ); printf("#define\tENOENT %d\n", ENOENT); printf("#define\tEFAULT %d\n", EFAULT); diff --git a/sys/i386/i386/locore.s b/sys/i386/i386/locore.s index e87c275..a1b6ff7 100644 --- a/sys/i386/i386/locore.s +++ b/sys/i386/i386/locore.s @@ -415,37 +415,14 @@ NON_GPROF_ENTRY(prepare_usermode) */ NON_GPROF_ENTRY(sigcode) call SIGF_HANDLER(%esp) /* call signal handler */ - movl SIGF_SIGRET(%esp),%eax /* Get sigreturn cookie */ - cmpl $0x0ABCDEF0,%eax /* New one? */ - jne 3f -/* New signalling code */ - lea SIGF_UC(%esp),%eax /* get ucontext */ + lea SIGF_UC(%esp),%eax /* get ucontext_t */ pushl %eax - testl $PSL_VM,UC_EFLAGS(%eax) - jne 1f - movl UC_GS(%eax),%gs /* restore %gs */ -1: - movl $SYS_sigreturn,%eax - pushl %eax /* junk to fake return addr. */ - int $0x80 /* enter kernel with args */ - /* on stack */ -2: - jmp 2b -/* Old signalling code */ -3: - lea SIGF_SC(%esp),%eax /* get sigcontext */ - pushl %eax - testl $PSL_VM,SC_PS(%eax) - jne 4f - movl SC_GS(%eax),%gs /* restore %gs */ -4: movl $SYS_osigreturn,%eax pushl %eax /* junk to fake return addr. */ int $0x80 /* enter kernel with args */ /* on stack */ -5: - jmp 5b - +1: + jmp 1b ALIGN_TEXT _esigcode: diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 1ef6fb0..a682098 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -599,6 +599,7 @@ osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) regs->tf_ds = _udatasel; regs->tf_es = _udatasel; regs->tf_fs = _udatasel; + load_gs(_udatasel); regs->tf_ss = _udatasel; } @@ -631,8 +632,8 @@ sendsig(catcher, sig, mask, code) sf.sf_uc.uc_sigmask = *mask; sf.sf_uc.uc_stack = psp->ps_sigstk; sf.sf_uc.uc_mcontext.mc_onstack = onstack; - sf.sf_uc.uc_mcontext.mc_tf = *regs; sf.sf_uc.uc_mcontext.mc_gs = rgs(); + bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(struct trapframe)); /* Allocate and validate space for the signal handler context. */ if ((psp->ps_flags & SAS_ALTSTACK) != 0 && !onstack && @@ -702,12 +703,12 @@ sendsig(catcher, sig, mask, code) struct vm86_kernel *vm86 = &p->p_addr->u_pcb.pcb_ext->ext_vm86; sf.sf_uc.uc_mcontext.mc_gs = tf->tf_vm86_gs; - sf.sf_uc.uc_mcontext.mc_tf.tf_fs = tf->tf_vm86_fs; - sf.sf_uc.uc_mcontext.mc_tf.tf_es = tf->tf_vm86_es; - sf.sf_uc.uc_mcontext.mc_tf.tf_ds = tf->tf_vm86_ds; + sf.sf_uc.uc_mcontext.mc_fs = tf->tf_vm86_fs; + sf.sf_uc.uc_mcontext.mc_es = tf->tf_vm86_es; + sf.sf_uc.uc_mcontext.mc_ds = tf->tf_vm86_ds; if (vm86->vm86_has_vme == 0) - sf.sf_uc.uc_mcontext.mc_tf.tf_eflags = + sf.sf_uc.uc_mcontext.mc_eflags = (tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) | (vm86->vm86_eflags & (PSL_VIF | PSL_VIP)); @@ -725,8 +726,6 @@ sendsig(catcher, sig, mask, code) tf->tf_eflags &= ~(PSL_VM|PSL_NT|PSL_T|PSL_VIF|PSL_VIP); } - sf.sf_sigreturn = 0x0ABCDEF0; - /* * Copy the sigframe out to the user's stack. */ @@ -744,6 +743,7 @@ sendsig(catcher, sig, mask, code) regs->tf_ds = _udatasel; regs->tf_es = _udatasel; regs->tf_fs = _udatasel; + load_gs(_udatasel); regs->tf_ss = _udatasel; } @@ -767,21 +767,15 @@ osigreturn(p, uap) } */ *uap; { register struct osigcontext *scp; - register struct osigframe *fp; register struct trapframe *regs = p->p_md.md_regs; int eflags; - /* - * (XXX old comment) regs->tf_esp points to the return address. - * The user scp pointer is above that. - * The return address is faked in the signal trampoline code - * for consistency. - */ + if ((p->p_flag & P_NEWSIGSET) != 0) + return sigreturn(p, (struct sigreturn_args *)uap); + scp = uap->sigcntxp; - fp = (struct osigframe *) - ((caddr_t)scp - offsetof(struct osigframe, sf_siginfo.si_sc)); - if (useracc((caddr_t)fp, sizeof (struct osigframe), B_WRITE) == 0) + if (useracc((caddr_t)scp, sizeof (struct osigcontext), B_WRITE) == 0) return(EFAULT); eflags = scp->sc_ps; @@ -847,6 +841,10 @@ osigreturn(p, uap) regs->tf_ds = scp->sc_ds; regs->tf_es = scp->sc_es; regs->tf_fs = scp->sc_fs; + if (load_gs_param(scp->sc_gs)) { + trapsignal(p, SIGBUS, T_SEGNPFLT); + return (EFAULT); + } } /* restore scratch registers */ @@ -860,9 +858,6 @@ osigreturn(p, uap) regs->tf_ss = scp->sc_ss; regs->tf_isp = scp->sc_isp; - if (useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0) - return(EINVAL); - if (scp->sc_onstack & 01) p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK; else @@ -888,9 +883,11 @@ sigreturn(p, uap) ucontext_t *ucp; int cs, eflags; + p->p_flag |= P_NEWSIGSET; + regs = p->p_md.md_regs; ucp = uap->sigcntxp; - eflags = ucp->uc_mcontext.mc_tf.tf_eflags; + eflags = ucp->uc_mcontext.mc_eflags; if (useracc((caddr_t)ucp, sizeof(ucontext_t), B_WRITE) == 0) return(EFAULT); @@ -920,7 +917,7 @@ sigreturn(p, uap) vm86->vm86_eflags = eflags; /* save VIF, VIP */ eflags = (tf->tf_eflags & ~VM_USERCHANGE) | (eflags & VM_USERCHANGE) | PSL_VM; } - *regs = ucp->uc_mcontext.mc_tf; + bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(struct trapframe)); tf->tf_vm86_ds = tf->tf_ds; tf->tf_vm86_es = tf->tf_es; tf->tf_vm86_fs = tf->tf_fs; @@ -952,14 +949,17 @@ sigreturn(p, uap) * hardware check for invalid selectors, excess privilege in * other selectors, invalid %eip's and invalid %esp's. */ - cs = ucp->uc_mcontext.mc_tf.tf_cs; + cs = ucp->uc_mcontext.mc_cs; if (!CS_SECURE(cs)) { printf("sigreturn: cs = 0x%x\n", cs); trapsignal(p, SIGBUS, T_PROTFLT); return(EINVAL); } - - *regs = ucp->uc_mcontext.mc_tf; + bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(struct trapframe)); + if (load_gs_param(ucp->uc_mcontext.mc_gs)) { + trapsignal(p, SIGBUS, T_SEGNPFLT); + return (EFAULT); + } } if (ucp->uc_mcontext.mc_onstack & 1) @@ -1033,10 +1033,10 @@ setregs(p, entry, stack, ps_strings) regs->tf_ebx = ps_strings; /* reset %gs as well */ - pcb->pcb_gs = _udatasel; - if (pcb == curpcb) { + if (pcb == curpcb) load_gs(_udatasel); - } + else + pcb->pcb_gs = _udatasel; /* * Initialize the math emulator (if any) for the current process. diff --git a/sys/i386/i386/support.s b/sys/i386/i386/support.s index ae99af9..6a6e9fc 100644 --- a/sys/i386/i386/support.s +++ b/sys/i386/i386/support.s @@ -1586,6 +1586,21 @@ ENTRY(load_cr4) movl %eax,%cr4 ret +/* int load_gs_param(caddr_t gs) */ +ENTRY(load_gs_param) + movl _curpcb,%ecx + movl $load_gs_param_fault,PCB_ONFAULT(%ecx) + movl 4(%esp),%eax + movl %eax,%gs + xor %eax,%eax + movl %eax,PCB_ONFAULT(%ecx) + ret +load_gs_param_fault: + movl _curpcb,%ecx + movl $0,PCB_ONFAULT(%ecx) + movl $EFAULT,%eax + ret + /*****************************************************************************/ /* setjump, longjump */ /*****************************************************************************/ diff --git a/sys/i386/include/md_var.h b/sys/i386/include/md_var.h index 755e1e7..d9a43fa 100644 --- a/sys/i386/include/md_var.h +++ b/sys/i386/include/md_var.h @@ -91,6 +91,7 @@ int i586_copyout __P((const void *kaddr, void *udaddr, size_t len)); void i686_pagezero __P((void *addr)); int is_physical_memory __P((vm_offset_t addr)); u_long kvtop __P((void *addr)); +int load_gs_param __P((u_int sel)); void setidt __P((int idx, alias_for_inthand_t *func, int typ, int dpl, int selec)); void swi_vm __P((void)); diff --git a/sys/i386/include/sigframe.h b/sys/i386/include/sigframe.h index ac64ddb..e7b47fa 100644 --- a/sys/i386/include/sigframe.h +++ b/sys/i386/include/sigframe.h @@ -86,9 +86,8 @@ struct sigframe { __siginfohandler_t *sf_action; __sighandler_t *sf_handler; } sf_ahu; - register_t sf_sigreturn; /* sigreturn to use */ - siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case) */ ucontext_t sf_uc; /* = *sf_ucontext */ + siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case) */ }; #endif /* !_MACHINE_SIGFRAME_H_ */ diff --git a/sys/i386/include/ucontext.h b/sys/i386/include/ucontext.h index 0d72716..6397a31 100644 --- a/sys/i386/include/ucontext.h +++ b/sys/i386/include/ucontext.h @@ -35,13 +35,30 @@ typedef struct __mcontext { /* - * The first 3 fields must match the definition of + * The first 20 fields must match the definition of * sigcontext. So that we can support sigcontext * and ucontext_t at the same time. */ int mc_onstack; /* XXX - sigcontext compat. */ int mc_gs; - struct trapframe mc_tf; + int mc_fs; + int mc_es; + int mc_ds; + int mc_edi; + int mc_esi; + int mc_ebp; + int mc_isp; + int mc_ebx; + int mc_edx; + int mc_ecx; + int mc_eax; + int mc_trapno; + int mc_err; + int mc_eip; + int mc_cs; + int mc_eflags; + int mc_esp; /* machine state */ + int mc_ss; int mc_fpregs[28]; /* env87 + fpacc87 + u_long */ int __spare__[17]; -- cgit v1.1