1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-10-20 02:38:43 +00:00

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.
This commit is contained in:
Marcel Moolenaar 1999-09-29 15:06:27 +00:00
parent 2c42a14602
commit 91078fca0c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=51792
26 changed files with 1870 additions and 489 deletions

View File

@ -138,6 +138,7 @@
#include <alpha/alpha/db_instruction.h>
#include <sys/vnode.h>
#include <miscfs/procfs/procfs.h>
#include <machine/sigframe.h>
#ifdef SYSVSHM
#include <sys/shm.h>
@ -1161,11 +1162,11 @@ DELAY(int n)
* frame pointer, it returns to the user
* specified pc, psl.
*/
void
sendsig(sig_t catcher, int sig, int mask, u_long code)
static void
osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
{
struct proc *p = curproc;
siginfo_t *sip, ksi;
osiginfo_t *sip, ksi;
struct trapframe *frame;
struct sigacts *psp = p->p_sigacts;
int oonstack, fsize, rndfsize;
@ -1174,6 +1175,7 @@ sendsig(sig_t catcher, int sig, int mask, u_long code)
oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
fsize = sizeof ksi;
rndfsize = ((fsize + 15) / 16) * 16;
/*
* Allocate and validate space for the signal handler
* context. Note that if the stack is in P0 space, the
@ -1182,33 +1184,23 @@ sendsig(sig_t catcher, int sig, int mask, u_long code)
* the space with a `brk'.
*/
if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
(psp->ps_sigonstack & sigmask(sig))) {
sip = (siginfo_t *)((caddr_t)psp->ps_sigstk.ss_sp +
SIGISMEMBER(psp->ps_sigonstack, sig)) {
sip = (osiginfo_t *)((caddr_t)psp->ps_sigstk.ss_sp +
psp->ps_sigstk.ss_size - rndfsize);
psp->ps_sigstk.ss_flags |= SS_ONSTACK;
} else
sip = (siginfo_t *)(alpha_pal_rdusp() - rndfsize);
sip = (osiginfo_t *)(alpha_pal_rdusp() - rndfsize);
(void)grow_stack(p, (u_long)sip);
#ifdef DEBUG
if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
printf("sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid,
sig, &oonstack, sip);
#endif
if (useracc((caddr_t)sip, fsize, B_WRITE) == 0) {
#ifdef DEBUG
if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
printf("sendsig(%d): useracc failed on sig %d\n",
p->p_pid, sig);
#endif
/*
* Process has trashed its stack; give it an illegal
* instruction to halt it in its tracks.
*/
SIGACTION(p, SIGILL) = SIG_DFL;
sig = sigmask(SIGILL);
p->p_sigignore &= ~sig;
p->p_sigcatch &= ~sig;
p->p_sigmask &= ~sig;
SIGACTION(p, SIGILL) = SIG_DFL;
SIGDELSET(p->p_sigignore, SIGILL);
SIGDELSET(p->p_sigcatch, SIGILL);
SIGDELSET(p->p_sigmask, SIGILL);
psignal(p, SIGILL);
return;
}
@ -1217,7 +1209,7 @@ sendsig(sig_t catcher, int sig, int mask, u_long code)
* Build the signal context to be used by sigreturn.
*/
ksi.si_sc.sc_onstack = oonstack;
ksi.si_sc.sc_mask = mask;
SIG2OSIG(*mask, ksi.si_sc.sc_mask);
ksi.si_sc.sc_pc = frame->tf_regs[FRAME_PC];
ksi.si_sc.sc_ps = frame->tf_regs[FRAME_PS];
@ -1251,6 +1243,105 @@ sendsig(sig_t catcher, int sig, int mask, u_long code)
ksi.si_code = code;
ksi.si_value.sigval_ptr = NULL; /* XXX */
/*
* copy the frame out to userland.
*/
(void) copyout((caddr_t)&ksi, (caddr_t)sip, fsize);
/*
* Set up the registers to return to sigcode.
*/
frame->tf_regs[FRAME_PC] = PS_STRINGS - (esigcode - sigcode);
frame->tf_regs[FRAME_A0] = sig;
if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig))
frame->tf_regs[FRAME_A1] = (u_int64_t)sip;
else
frame->tf_regs[FRAME_A1] = code;
frame->tf_regs[FRAME_A2] = (u_int64_t)&sip->si_sc;
frame->tf_regs[FRAME_T12] = (u_int64_t)catcher; /* t12 is pv */
alpha_pal_wrusp((unsigned long)sip);
}
void
sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
{
struct proc *p;
struct trapframe *frame;
struct sigacts *psp;
struct sigframe sf, *sfp;
int rndfsize;
p = curproc;
if ((p->p_flag & P_NEWSIGSET) == 0) {
osendsig(catcher, sig, mask, code);
return;
}
frame = p->p_md.md_tf;
psp = p->p_sigacts;
rndfsize = ((sizeof(sf) + 15) / 16) * 16;
/* 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 = *frame;
/*
* Allocate and validate space for the signal handler
* context. Note that if the stack is in P0 space, the
* call to grow() is a nop, and the useracc() check
* will fail if the process has not already allocated
* the space with a `brk'.
*/
if ((psp->ps_flags & SAS_ALTSTACK) != 0 &&
(psp->ps_sigstk.ss_flags & SS_ONSTACK) == 0 &&
SIGISMEMBER(psp->ps_sigonstack, sig)) {
sfp = (struct sigframe *)((caddr_t)psp->ps_sigstk.ss_sp +
psp->ps_sigstk.ss_size - rndfsize);
psp->ps_sigstk.ss_flags |= SS_ONSTACK;
} else
sfp = (struct sigframe *)(alpha_pal_rdusp() - rndfsize);
(void)grow_stack(p, (u_long)sfp);
#ifdef DEBUG
if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
printf("sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid,
sig, &sf, sfp);
#endif
if (useracc((caddr_t)sfp, sizeof(sf), B_WRITE) == 0) {
#ifdef DEBUG
if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
printf("sendsig(%d): useracc failed on sig %d\n",
p->p_pid, sig);
#endif
/*
* Process has trashed its stack; give it an illegal
* instruction to halt it in its tracks.
*/
SIGACTION(p, SIGILL) = SIG_DFL;
SIGDELSET(p->p_sigignore, SIGILL);
SIGDELSET(p->p_sigcatch, SIGILL);
SIGDELSET(p->p_sigmask, SIGILL);
psignal(p, SIGILL);
return;
}
sf.sf_uc.uc_mcontext.mc_tf.tf_regs[FRAME_SP] = alpha_pal_rdusp();
/* save the floating-point state, if necessary, then copy it. */
if (p == fpcurproc) {
alpha_pal_wrfen(1);
savefpstate(&p->p_addr->u_pcb.pcb_fp);
alpha_pal_wrfen(0);
fpcurproc = NULL;
}
sf.sf_uc.uc_mcontext.mc_ownedfp = p->p_md.md_flags & MDP_FPUSED;
bcopy(&p->p_addr->u_pcb.pcb_fp,
(struct fpreg *)sf.sf_uc.uc_mcontext.mc_fpregs,
sizeof(struct fpreg));
sf.sf_uc.uc_mcontext.mc_fp_control = p->p_addr->u_pcb.pcb_fp_control;
#ifdef COMPAT_OSF1
/*
@ -1261,11 +1352,11 @@ sendsig(sig_t catcher, int sig, int mask, u_long code)
/*
* copy the frame out to userland.
*/
(void) copyout((caddr_t)&ksi, (caddr_t)sip, fsize);
(void) copyout((caddr_t)&sf, (caddr_t)sfp, sizeof(sf));
#ifdef DEBUG
if (sigdebug & SDB_FOLLOW)
printf("sendsig(%d): sig %d sip %p code %lx\n", p->p_pid, sig,
sip, code);
printf("sendsig(%d): sig %d sfp %p code %lx\n", p->p_pid, sig,
sfp, code);
#endif
/*
@ -1273,13 +1364,19 @@ sendsig(sig_t catcher, int sig, int mask, u_long code)
*/
frame->tf_regs[FRAME_PC] = PS_STRINGS - (esigcode - sigcode);
frame->tf_regs[FRAME_A0] = sig;
if (p->p_sigacts->ps_siginfo & sigmask(sig))
frame->tf_regs[FRAME_A1] = (u_int64_t)sip;
if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
frame->tf_regs[FRAME_A1] = (u_int64_t)&(sfp->sf_si);
/* Fill in POSIX parts */
sf.sf_si.si_signo = sig;
sf.sf_si.si_code = code;
}
else
frame->tf_regs[FRAME_A1] = code;
frame->tf_regs[FRAME_A2] = (u_int64_t)&sip->si_sc;
frame->tf_regs[FRAME_A2] = (u_int64_t)&(sfp->sf_uc);
frame->tf_regs[FRAME_T12] = (u_int64_t)catcher; /* t12 is pv */
alpha_pal_wrusp((unsigned long)sip);
alpha_pal_wrusp((unsigned long)sfp);
#ifdef DEBUG
if (sigdebug & SDB_FOLLOW)
@ -1301,19 +1398,14 @@ sendsig(sig_t catcher, int sig, int mask, u_long code)
* state to gain improper privileges.
*/
int
sigreturn(struct proc *p,
struct sigreturn_args /* {
struct sigcontext *sigcntxp;
} */ *uap)
osigreturn(struct proc *p,
struct osigreturn_args /* {
struct osigcontext *sigcntxp;
} */ *uap)
{
struct sigcontext *scp, ksc;
struct osigcontext *scp, ksc;
scp = uap->sigcntxp;
#ifdef DEBUG
if (sigdebug & SDB_FOLLOW)
printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp);
#endif
if (ALIGN(scp) != (u_int64_t)scp)
return (EINVAL);
@ -1334,7 +1426,18 @@ sigreturn(struct proc *p,
p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
else
p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
p->p_sigmask = ksc.sc_mask &~ sigcantmask;
/*
* longjmp is still implemented by calling osigreturn. The new
* sigmask is stored in sc_reserved, sc_mask is only used for
* backward compatibility.
*/
if ((p->p_flag & P_NEWSIGSET) == 0) {
OSIG2SIG(ksc.sc_mask, p->p_sigmask);
}
else
p->p_sigmask = *((sigset_t *)(&ksc.sc_reserved[0]));
SIG_CANTMASK(p->p_sigmask);
set_regs(p, (struct reg *)ksc.sc_regs);
p->p_md.md_tf->tf_regs[FRAME_PC] = ksc.sc_pc;
@ -1349,6 +1452,60 @@ sigreturn(struct proc *p,
bcopy((struct fpreg *)ksc.sc_fpregs, &p->p_addr->u_pcb.pcb_fp,
sizeof(struct fpreg));
p->p_addr->u_pcb.pcb_fp_control = ksc.sc_fp_control;
return (EJUSTRETURN);
}
int
sigreturn(struct proc *p,
struct sigreturn_args /* {
ucontext_t *sigcntxp;
} */ *uap)
{
ucontext_t uc, *ucp;
struct pcb *pcb;
ucp = uap->sigcntxp;
if ((p->p_flag & P_NEWSIGSET) == 0)
return (osigreturn(p, (struct osigreturn_args *)uap));
pcb = &p->p_addr->u_pcb;
#ifdef DEBUG
if (sigdebug & SDB_FOLLOW)
printf("sigreturn: pid %d, scp %p\n", p->p_pid, ucp);
#endif
if (ALIGN(ucp) != (u_int64_t)ucp)
return (EINVAL);
/*
* Test and fetch the context structure.
* We grab it all at once for speed.
*/
if (useracc((caddr_t)ucp, sizeof(ucontext_t), B_WRITE) == 0 ||
copyin((caddr_t)ucp, (caddr_t)&uc, sizeof(ucontext_t)))
return (EINVAL);
/*
* Restore the user-supplied information
*/
*p->p_md.md_tf = uc.uc_mcontext.mc_tf;
p->p_md.md_tf->tf_regs[FRAME_PS] |= ALPHA_PSL_USERSET;
p->p_md.md_tf->tf_regs[FRAME_PS] &= ~ALPHA_PSL_USERCLR;
pcb->pcb_hw.apcb_usp = p->p_md.md_tf->tf_regs[FRAME_SP];
alpha_pal_wrusp(pcb->pcb_hw.apcb_usp);
p->p_sigacts->ps_sigstk = uc.uc_stack;
p->p_sigmask = uc.uc_sigmask;
SIG_CANTMASK(p->p_sigmask);
/* XXX ksc.sc_ownedfp ? */
if (p == fpcurproc)
fpcurproc = NULL;
bcopy((struct fpreg *)uc.uc_mcontext.mc_fpregs,
&p->p_addr->u_pcb.pcb_fp, sizeof(struct fpreg));
p->p_addr->u_pcb.pcb_fp_control = uc.uc_mcontext.mc_fp_control;
#ifdef DEBUG
if (sigdebug & SDB_FOLLOW)

View File

@ -0,0 +1,45 @@
/*-
* 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 {
struct osigcontext sf_sc;
osiginfo_t sf_si;
};
struct sigframe {
unsigned long __spare__;
ucontext_t sf_uc;
siginfo_t sf_si;
};
#endif /* _MACHINE_SIGFRAME_H_ */

View File

@ -32,8 +32,8 @@
#define _ALPHA_SIGNAL_H_
typedef long sig_atomic_t;
#ifndef _ANSI_SOURCE
/*
* Information pushed on stack when a signal is delivered.
* This is used by the kernel to restore state following
@ -44,7 +44,9 @@ typedef long sig_atomic_t;
* Note that sc_regs[] and sc_fpregs[]+sc_fpcr are inline
* representations of 'struct reg' and 'struct fpreg', respectively.
*/
struct sigcontext {
typedef unsigned int osigset_t;
struct osigcontext {
long sc_onstack; /* sigstack state to restore */
long sc_mask; /* signal mask to restore */
long sc_pc; /* pc to restore */

View File

@ -0,0 +1,46 @@
/*-
* 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 {
struct trapframe mc_tf;
unsigned long mc_fpregs[32];
unsigned long mc_fpcr;
unsigned long mc_fp_control;
unsigned long mc_apcb_usp;
long mc_ownedfp;
long __spare__[8];
} mcontext_t;
#endif /* _MACHINE_UCONTEXT_H_ */

View File

@ -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);

View File

@ -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:

View File

@ -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:

View File

@ -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;

View File

@ -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

View File

@ -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 *));

View File

@ -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

View File

@ -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_ */

View File

@ -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 */

View File

@ -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_ */

View File

@ -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);

