summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>1999-09-29 15:06:27 +0000
committermarcel <marcel@FreeBSD.org>1999-09-29 15:06:27 +0000
commita16d76cb5680cf0afd1a3be9be9d1f7ea686a96c (patch)
tree01641d7a39068193783b082ecaf28021e39ce36c /sys/amd64
parentd5e8d714b93b1824409b762780bec45541995276 (diff)
downloadFreeBSD-src-a16d76cb5680cf0afd1a3be9be9d1f7ea686a96c.zip
FreeBSD-src-a16d76cb5680cf0afd1a3be9be9d1f7ea686a96c.tar.gz
sigset_t change (part 3 of 5)
----------------------------- By introducing a new sigframe so that the signal handler operates on the new siginfo_t and on ucontext_t instead of sigcontext, we now need two version of sendsig and sigreturn. A flag in struct proc determines whether the process expects an old sigframe or a new sigframe. The signal trampoline handles which sigreturn to call. It does this by testing for a magic cookie in the frame. The alpha uses osigreturn to implement longjmp. This means that osigreturn is not only used for compatibility with existing binaries. To handle the new sigset_t, setjmp saves it in sc_reserved (see NOTE). the struct sigframe has been moved from frame.h to sigframe.h to handle the complex header dependencies that was caused by the new sigframe. NOTE: For the i386, the size of jmp_buf has been increased to hold the new sigset_t. On the alpha this has been prevented by using sc_reserved in sigcontext.
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/amd64/genassym.c16
-rw-r--r--sys/amd64/amd64/locore.S38
-rw-r--r--sys/amd64/amd64/locore.s38
-rw-r--r--sys/amd64/amd64/machdep.c345
-rw-r--r--sys/amd64/include/db_machdep.h1
-rw-r--r--sys/amd64/include/frame.h38
-rw-r--r--sys/amd64/include/setjmp.h2
-rw-r--r--sys/amd64/include/sigframe.h86
-rw-r--r--sys/amd64/include/signal.h56
-rw-r--r--sys/amd64/include/ucontext.h43
10 files changed, 505 insertions, 158 deletions
diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c
index d4023cc..62dbf53 100644
--- a/sys/amd64/amd64/genassym.c
+++ b/sys/amd64/amd64/genassym.c
@@ -72,6 +72,8 @@
#include <machine/globaldata.h>
#include <machine/vm86.h>
+#include <machine/sigframe.h>
+
#define OS(s, m) ((u_int)offsetof(struct s, m))
int main __P((void));
@@ -147,10 +149,16 @@ 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_SC %#x\n", OS(sigframe, sf_siginfo.si_sc));
- printf("#define\tSC_PS %#x\n", OS(sigcontext, sc_ps));
- printf("#define\tSC_FS %#x\n", OS(sigcontext, sc_fs));
- printf("#define\tSC_GS %#x\n", OS(sigcontext, sc_gs));
+ 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);
diff --git a/sys/amd64/amd64/locore.S b/sys/amd64/amd64/locore.S
index ad499bd..e87c275 100644
--- a/sys/amd64/amd64/locore.S
+++ b/sys/amd64/amd64/locore.S
@@ -414,18 +414,38 @@ NON_GPROF_ENTRY(prepare_usermode)
* Signal trampoline, copied to top of user stack
*/
NON_GPROF_ENTRY(sigcode)
- call SIGF_HANDLER(%esp)
- lea SIGF_SC(%esp),%eax /* scp (the call may have clobbered the */
- /* copy at 8(%esp)) */
+ 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 */
pushl %eax
- pushl %eax /* junk to fake return address */
- testl $PSL_VM,SC_PS(%eax)
+ testl $PSL_VM,UC_EFLAGS(%eax)
jne 1f
- movl SC_GS(%eax),%gs /* restore %gs */
+ movl UC_GS(%eax),%gs /* restore %gs */
1:
- movl $SYS_sigreturn,%eax /* sigreturn() */
- int $0x80 /* enter kernel with args on stack */
-2: jmp 2b
+ 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
+
ALIGN_TEXT
_esigcode:
diff --git a/sys/amd64/amd64/locore.s b/sys/amd64/amd64/locore.s
index ad499bd..e87c275 100644
--- a/sys/amd64/amd64/locore.s
+++ b/sys/amd64/amd64/locore.s
@@ -414,18 +414,38 @@ NON_GPROF_ENTRY(prepare_usermode)
* Signal trampoline, copied to top of user stack
*/
NON_GPROF_ENTRY(sigcode)
- call SIGF_HANDLER(%esp)
- lea SIGF_SC(%esp),%eax /* scp (the call may have clobbered the */
- /* copy at 8(%esp)) */
+ 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 */
pushl %eax
- pushl %eax /* junk to fake return address */
- testl $PSL_VM,SC_PS(%eax)
+ testl $PSL_VM,UC_EFLAGS(%eax)
jne 1f
- movl SC_GS(%eax),%gs /* restore %gs */
+ movl UC_GS(%eax),%gs /* restore %gs */
1:
- movl $SYS_sigreturn,%eax /* sigreturn() */
- int $0x80 /* enter kernel with args on stack */
-2: jmp 2b
+ 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
+
ALIGN_TEXT
_esigcode:
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 7b712d2..b5280c6 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -127,6 +127,7 @@
#include <machine/vm86.h>
#include <machine/random.h>
#include <sys/ptrace.h>
+#include <machine/sigframe.h>
extern void init386 __P((int first));
extern void dblfault_handler __P((void));
@@ -471,79 +472,66 @@ netisr_sysinit(data)
* frame pointer, it returns to the user
* specified pc, psl.
*/
-void
-sendsig(catcher, sig, mask, code)
- sig_t catcher;
- int sig, mask;
- u_long code;
+static void
+osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
{
register struct proc *p = curproc;
register struct trapframe *regs;
- register struct sigframe *fp;
- struct sigframe sf;
+ register struct osigframe *fp;
+ struct osigframe sf;
struct sigacts *psp = p->p_sigacts;
int oonstack;
regs = p->p_md.md_regs;
- oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
- /*
- * Allocate and validate space for the signal handler context.
- */
- if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
- (psp->ps_sigonstack & sigmask(sig))) {
- fp = (struct sigframe *)(psp->ps_sigstk.ss_sp +
- psp->ps_sigstk.ss_size - sizeof(struct sigframe));
+ oonstack = (psp->ps_sigstk.ss_flags & SS_ONSTACK) ? 1 : 0;
+
+ /* Allocate and validate space for the signal handler context. */
+ if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
+ SIGISMEMBER(psp->ps_sigonstack, sig)) {
+ fp = (struct osigframe *)(psp->ps_sigstk.ss_sp +
+ psp->ps_sigstk.ss_size - sizeof(struct osigframe));
psp->ps_sigstk.ss_flags |= SS_ONSTACK;
- } else {
- fp = (struct sigframe *)regs->tf_esp - 1;
}
+ else
+ fp = (struct osigframe *)regs->tf_esp - 1;
/*
* grow() will return FALSE if the fp will not fit inside the stack
* and the stack can not be grown. useracc will return FALSE
* if access is denied.
*/
- if ((grow_stack (p, (int)fp) == FALSE) ||
- (useracc((caddr_t)fp, sizeof(struct sigframe), B_WRITE) == FALSE)) {
+ if (grow_stack(p, (int)fp) == FALSE ||
+ useracc((caddr_t)fp, sizeof(struct osigframe), B_WRITE) == FALSE) {
/*
* Process has trashed its stack; give it an illegal
* instruction to halt it in its tracks.
*/
-#ifdef DEBUG
- printf("process %d has trashed its stack\n", p->p_pid);
-#endif
SIGACTION(p, SIGILL) = SIG_DFL;
- sig = sigmask(SIGILL);
- p->p_sigignore &= ~sig;
- p->p_sigcatch &= ~sig;
- p->p_sigmask &= ~sig;
+ SIGDELSET(p->p_sigignore, SIGILL);
+ SIGDELSET(p->p_sigcatch, SIGILL);
+ SIGDELSET(p->p_sigmask, SIGILL);
psignal(p, SIGILL);
return;
}
- /*
- * Build the argument list for the signal handler.
- */
+ /* Translate the signal if appropriate */
if (p->p_sysent->sv_sigtbl) {
- if (sig < p->p_sysent->sv_sigsize)
- sig = p->p_sysent->sv_sigtbl[sig];
- else
- sig = p->p_sysent->sv_sigsize + 1;
+ if (sig <= p->p_sysent->sv_sigsize)
+ sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
}
+
+ /* Build the argument list for the signal handler. */
sf.sf_signum = sig;
sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc;
- if (p->p_sigacts->ps_siginfo & sigmask(sig)) {
- /*
- * Signal handler installed with SA_SIGINFO.
- */
+ if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ /* Signal handler installed with SA_SIGINFO. */
sf.sf_arg2 = (register_t)&fp->sf_siginfo;
sf.sf_siginfo.si_signo = sig;
sf.sf_siginfo.si_code = code;
- sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
- } else {
- /*
- * Old FreeBSD-style arguments.
- */
+ sf.sf_ahu.sf_action = (__osiginfohandler_t *)catcher;
+ }
+ else {
+ /* Old FreeBSD-style arguments. */
sf.sf_arg2 = code;
sf.sf_ahu.sf_handler = catcher;
}
@@ -565,11 +553,9 @@ sendsig(catcher, sig, mask, code)
sf.sf_siginfo.si_sc.sc_gs = rgs();
sf.sf_siginfo.si_sc.sc_isp = regs->tf_isp;
- /*
- * Build the signal context to be used by sigreturn.
- */
+ /* Build the signal context to be used by sigreturn. */
sf.sf_siginfo.si_sc.sc_onstack = oonstack;
- sf.sf_siginfo.si_sc.sc_mask = mask;
+ SIG2OSIG(*mask, sf.sf_siginfo.si_sc.sc_mask);
sf.sf_siginfo.si_sc.sc_sp = regs->tf_esp;
sf.sf_siginfo.si_sc.sc_fp = regs->tf_ebp;
sf.sf_siginfo.si_sc.sc_pc = regs->tf_eip;
@@ -592,8 +578,135 @@ sendsig(catcher, sig, mask, code)
sf.sf_siginfo.si_sc.sc_ds = tf->tf_vm86_ds;
if (vm86->vm86_has_vme == 0)
- sf.sf_siginfo.si_sc.sc_ps = (tf->tf_eflags & ~(PSL_VIF | PSL_VIP))
+ sf.sf_siginfo.si_sc.sc_ps =
+ (tf->tf_eflags & ~(PSL_VIF | PSL_VIP))
| (vm86->vm86_eflags & (PSL_VIF | PSL_VIP));
+ /* see sendsig for comment */
+ tf->tf_eflags &= ~(PSL_VM|PSL_NT|PSL_T|PSL_VIF|PSL_VIP);
+ }
+
+ /* Copy the sigframe out to the user's stack. */
+ if (copyout(&sf, fp, sizeof(struct osigframe)) != 0) {
+ /*
+ * Something is wrong with the stack pointer.
+ * ...Kill the process.
+ */
+ sigexit(p, SIGILL);
+ }
+
+ regs->tf_esp = (int)fp;
+ regs->tf_eip = PS_STRINGS - *(p->p_sysent->sv_szsigcode);
+ regs->tf_cs = _ucodesel;
+ regs->tf_ds = _udatasel;
+ regs->tf_es = _udatasel;
+ regs->tf_fs = _udatasel;
+ regs->tf_ss = _udatasel;
+}
+
+void
+sendsig(catcher, sig, mask, code)
+ sig_t catcher;
+ int sig;
+ sigset_t *mask;
+ u_long code;
+{
+ struct proc *p;
+ struct trapframe *regs;
+ struct sigacts *psp;
+ struct sigframe sf, *sfp;
+
+ p = curproc;
+
+ if ((p->p_flag & P_NEWSIGSET) == 0) {
+ osendsig(catcher, sig, mask, code);
+ return;
+ }
+
+ regs = p->p_md.md_regs;
+ psp = p->p_sigacts;
+
+ /* save user context */
+ bzero(&sf, sizeof(struct sigframe));
+ sf.sf_uc.uc_sigmask = *mask;
+ sf.sf_uc.uc_stack = psp->ps_sigstk;
+ sf.sf_uc.uc_mcontext.mc_tf = *regs;
+ sf.sf_uc.uc_mcontext.mc_gs = rgs();
+
+ /* Allocate and validate space for the signal handler context. */
+ if ((psp->ps_flags & SAS_ALTSTACK) != 0 &&
+ (psp->ps_sigstk.ss_flags & SS_ONSTACK) == 0 &&
+ SIGISMEMBER(psp->ps_sigonstack, sig)) {
+ sfp = (struct sigframe *)(psp->ps_sigstk.ss_sp +
+ psp->ps_sigstk.ss_size - sizeof(struct sigframe));
+ psp->ps_sigstk.ss_flags |= SS_ONSTACK;
+ }
+ else
+ sfp = (struct sigframe *)regs->tf_esp - 1;
+
+ /*
+ * grow() will return FALSE if the sfp will not fit inside the stack
+ * and the stack can not be grown. useracc will return FALSE if
+ * access is denied.
+ */
+ if (grow_stack(p, (int)sfp) == FALSE ||
+ useracc((caddr_t)sfp, sizeof(struct sigframe), B_WRITE) == FALSE) {
+ /*
+ * Process has trashed its stack; give it an illegal
+ * instruction to halt it in its tracks.
+ */
+#ifdef DEBUG
+ printf("process %d has trashed its stack\n", p->p_pid);
+#endif
+ SIGACTION(p, SIGILL) = SIG_DFL;
+ SIGDELSET(p->p_sigignore, SIGILL);
+ SIGDELSET(p->p_sigcatch, SIGILL);
+ SIGDELSET(p->p_sigmask, SIGILL);
+ psignal(p, SIGILL);
+ return;
+ }
+
+ /* Translate the signal is appropriate */
+ if (p->p_sysent->sv_sigtbl) {
+ if (sig <= p->p_sysent->sv_sigsize)
+ sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
+ }
+
+ /* Build the argument list for the signal handler. */
+ sf.sf_signum = sig;
+ sf.sf_ucontext = (register_t)&sfp->sf_uc;
+ if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ /* Signal handler installed with SA_SIGINFO. */
+ sf.sf_siginfo = (register_t)&sfp->sf_si;
+ sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
+
+ /* fill siginfo structure */
+ sf.sf_si.si_signo = sig;
+ sf.sf_si.si_code = code;
+ }
+ else {
+ /* Old FreeBSD-style arguments. */
+ sf.sf_siginfo = code;
+ sf.sf_ahu.sf_handler = catcher;
+ }
+
+ /*
+ * If we're a vm86 process, we want to save the segment registers.
+ * We also change eflags to be our emulated eflags, not the actual
+ * eflags.
+ */
+ if (regs->tf_eflags & PSL_VM) {
+ struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
+ 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;
+
+ if (vm86->vm86_has_vme == 0)
+ sf.sf_uc.uc_mcontext.mc_tf.tf_eflags =
+ (tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) |
+ (vm86->vm86_eflags & (PSL_VIF | PSL_VIP));
/*
* We should never have PSL_T set when returning from vm86
@@ -606,13 +719,15 @@ sendsig(catcher, sig, mask, code)
* does nothing in vm86 mode, but vm86 programs can set it
* almost legitimately in probes for old cpu types.
*/
- tf->tf_eflags &= ~(PSL_VM | PSL_NT | PSL_T | PSL_VIF | PSL_VIP);
+ 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.
*/
- if (copyout(&sf, fp, sizeof(struct sigframe)) != 0) {
+ if (copyout(&sf, sfp, sizeof(struct sigframe)) != 0) {
/*
* Something is wrong with the stack pointer.
* ...Kill the process.
@@ -620,7 +735,7 @@ sendsig(catcher, sig, mask, code)
sigexit(p, SIGILL);
}
- regs->tf_esp = (int)fp;
+ regs->tf_esp = (int)sfp;
regs->tf_eip = PS_STRINGS - *(p->p_sysent->sv_szsigcode);
regs->tf_cs = _ucodesel;
regs->tf_ds = _udatasel;
@@ -638,15 +753,18 @@ sendsig(catcher, sig, mask, code)
* make sure that the user has not modified the
* state to gain improper privileges.
*/
+#define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
+#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL)
+
int
-sigreturn(p, uap)
+osigreturn(p, uap)
struct proc *p;
- struct sigreturn_args /* {
- struct sigcontext *sigcntxp;
+ struct osigreturn_args /* {
+ struct osigcontext *sigcntxp;
} */ *uap;
{
- register struct sigcontext *scp;
- register struct sigframe *fp;
+ register struct osigcontext *scp;
+ register struct osigframe *fp;
register struct trapframe *regs = p->p_md.md_regs;
int eflags;
@@ -657,10 +775,10 @@ sigreturn(p, uap)
* for consistency.
*/
scp = uap->sigcntxp;
- fp = (struct sigframe *)
- ((caddr_t)scp - offsetof(struct sigframe, sf_siginfo.si_sc));
+ fp = (struct osigframe *)
+ ((caddr_t)scp - offsetof(struct osigframe, sf_siginfo.si_sc));
- if (useracc((caddr_t)fp, sizeof (*fp), B_WRITE) == 0)
+ if (useracc((caddr_t)fp, sizeof (struct osigframe), B_WRITE) == 0)
return(EFAULT);
eflags = scp->sc_ps;
@@ -700,7 +818,6 @@ sigreturn(p, uap)
/*
* Don't allow users to change privileged or reserved flags.
*/
-#define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
/*
* XXX do allow users to change the privileged flag PSL_RF.
* The cpu sets PSL_RF in tf_eflags for faults. Debuggers
@@ -711,10 +828,7 @@ sigreturn(p, uap)
* Corruption of the PSL_RF bit at worst causes one more or
* one less debugger trap, so allowing it is fairly harmless.
*/
- if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) {
-#ifdef DEBUG
- printf("sigreturn: eflags = 0x%x\n", eflags);
-#endif
+ if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) {
return(EINVAL);
}
@@ -723,11 +837,7 @@ sigreturn(p, uap)
* hardware check for invalid selectors, excess privilege in
* other selectors, invalid %eip's and invalid %esp's.
*/
-#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL)
if (!CS_SECURE(scp->sc_cs)) {
-#ifdef DEBUG
- printf("sigreturn: cs = 0x%x\n", scp->sc_cs);
-#endif
trapsignal(p, SIGBUS, T_PROTFLT);
return(EINVAL);
}
@@ -754,7 +864,9 @@ sigreturn(p, uap)
p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
else
p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
- p->p_sigmask = scp->sc_mask & ~sigcantmask;
+
+ OSIG2SIG(scp->sc_mask, p->p_sigmask);
+ SIG_CANTMASK(p->p_sigmask);
regs->tf_ebp = scp->sc_fp;
regs->tf_esp = scp->sc_sp;
regs->tf_eip = scp->sc_pc;
@@ -762,6 +874,99 @@ sigreturn(p, uap)
return(EJUSTRETURN);
}
+int
+sigreturn(p, uap)
+ struct proc *p;
+ struct sigreturn_args /* {
+ ucontext_t *sigcntxp;
+ } */ *uap;
+{
+ struct trapframe *regs;
+ ucontext_t *ucp;
+ struct sigframe *sfp;
+ int eflags;
+
+ regs = p->p_md.md_regs;
+ ucp = uap->sigcntxp;
+ sfp = (struct sigframe *)
+ ((caddr_t)ucp - offsetof(struct sigframe, sf_uc));
+ eflags = ucp->uc_mcontext.mc_tf.tf_eflags;
+
+ if (useracc((caddr_t)sfp, sizeof(struct sigframe), B_WRITE) == 0)
+ return(EFAULT);
+
+ 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 (p->p_addr->u_pcb.pcb_ext == 0)
+ return (EINVAL);
+ vm86 = &p->p_addr->u_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(p, 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;
+ }
+ *regs = ucp->uc_mcontext.mc_tf;
+ 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 = ucp->uc_mcontext.mc_gs;
+ tf->tf_ds = _udatasel;
+ tf->tf_es = _udatasel;
+ tf->tf_fs = _udatasel;
+ } else {
+ /*
+ * 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)) {
+ printf("sigreturn: eflags = 0x%x\n", eflags);
+ return(EINVAL);
+ }
+
+ *regs = ucp->uc_mcontext.mc_tf;
+
+ /*
+ * 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.
+ */
+ if (!CS_SECURE(regs->tf_cs)) {
+ printf("sigreturn: cs = 0x%x\n", regs->tf_cs);
+ trapsignal(p, SIGBUS, T_PROTFLT);
+ return(EINVAL);
+ }
+ }
+
+ p->p_sigacts->ps_sigstk = ucp->uc_stack;
+ p->p_sigmask = ucp->uc_sigmask;
+ SIG_CANTMASK(p->p_sigmask);
+ return(EJUSTRETURN);
+}
+
/*
* Machine dependent boot() routine
*
@@ -1862,7 +2067,7 @@ int ptrace_write_u(p, off, data)
tp = p->p_md.md_regs;
frame_copy = *tp;
*(int *)((char *)&frame_copy + (off - min)) = data;
- if (!EFLAGS_SECURE(frame_copy.tf_eflags, tp->tf_eflags) ||
+ if (!EFL_SECURE(frame_copy.tf_eflags, tp->tf_eflags) ||
!CS_SECURE(frame_copy.tf_cs))
return (EINVAL);
*(int*)((char *)p->p_addr + off) = data;
@@ -1914,7 +2119,7 @@ set_regs(p, regs)
struct trapframe *tp;
tp = p->p_md.md_regs;
- if (!EFLAGS_SECURE(regs->r_eflags, tp->tf_eflags) ||
+ if (!EFL_SECURE(regs->r_eflags, tp->tf_eflags) ||
!CS_SECURE(regs->r_cs))
return (EINVAL);
tp->tf_fs = regs->r_fs;
diff --git a/sys/amd64/include/db_machdep.h b/sys/amd64/include/db_machdep.h
index d5022d8..719c556 100644
--- a/sys/amd64/include/db_machdep.h
+++ b/sys/amd64/include/db_machdep.h
@@ -30,6 +30,7 @@
#define _MACHINE_DB_MACHDEP_H_
#include <machine/frame.h>
+#include <machine/trap.h>
#include <machine/psl.h>
#define i386_saved_state trapframe
diff --git a/sys/amd64/include/frame.h b/sys/amd64/include/frame.h
index b212d6c..634e690 100644
--- a/sys/amd64/include/frame.h
+++ b/sys/amd64/include/frame.h
@@ -40,8 +40,6 @@
#ifndef _MACHINE_FRAME_H_
#define _MACHINE_FRAME_H_ 1
-#include <sys/signal.h>
-
/*
* System stack frames.
*/
@@ -157,42 +155,6 @@ struct clockframe {
int cf_ss;
};
-/*
- * Signal frame, arguments passed to application signal handlers.
- */
-struct sigframe {
- /*
- * The first three members may be used by applications.
- */
-
- register_t sf_signum;
-
- /*
- * Either 'int' for old-style FreeBSD handler or 'siginfo_t *'
- * pointing to sf_siginfo for SA_SIGINFO handlers.
- */
- register_t sf_arg2;
-
- /* Points to sf_siginfo.si_sc. */
- register_t sf_scp;
-
- /*
- * The following arguments are not constrained by the
- * function call protocol.
- * Applications are not supposed to access these members,
- * except using the pointers we provide in the first three
- * arguments.
- */
- char *sf_addr;
- union {
- __siginfohandler_t *sf_action;
- __sighandler_t *sf_handler;
- } sf_ahu;
-
- /* In the SA_SIGINFO case, sf_arg2 points here. */
- siginfo_t sf_siginfo;
-};
-
int kdb_trap __P((int, int, struct trapframe *));
extern int (*pmath_emulate) __P((struct trapframe *));
diff --git a/sys/amd64/include/setjmp.h b/sys/amd64/include/setjmp.h
index 173ea2d..3097df7 100644
--- a/sys/amd64/include/setjmp.h
+++ b/sys/amd64/include/setjmp.h
@@ -32,7 +32,7 @@
*
*/
-#define _JBLEN 8 /* Size of the jmp_buf on x86. */
+#define _JBLEN 11 /* Size of the jmp_buf on x86. */
/*
* jmp_buf and sigjmp_buf are encapsulated in different structs to force
diff --git a/sys/amd64/include/sigframe.h b/sys/amd64/include/sigframe.h
new file mode 100644
index 0000000..9c47915
--- /dev/null
+++ b/sys/amd64/include/sigframe.h
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (c) 1999 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE_SIGFRAME_H_
+#define _MACHINE_SIGFRAME_H_ 1
+
+struct osigframe {
+ /*
+ * The first three members may be used by applications.
+ */
+
+ register_t sf_signum;
+
+ /*
+ * Either 'int' for old-style FreeBSD handler or 'siginfo_t *'
+ * pointing to sf_siginfo for SA_SIGINFO handlers.
+ */
+ register_t sf_arg2;
+
+ /* Points to sf_siginfo.si_sc. */
+ register_t sf_scp;
+
+ /*
+ * The following arguments are not constrained by the
+ * function call protocol.
+ * Applications are not supposed to access these members,
+ * except using the pointers we provide in the first three
+ * arguments.
+ */
+
+ char *sf_addr;
+
+ union {
+ __osiginfohandler_t *sf_action;
+ __sighandler_t *sf_handler;
+ } sf_ahu;
+
+ /* In the SA_SIGINFO case, sf_arg2 points here. */
+ osiginfo_t sf_siginfo;
+};
+
+struct sigframe {
+ /*
+ * The first three members may be used by applications.
+ */
+ register_t sf_signum;
+ register_t sf_siginfo; /* code or pointer to sf_si */
+ register_t sf_ucontext; /* points to sf_uc */
+ register_t __spare__; /* Align sf_ahu */
+ union {
+ __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 */
+};
+
+#endif /* _MACHINE_SIGFRAME_H_ */
diff --git a/sys/amd64/include/signal.h b/sys/amd64/include/signal.h
index deaa06c..e9f739e 100644
--- a/sys/amd64/include/signal.h
+++ b/sys/amd64/include/signal.h
@@ -54,33 +54,35 @@ typedef int sig_atomic_t;
* to the handler to allow it to restore state properly if
* a non-standard exit is performed.
*/
-struct sigcontext {
- int sc_onstack; /* sigstack state to restore */
- int sc_mask; /* signal mask to restore */
- int sc_esp; /* machine state */
- int sc_ebp;
- int sc_isp;
- int sc_eip;
- int sc_efl;
- int sc_es;
- int sc_ds;
- int sc_cs;
- int sc_ss;
- int sc_edi;
- int sc_esi;
- int sc_ebx;
- int sc_edx;
- int sc_ecx;
- int sc_eax;
- int sc_gs;
- int sc_fs;
-# define sc_sp sc_esp
-# define sc_fp sc_ebp
-# define sc_pc sc_eip
-# define sc_ps sc_efl
-# define sc_eflags sc_efl
- int sc_trapno;
- int sc_err;
+typedef unsigned int osigset_t;
+
+struct osigcontext {
+ int sc_onstack; /* sigstack state to restore */
+ osigset_t sc_mask; /* signal mask to restore */
+ int sc_esp; /* machine state */
+ int sc_ebp;
+ int sc_isp;
+ int sc_eip;
+ int sc_efl;
+ int sc_es;
+ int sc_ds;
+ int sc_cs;
+ int sc_ss;
+ int sc_edi;
+ int sc_esi;
+ int sc_ebx;
+ int sc_edx;
+ int sc_ecx;
+ int sc_eax;
+ int sc_gs;
+ int sc_fs;
+#define sc_sp sc_esp
+#define sc_fp sc_ebp
+#define sc_pc sc_eip
+#define sc_ps sc_efl
+#define sc_eflags sc_efl
+ int sc_trapno;
+ int sc_err;
};
#endif /* !_ANSI_SOURCE && !_POSIX_SOURCE */
diff --git a/sys/amd64/include/ucontext.h b/sys/amd64/include/ucontext.h
new file mode 100644
index 0000000..bdf2e1d
--- /dev/null
+++ b/sys/amd64/include/ucontext.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 1999 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE_UCONTEXT_H_
+#define _MACHINE_UCONTEXT_H_ 1
+
+#include <machine/frame.h>
+
+typedef struct {
+ int mc_gs; /* %gs */
+ struct trapframe mc_tf; /* trapframe */
+ int mc_fpregs[28]; /* env87 + fpacc87 + u_long */
+ int __spare__[17];
+} mcontext_t;
+
+#endif /* _MACHINE_UCONTEXT_H_ */
OpenPOWER on IntegriCloud