mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-14 10:09:48 +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:
parent
2c42a14602
commit
91078fca0c
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=51792
@ -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)
|
||||
|
45
sys/alpha/include/sigframe.h
Normal file
45
sys/alpha/include/sigframe.h
Normal 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_ */
|
@ -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 */
|
||||
|
46
sys/alpha/include/ucontext.h
Normal file
46
sys/alpha/include/ucontext.h
Normal 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_ */
|
@ -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);
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 *));
|
||||
|
||||
|
@ -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
|
||||
|
86
sys/amd64/include/sigframe.h
Normal file
86
sys/amd64/include/sigframe.h
Normal 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_ */
|
@ -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 */
|
||||
|
43
sys/amd64/include/ucontext.h
Normal file
43
sys/amd64/include/ucontext.h
Normal 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_ */
|
@ -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);
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 *));
|
||||
|
||||
|
@ -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
|
||||
|
86
sys/i386/include/sigframe.h
Normal file
86
sys/i386/include/sigframe.h
Normal 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_ */
|
@ -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 */
|
||||
|
43
sys/i386/include/ucontext.h
Normal file
43
sys/i386/include/ucontext.h
Normal 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_ */
|
@ -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;
|
||||
|
@ -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;
|
||||
|
45
sys/powerpc/include/sigframe.h
Normal file
45
sys/powerpc/include/sigframe.h
Normal 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_ */
|
Loading…
Reference in New Issue
Block a user