summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>1999-10-07 12:40:34 +0000
committermarcel <marcel@FreeBSD.org>1999-10-07 12:40:34 +0000
commit82d2a417f9f83101d1887aa1f696d8855b15cb8e (patch)
tree0f8242e8f4f2389aea38ffa052f3deaf4df7651d
parent92cdc096e64f4f2f9198db3941bce72a914b7350 (diff)
downloadFreeBSD-src-82d2a417f9f83101d1887aa1f696d8855b15cb8e.zip
FreeBSD-src-82d2a417f9f83101d1887aa1f696d8855b15cb8e.tar.gz
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
-rw-r--r--sys/amd64/amd64/genassym.c10
-rw-r--r--sys/amd64/amd64/locore.S29
-rw-r--r--sys/amd64/amd64/locore.s29
-rw-r--r--sys/amd64/amd64/machdep.c56
-rw-r--r--sys/amd64/amd64/support.S15
-rw-r--r--sys/amd64/amd64/support.s15
-rw-r--r--sys/amd64/include/md_var.h1
-rw-r--r--sys/amd64/include/sigframe.h3
-rw-r--r--sys/amd64/include/ucontext.h21
-rw-r--r--sys/i386/i386/genassym.c10
-rw-r--r--sys/i386/i386/locore.s29
-rw-r--r--sys/i386/i386/machdep.c56
-rw-r--r--sys/i386/i386/support.s15
-rw-r--r--sys/i386/include/md_var.h1
-rw-r--r--sys/i386/include/sigframe.h3
-rw-r--r--sys/i386/include/ucontext.h21
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];
OpenPOWER on IntegriCloud