View File

@ -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:

View File

@ -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;

View File

@ -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

View File

@ -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 *));

View File

@ -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

View File

@ -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_ */

View File

@ -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 */

View File

@ -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_ */

View File

@ -132,6 +132,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));
@ -484,79 +485,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;
}
@ -578,11 +566,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;
@ -605,8 +591,136 @@ 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 */
sf.sf_uc.uc_link = NULL;
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;
sf.sf_si.si_pid = p->p_pid;
}
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
@ -619,13 +733,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.
@ -633,7 +749,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;
@ -651,15 +767,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;
@ -670,10 +789,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;
@ -713,7 +832,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
@ -724,10 +842,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);
}
@ -736,11 +851,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);
}
@ -767,7 +878,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;
@ -775,6 +888,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
*
@ -2098,7 +2304,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;
@ -2150,7 +2356,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;

View File

@ -132,6 +132,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));
@ -484,79 +485,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;
}
@ -578,11 +566,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;
@ -605,8 +591,136 @@ 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 */
sf.sf_uc.uc_link = NULL;
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;
sf.sf_si.si_pid = p->p_pid;
}
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
@ -619,13 +733,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.
@ -633,7 +749,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;
@ -651,15 +767,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;
@ -670,10 +789,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;
@ -713,7 +832,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
@ -724,10 +842,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);
}
@ -736,11 +851,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);
}
@ -767,7 +878,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;
@ -775,6 +888,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
*
@ -2098,7 +2304,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;
@ -2150,7 +2356,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;

View File

@ -0,0 +1,45 @@
/*-
* 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 {
struct osigcontext sf_sc;
osiginfo_t sf_si;
};
struct sigframe {
unsigned long __spare__;
ucontext_t sf_uc;
siginfo_t sf_si;
};
#endif /* _MACHINE_SIGFRAME_H_ */