Don't use p->p_sigstk.ss_flags to keep state of whether the
process is on the alternate stack or not. For compatibility with sigstack(2) state is being updated if such is needed. We now determine whether the process is on the alternate stack by looking at its stack pointer. This allows a process to siglongjmp from a signal handler on the alternate stack to the place of the sigsetjmp on the normal stack. When maintaining state, this would have invalidated the state information and causing a subsequent signal to be delivered on the normal stack instead of the alternate stack. PR: 22286
This commit is contained in:
parent
673e30eada
commit
75c76bdc6b
sys
alpha
amd64
compat/svr4
i386
ia64
kern
pc98
sys
@ -1258,7 +1258,7 @@ osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
|
||||
int oonstack, fsize, rndfsize;
|
||||
|
||||
frame = p->p_md.md_tf;
|
||||
oonstack = p->p_sigstk.ss_flags & SS_ONSTACK;
|
||||
oonstack = sigonstack(alpha_pal_rdusp());
|
||||
fsize = sizeof ksi;
|
||||
rndfsize = ((fsize + 15) / 16) * 16;
|
||||
|
||||
@ -1273,7 +1273,9 @@ osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
|
||||
SIGISMEMBER(psp->ps_sigonstack, sig)) {
|
||||
sip = (osiginfo_t *)((caddr_t)p->p_sigstk.ss_sp +
|
||||
p->p_sigstk.ss_size - rndfsize);
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
#endif
|
||||
} else
|
||||
sip = (osiginfo_t *)(alpha_pal_rdusp() - rndfsize);
|
||||
|
||||
@ -1294,7 +1296,7 @@ osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
|
||||
/*
|
||||
* Build the signal context to be used by sigreturn.
|
||||
*/
|
||||
ksi.si_sc.sc_onstack = oonstack;
|
||||
ksi.si_sc.sc_onstack = (oonstack) ? 1 : 0;
|
||||
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];
|
||||
@ -1358,14 +1360,16 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
|
||||
}
|
||||
|
||||
frame = p->p_md.md_tf;
|
||||
oonstack = (p->p_sigstk.ss_flags & SS_ONSTACK) ? 1 : 0;
|
||||
oonstack = sigonstack(alpha_pal_rdusp());
|
||||
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 = p->p_sigstk;
|
||||
sf.sf_uc.uc_mcontext.mc_onstack = oonstack;
|
||||
sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK)
|
||||
? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
|
||||
sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
|
||||
|
||||
fill_regs(p, (struct reg *)sf.sf_uc.uc_mcontext.mc_regs);
|
||||
sf.sf_uc.uc_mcontext.mc_regs[R_SP] = alpha_pal_rdusp();
|
||||
@ -1390,7 +1394,9 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
|
||||
SIGISMEMBER(psp->ps_sigonstack, sig)) {
|
||||
sfp = (struct sigframe *)((caddr_t)p->p_sigstk.ss_sp +
|
||||
p->p_sigstk.ss_size - rndfsize);
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
#endif
|
||||
} else
|
||||
sfp = (struct sigframe *)(alpha_pal_rdusp() - rndfsize);
|
||||
|
||||
@ -1503,6 +1509,8 @@ osigreturn(struct proc *p,
|
||||
*/
|
||||
if (ksc.sc_regs[R_ZERO] != 0xACEDBADE) /* magic number */
|
||||
return (EINVAL);
|
||||
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
/*
|
||||
* Restore the user-supplied information
|
||||
*/
|
||||
@ -1510,6 +1518,7 @@ osigreturn(struct proc *p,
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
else
|
||||
p->p_sigstk.ss_flags &= ~SS_ONSTACK;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* longjmp is still implemented by calling osigreturn. The new
|
||||
@ -1571,10 +1580,12 @@ sigreturn(struct proc *p,
|
||||
p->p_md.md_tf->tf_regs[FRAME_PC] = uc.uc_mcontext.mc_regs[R_PC];
|
||||
alpha_pal_wrusp(uc.uc_mcontext.mc_regs[R_SP]);
|
||||
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
if (uc.uc_mcontext.mc_onstack & 1)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
else
|
||||
p->p_sigstk.ss_flags &= ~SS_ONSTACK;
|
||||
#endif
|
||||
|
||||
p->p_sigmask = uc.uc_sigmask;
|
||||
SIG_CANTMASK(p->p_sigmask);
|
||||
|
@ -52,6 +52,8 @@
|
||||
|
||||
#include <machine/frame.h>
|
||||
|
||||
#define cpu_getstack(p) (alpha_pal_rdusp())
|
||||
|
||||
/*
|
||||
* Arguments to hardclock and gatherstats encapsulate the previous
|
||||
* machine state in an opaque clockframe. One the Alpha, we use
|
||||
|
@ -583,7 +583,7 @@ osf1_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
|
||||
psp = p->p_sigacts;
|
||||
|
||||
frame = p->p_md.md_tf;
|
||||
oonstack = p->p_sigstk.ss_flags & SS_ONSTACK;
|
||||
oonstack = sigonstack(alpha_pal_rdusp());
|
||||
fsize = sizeof ksi;
|
||||
rndfsize = ((fsize + 15) / 16) * 16;
|
||||
|
||||
@ -618,7 +618,7 @@ osf1_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
|
||||
/*
|
||||
* Build the signal context to be used by sigreturn.
|
||||
*/
|
||||
ksi.si_sc.sc_onstack = oonstack;
|
||||
ksi.si_sc.sc_onstack = (oonstack) ? 1 : 0;
|
||||
bsd_to_osf1_sigset(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];
|
||||
|
@ -494,14 +494,16 @@ osendsig(catcher, sig, mask, code)
|
||||
p = curproc;
|
||||
psp = p->p_sigacts;
|
||||
regs = p->p_md.md_regs;
|
||||
oonstack = p->p_sigstk.ss_flags & SS_ONSTACK;
|
||||
oonstack = sigonstack(regs->tf_esp);
|
||||
|
||||
/* Allocate and validate space for the signal handler context. */
|
||||
if ((p->p_flag & P_ALTSTACK) && !oonstack &&
|
||||
SIGISMEMBER(psp->ps_sigonstack, sig)) {
|
||||
fp = (struct osigframe *)(p->p_sigstk.ss_sp +
|
||||
p->p_sigstk.ss_size - sizeof(struct osigframe));
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
#endif
|
||||
} else
|
||||
fp = (struct osigframe *)regs->tf_esp - 1;
|
||||
|
||||
@ -560,7 +562,7 @@ osendsig(catcher, sig, mask, code)
|
||||
sf.sf_siginfo.si_sc.sc_isp = regs->tf_isp;
|
||||
|
||||
/* Build the signal context to be used by osigreturn(). */
|
||||
sf.sf_siginfo.si_sc.sc_onstack = oonstack;
|
||||
sf.sf_siginfo.si_sc.sc_onstack = (oonstack) ? 1 : 0;
|
||||
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;
|
||||
@ -633,13 +635,15 @@ sendsig(catcher, sig, mask, code)
|
||||
return;
|
||||
}
|
||||
regs = p->p_md.md_regs;
|
||||
oonstack = p->p_sigstk.ss_flags & SS_ONSTACK;
|
||||
oonstack = sigonstack(regs->tf_esp);
|
||||
|
||||
/* Save user context. */
|
||||
bzero(&sf, sizeof(sf));
|
||||
sf.sf_uc.uc_sigmask = *mask;
|
||||
sf.sf_uc.uc_stack = p->p_sigstk;
|
||||
sf.sf_uc.uc_mcontext.mc_onstack = oonstack;
|
||||
sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK)
|
||||
? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
|
||||
sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
|
||||
sf.sf_uc.uc_mcontext.mc_gs = rgs();
|
||||
bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(*regs));
|
||||
|
||||
@ -648,7 +652,9 @@ sendsig(catcher, sig, mask, code)
|
||||
SIGISMEMBER(psp->ps_sigonstack, sig)) {
|
||||
sfp = (struct sigframe *)(p->p_sigstk.ss_sp +
|
||||
p->p_sigstk.ss_size - sizeof(struct sigframe));
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
#endif
|
||||
} else
|
||||
sfp = (struct sigframe *)regs->tf_esp - 1;
|
||||
|
||||
@ -849,10 +855,13 @@ osigreturn(p, uap)
|
||||
regs->tf_ss = scp->sc_ss;
|
||||
regs->tf_isp = scp->sc_isp;
|
||||
|
||||
if (scp->sc_onstack & 01)
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
if (scp->sc_onstack & 1)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
else
|
||||
p->p_sigstk.ss_flags &= ~SS_ONSTACK;
|
||||
#endif
|
||||
|
||||
SIGSETOLD(p->p_sigmask, scp->sc_mask);
|
||||
SIG_CANTMASK(p->p_sigmask);
|
||||
regs->tf_ebp = scp->sc_fp;
|
||||
@ -958,10 +967,13 @@ sigreturn(p, uap)
|
||||
|
||||
bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(*regs));
|
||||
}
|
||||
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
if (ucp->uc_mcontext.mc_onstack & 1)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
else
|
||||
p->p_sigstk.ss_flags &= ~SS_ONSTACK;
|
||||
#endif
|
||||
|
||||
p->p_sigmask = ucp->uc_sigmask;
|
||||
SIG_CANTMASK(p->p_sigmask);
|
||||
|
@ -58,7 +58,8 @@
|
||||
|
||||
#define cpu_exec(p) /* nothing */
|
||||
#define cpu_swapin(p) /* nothing */
|
||||
#define cpu_setstack(p, ap) ((p)->p_md.md_regs[SP] = (ap))
|
||||
#define cpu_getstack(p) ((p)->p_md.md_regs->tf_esp)
|
||||
#define cpu_setstack(p, ap) ((p)->p_md.md_regs->tf_esp = (ap))
|
||||
|
||||
#define CLKF_USERMODE(framep) \
|
||||
((ISPL((framep)->cf_cs) == SEL_UPL) || (framep->cf_eflags & PSL_VM))
|
||||
|
@ -628,7 +628,7 @@ svr4_sys_context(p, uap)
|
||||
case 0:
|
||||
DPRINTF(("getcontext(%p)\n", uap->uc));
|
||||
svr4_getcontext(p, &uc, &p->p_sigmask,
|
||||
p->p_sigstk.ss_flags & SS_ONSTACK);
|
||||
sigonstack(cpu_getstack(p)));
|
||||
return copyout(&uc, uap->uc, sizeof(uc));
|
||||
|
||||
case 1:
|
||||
|
@ -494,14 +494,16 @@ osendsig(catcher, sig, mask, code)
|
||||
p = curproc;
|
||||
psp = p->p_sigacts;
|
||||
regs = p->p_md.md_regs;
|
||||
oonstack = p->p_sigstk.ss_flags & SS_ONSTACK;
|
||||
oonstack = sigonstack(regs->tf_esp);
|
||||
|
||||
/* Allocate and validate space for the signal handler context. */
|
||||
if ((p->p_flag & P_ALTSTACK) && !oonstack &&
|
||||
SIGISMEMBER(psp->ps_sigonstack, sig)) {
|
||||
fp = (struct osigframe *)(p->p_sigstk.ss_sp +
|
||||
p->p_sigstk.ss_size - sizeof(struct osigframe));
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
#endif
|
||||
} else
|
||||
fp = (struct osigframe *)regs->tf_esp - 1;
|
||||
|
||||
@ -560,7 +562,7 @@ osendsig(catcher, sig, mask, code)
|
||||
sf.sf_siginfo.si_sc.sc_isp = regs->tf_isp;
|
||||
|
||||
/* Build the signal context to be used by osigreturn(). */
|
||||
sf.sf_siginfo.si_sc.sc_onstack = oonstack;
|
||||
sf.sf_siginfo.si_sc.sc_onstack = (oonstack) ? 1 : 0;
|
||||
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;
|
||||
@ -633,13 +635,15 @@ sendsig(catcher, sig, mask, code)
|
||||
return;
|
||||
}
|
||||
regs = p->p_md.md_regs;
|
||||
oonstack = p->p_sigstk.ss_flags & SS_ONSTACK;
|
||||
oonstack = sigonstack(regs->tf_esp);
|
||||
|
||||
/* Save user context. */
|
||||
bzero(&sf, sizeof(sf));
|
||||
sf.sf_uc.uc_sigmask = *mask;
|
||||
sf.sf_uc.uc_stack = p->p_sigstk;
|
||||
sf.sf_uc.uc_mcontext.mc_onstack = oonstack;
|
||||
sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK)
|
||||
? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
|
||||
sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
|
||||
sf.sf_uc.uc_mcontext.mc_gs = rgs();
|
||||
bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(*regs));
|
||||
|
||||
@ -648,7 +652,9 @@ sendsig(catcher, sig, mask, code)
|
||||
SIGISMEMBER(psp->ps_sigonstack, sig)) {
|
||||
sfp = (struct sigframe *)(p->p_sigstk.ss_sp +
|
||||
p->p_sigstk.ss_size - sizeof(struct sigframe));
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
#endif
|
||||
} else
|
||||
sfp = (struct sigframe *)regs->tf_esp - 1;
|
||||
|
||||
@ -849,10 +855,13 @@ osigreturn(p, uap)
|
||||
regs->tf_ss = scp->sc_ss;
|
||||
regs->tf_isp = scp->sc_isp;
|
||||
|
||||
if (scp->sc_onstack & 01)
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
if (scp->sc_onstack & 1)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
else
|
||||
p->p_sigstk.ss_flags &= ~SS_ONSTACK;
|
||||
#endif
|
||||
|
||||
SIGSETOLD(p->p_sigmask, scp->sc_mask);
|
||||
SIG_CANTMASK(p->p_sigmask);
|
||||
regs->tf_ebp = scp->sc_fp;
|
||||
@ -958,10 +967,13 @@ sigreturn(p, uap)
|
||||
|
||||
bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(*regs));
|
||||
}
|
||||
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
if (ucp->uc_mcontext.mc_onstack & 1)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
else
|
||||
p->p_sigstk.ss_flags &= ~SS_ONSTACK;
|
||||
#endif
|
||||
|
||||
p->p_sigmask = ucp->uc_sigmask;
|
||||
SIG_CANTMASK(p->p_sigmask);
|
||||
|
@ -58,7 +58,8 @@
|
||||
|
||||
#define cpu_exec(p) /* nothing */
|
||||
#define cpu_swapin(p) /* nothing */
|
||||
#define cpu_setstack(p, ap) ((p)->p_md.md_regs[SP] = (ap))
|
||||
#define cpu_getstack(p) ((p)->p_md.md_regs->tf_esp)
|
||||
#define cpu_setstack(p, ap) ((p)->p_md.md_regs->tf_esp = (ap))
|
||||
|
||||
#define CLKF_USERMODE(framep) \
|
||||
((ISPL((framep)->cf_cs) == SEL_UPL) || (framep->cf_eflags & PSL_VM))
|
||||
|
@ -163,7 +163,6 @@ struct linux_new_utsname {
|
||||
|
||||
/* sigaltstack */
|
||||
#define LINUX_MINSIGSTKSZ 2048
|
||||
#define LINUX_SS_ONSTACK_BC 0 /* backwards compat SS_ONSTACK */
|
||||
#define LINUX_SS_ONSTACK 1
|
||||
#define LINUX_SS_DISABLE 2
|
||||
|
||||
|
@ -82,8 +82,6 @@ linux_to_bsd_sigaltstack(int lsa)
|
||||
bsa |= SS_DISABLE;
|
||||
if (lsa & LINUX_SS_ONSTACK)
|
||||
bsa |= SS_ONSTACK;
|
||||
if (lsa == LINUX_SS_ONSTACK_BC)
|
||||
bsa = SS_ONSTACK;
|
||||
return (bsa);
|
||||
}
|
||||
|
||||
|
@ -205,7 +205,7 @@ linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
|
||||
int oonstack;
|
||||
|
||||
regs = p->p_md.md_regs;
|
||||
oonstack = p->p_sigstk.ss_flags & SS_ONSTACK;
|
||||
oonstack = sigonstack(regs->tf_esp);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Linux-emul(%ld): linux_rt_sendsig(%p, %d, %p, %lu)\n",
|
||||
@ -218,10 +218,8 @@ linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
|
||||
SIGISMEMBER(p->p_sigacts->ps_sigonstack, sig)) {
|
||||
fp = (struct linux_rt_sigframe *)(p->p_sigstk.ss_sp +
|
||||
p->p_sigstk.ss_size - sizeof(struct linux_rt_sigframe));
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
} else {
|
||||
} else
|
||||
fp = (struct linux_rt_sigframe *)regs->tf_esp - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* grow() will return FALSE if the fp will not fit inside the stack
|
||||
@ -240,8 +238,8 @@ linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
|
||||
SIGDELSET(p->p_sigcatch, SIGILL);
|
||||
SIGDELSET(p->p_sigmask, SIGILL);
|
||||
#ifdef DEBUG
|
||||
printf("Linux-emul(%ld): linux_rt_sendsig -- bad stack %p, SS_ONSTACK: 0x%x ",
|
||||
(long)p->p_pid, fp, p->p_sigstk.ss_flags & SS_ONSTACK);
|
||||
printf("Linux-emul(%ld): linux_rt_sendsig -- bad stack %p, "
|
||||
"oonstack=%x\n", (long)p->p_pid, fp, oonstack);
|
||||
#endif
|
||||
psignal(p, SIGILL);
|
||||
return;
|
||||
@ -271,9 +269,9 @@ linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
|
||||
frame.sf_sc.uc_link = NULL; /* XXX ??? */
|
||||
|
||||
frame.sf_sc.uc_stack.ss_sp = p->p_sigstk.ss_sp;
|
||||
frame.sf_sc.uc_stack.ss_flags =
|
||||
bsd_to_linux_sigaltstack(p->p_sigstk.ss_flags);
|
||||
frame.sf_sc.uc_stack.ss_size = p->p_sigstk.ss_size;
|
||||
frame.sf_sc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK)
|
||||
? ((oonstack) ? LINUX_SS_ONSTACK : 0) : LINUX_SS_DISABLE;
|
||||
|
||||
bsd_to_linux_sigset(mask, &frame.sf_sc.uc_sigmask);
|
||||
|
||||
@ -298,9 +296,10 @@ linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
|
||||
frame.sf_sc.uc_mcontext.sc_trapno = code; /* XXX ???? */
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Linux-emul(%ld): rt_sendsig flags: 0x%x, sp: %p, ss: 0x%x, mask: 0x%x\n",
|
||||
(long)p->p_pid, frame.sf_sc.uc_stack.ss_flags, p->p_sigstk.ss_sp,
|
||||
p->p_sigstk.ss_size, frame.sf_sc.uc_mcontext.sc_mask);
|
||||
printf("Linux-emul(%ld): rt_sendsig flags: 0x%x, sp: %p, ss: 0x%x, "
|
||||
"mask: 0x%x\n", (long)p->p_pid, frame.sf_sc.uc_stack.ss_flags,
|
||||
p->p_sigstk.ss_sp, p->p_sigstk.ss_size,
|
||||
frame.sf_sc.uc_mcontext.sc_mask);
|
||||
#endif
|
||||
|
||||
if (copyout(&frame, fp, sizeof(frame)) != 0) {
|
||||
@ -355,7 +354,7 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
|
||||
}
|
||||
|
||||
regs = p->p_md.md_regs;
|
||||
oonstack = p->p_sigstk.ss_flags & SS_ONSTACK;
|
||||
oonstack = sigonstack(regs->tf_esp);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Linux-emul(%ld): linux_sendsig(%p, %d, %p, %lu)\n",
|
||||
@ -369,10 +368,8 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
|
||||
SIGISMEMBER(p->p_sigacts->ps_sigonstack, sig)) {
|
||||
fp = (struct linux_sigframe *)(p->p_sigstk.ss_sp +
|
||||
p->p_sigstk.ss_size - sizeof(struct linux_sigframe));
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
} else {
|
||||
} else
|
||||
fp = (struct linux_sigframe *)regs->tf_esp - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* grow() will return FALSE if the fp will not fit inside the stack
|
||||
@ -521,7 +518,6 @@ linux_sigreturn(p, args)
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
p->p_sigstk.ss_flags &= ~SS_ONSTACK;
|
||||
lmask.__bits[0] = frame.sf_sc.sc_mask;
|
||||
for (i = 0; i < (LINUX_NSIG_WORDS-1); i++)
|
||||
lmask.__bits[i+1] = frame.sf_extramask[i];
|
||||
@ -621,7 +617,6 @@ linux_rt_sigreturn(p, args)
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
p->p_sigstk.ss_flags &= ~SS_ONSTACK;
|
||||
linux_to_bsd_sigset(&uc.uc_sigmask, &p->p_sigmask);
|
||||
SIG_CANTMASK(p->p_sigmask);
|
||||
|
||||
|
@ -404,7 +404,7 @@ svr4_sendsig(catcher, sig, mask, code)
|
||||
#endif
|
||||
|
||||
tf = p->p_md.md_regs;
|
||||
oonstack = p->p_sigstk.ss_flags & SS_ONSTACK;
|
||||
oonstack = sigonstack(tf->tf_esp);
|
||||
|
||||
/*
|
||||
* Allocate space for the signal handler context.
|
||||
|
@ -785,7 +785,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
|
||||
int oonstack, rndfsize;
|
||||
|
||||
frame = p->p_md.md_tf;
|
||||
oonstack = (p->p_sigstk.ss_flags & SS_ONSTACK) ? 1 : 0;
|
||||
oonstack = sigonstack(frame->tf_r[FRAME_SP]);
|
||||
rndfsize = ((sizeof(sf) + 15) / 16) * 16;
|
||||
|
||||
/*
|
||||
@ -798,7 +798,10 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
|
||||
bzero(&sf, sizeof(struct sigframe));
|
||||
sf.sf_uc.uc_sigmask = *mask;
|
||||
sf.sf_uc.uc_stack = p->p_sigstk;
|
||||
sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK)
|
||||
? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
|
||||
sf.sf_uc.uc_mcontext.mc_flags = IA64_MC_FLAG_ONSTACK;
|
||||
sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
|
||||
|
||||
sf.sf_uc.uc_mcontext.mc_nat = 0; /* XXX */
|
||||
sf.sf_uc.uc_mcontext.mc_sp = frame->tf_r[FRAME_SP];
|
||||
@ -837,8 +840,9 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
|
||||
sbs = (u_int64_t) p->p_sigstk.ss_sp;
|
||||
sfp = (struct sigframe *)((caddr_t)p->p_sigstk.ss_sp +
|
||||
p->p_sigstk.ss_size - rndfsize);
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
sf.sf_uc.uc_mcontext.mc_onstack |= 1;
|
||||
#endif
|
||||
} else
|
||||
sfp = (struct sigframe *)(frame->tf_r[FRAME_SP] - rndfsize);
|
||||
|
||||
@ -1009,10 +1013,12 @@ sigreturn(struct proc *p,
|
||||
|
||||
frame->tf_r[FRAME_SP] = mcp->mc_sp;
|
||||
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
if (uc.uc_mcontext.mc_onstack & 1)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
else
|
||||
p->p_sigstk.ss_flags &= ~SS_ONSTACK;
|
||||
#endif
|
||||
|
||||
p->p_sigmask = uc.uc_sigmask;
|
||||
SIG_CANTMASK(p->p_sigmask);
|
||||
|
@ -52,6 +52,8 @@
|
||||
|
||||
#include <machine/frame.h>
|
||||
|
||||
#define cpu_getstack(p) ((p)->p_md.md_tf->tf_r[FRAME_SP])
|
||||
|
||||
/*
|
||||
* Arguments to hardclock and gatherstats encapsulate the previous
|
||||
* machine state in an opaque clockframe. One the Alpha, we use
|
||||
|
@ -782,20 +782,25 @@ osigstack(p, uap)
|
||||
register struct osigstack_args *uap;
|
||||
{
|
||||
struct sigstack ss;
|
||||
int error = 0;
|
||||
int error;
|
||||
|
||||
ss.ss_sp = p->p_sigstk.ss_sp;
|
||||
ss.ss_onstack = p->p_sigstk.ss_flags & SS_ONSTACK;
|
||||
if (uap->oss && (error = copyout(&ss, uap->oss,
|
||||
sizeof(struct sigstack))))
|
||||
return (error);
|
||||
if (uap->nss && (error = copyin(uap->nss, &ss, sizeof(ss))) == 0) {
|
||||
if (uap->oss != NULL) {
|
||||
ss.ss_sp = p->p_sigstk.ss_sp;
|
||||
ss.ss_onstack = sigonstack(cpu_getstack(p));
|
||||
error = copyout(&ss, uap->oss, sizeof(struct sigstack));
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (uap->nss != NULL) {
|
||||
if ((error = copyin(uap->nss, &ss, sizeof(ss))) != 0)
|
||||
return (error);
|
||||
p->p_sigstk.ss_sp = ss.ss_sp;
|
||||
p->p_sigstk.ss_size = 0;
|
||||
p->p_sigstk.ss_flags |= ss.ss_onstack & SS_ONSTACK;
|
||||
p->p_flag |= P_ALTSTACK;
|
||||
}
|
||||
return (error);
|
||||
return (0);
|
||||
}
|
||||
#endif /* COMPAT_43 || COMPAT_SUNOS */
|
||||
|
||||
@ -812,28 +817,33 @@ sigaltstack(p, uap)
|
||||
register struct sigaltstack_args *uap;
|
||||
{
|
||||
stack_t ss;
|
||||
int error;
|
||||
int error, oonstack;
|
||||
|
||||
if ((p->p_flag & P_ALTSTACK) == 0)
|
||||
p->p_sigstk.ss_flags |= SS_DISABLE;
|
||||
if (uap->oss && (error = copyout(&p->p_sigstk, uap->oss,
|
||||
sizeof(stack_t))))
|
||||
return (error);
|
||||
if (uap->ss == 0)
|
||||
return (0);
|
||||
if ((error = copyin(uap->ss, &ss, sizeof(ss))))
|
||||
return (error);
|
||||
if (ss.ss_flags & SS_DISABLE) {
|
||||
if (p->p_sigstk.ss_flags & SS_ONSTACK)
|
||||
return (EINVAL);
|
||||
p->p_flag &= ~P_ALTSTACK;
|
||||
p->p_sigstk.ss_flags = ss.ss_flags;
|
||||
return (0);
|
||||
oonstack = sigonstack(cpu_getstack(p));
|
||||
|
||||
if (uap->oss != NULL) {
|
||||
ss = p->p_sigstk;
|
||||
ss.ss_flags = (p->p_flag & P_ALTSTACK)
|
||||
? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
|
||||
if ((error = copyout(&ss, uap->oss, sizeof(stack_t))) != 0)
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (uap->ss != NULL) {
|
||||
if (oonstack)
|
||||
return (EPERM);
|
||||
if ((error = copyin(uap->ss, &ss, sizeof(ss))) != 0)
|
||||
return (error);
|
||||
if ((ss.ss_flags & ~SS_DISABLE) != 0)
|
||||
return (EINVAL);
|
||||
if (!(ss.ss_flags & SS_DISABLE)) {
|
||||
if (ss.ss_size < p->p_sysent->sv_minsigstksz)
|
||||
return (ENOMEM);
|
||||
p->p_sigstk = ss;
|
||||
p->p_flag |= P_ALTSTACK;
|
||||
} else
|
||||
p->p_flag &= ~P_ALTSTACK;
|
||||
}
|
||||
if (ss.ss_size < p->p_sysent->sv_minsigstksz)
|
||||
return (ENOMEM);
|
||||
p->p_flag |= P_ALTSTACK;
|
||||
p->p_sigstk = ss;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -495,14 +495,16 @@ osendsig(catcher, sig, mask, code)
|
||||
p = curproc;
|
||||
psp = p->p_sigacts;
|
||||
regs = p->p_md.md_regs;
|
||||
oonstack = p->p_sigstk.ss_flags & SS_ONSTACK;
|
||||
oonstack = sigonstack(regs->tf_esp);
|
||||
|
||||
/* Allocate and validate space for the signal handler context. */
|
||||
if ((p->p_flag & P_ALTSTACK) && !oonstack &&
|
||||
SIGISMEMBER(psp->ps_sigonstack, sig)) {
|
||||
fp = (struct osigframe *)(p->p_sigstk.ss_sp +
|
||||
p->p_sigstk.ss_size - sizeof(struct osigframe));
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
#endif
|
||||
} else
|
||||
fp = (struct osigframe *)regs->tf_esp - 1;
|
||||
|
||||
@ -561,7 +563,7 @@ osendsig(catcher, sig, mask, code)
|
||||
sf.sf_siginfo.si_sc.sc_isp = regs->tf_isp;
|
||||
|
||||
/* Build the signal context to be used by osigreturn(). */
|
||||
sf.sf_siginfo.si_sc.sc_onstack = oonstack;
|
||||
sf.sf_siginfo.si_sc.sc_onstack = (oonstack) ? 1 : 0;
|
||||
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;
|
||||
@ -634,13 +636,15 @@ sendsig(catcher, sig, mask, code)
|
||||
return;
|
||||
}
|
||||
regs = p->p_md.md_regs;
|
||||
oonstack = p->p_sigstk.ss_flags & SS_ONSTACK;
|
||||
oonstack = sigonstack(regs->tf_esp);
|
||||
|
||||
/* Save user context. */
|
||||
bzero(&sf, sizeof(sf));
|
||||
sf.sf_uc.uc_sigmask = *mask;
|
||||
sf.sf_uc.uc_stack = p->p_sigstk;
|
||||
sf.sf_uc.uc_mcontext.mc_onstack = oonstack;
|
||||
sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK)
|
||||
? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
|
||||
sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
|
||||
sf.sf_uc.uc_mcontext.mc_gs = rgs();
|
||||
bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(*regs));
|
||||
|
||||
@ -649,7 +653,9 @@ sendsig(catcher, sig, mask, code)
|
||||
SIGISMEMBER(psp->ps_sigonstack, sig)) {
|
||||
sfp = (struct sigframe *)(p->p_sigstk.ss_sp +
|
||||
p->p_sigstk.ss_size - sizeof(struct sigframe));
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
#endif
|
||||
} else
|
||||
sfp = (struct sigframe *)regs->tf_esp - 1;
|
||||
|
||||
@ -850,10 +856,13 @@ osigreturn(p, uap)
|
||||
regs->tf_ss = scp->sc_ss;
|
||||
regs->tf_isp = scp->sc_isp;
|
||||
|
||||
if (scp->sc_onstack & 01)
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
if (scp->sc_onstack & 1)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
else
|
||||
p->p_sigstk.ss_flags &= ~SS_ONSTACK;
|
||||
#endif
|
||||
|
||||
SIGSETOLD(p->p_sigmask, scp->sc_mask);
|
||||
SIG_CANTMASK(p->p_sigmask);
|
||||
regs->tf_ebp = scp->sc_fp;
|
||||
@ -959,10 +968,13 @@ sigreturn(p, uap)
|
||||
|
||||
bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(*regs));
|
||||
}
|
||||
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
if (ucp->uc_mcontext.mc_onstack & 1)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
else
|
||||
p->p_sigstk.ss_flags &= ~SS_ONSTACK;
|
||||
#endif
|
||||
|
||||
p->p_sigmask = ucp->uc_sigmask;
|
||||
SIG_CANTMASK(p->p_sigmask);
|
||||
|
@ -495,14 +495,16 @@ osendsig(catcher, sig, mask, code)
|
||||
p = curproc;
|
||||
psp = p->p_sigacts;
|
||||
regs = p->p_md.md_regs;
|
||||
oonstack = p->p_sigstk.ss_flags & SS_ONSTACK;
|
||||
oonstack = sigonstack(regs->tf_esp);
|
||||
|
||||
/* Allocate and validate space for the signal handler context. */
|
||||
if ((p->p_flag & P_ALTSTACK) && !oonstack &&
|
||||
SIGISMEMBER(psp->ps_sigonstack, sig)) {
|
||||
fp = (struct osigframe *)(p->p_sigstk.ss_sp +
|
||||
p->p_sigstk.ss_size - sizeof(struct osigframe));
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
#endif
|
||||
} else
|
||||
fp = (struct osigframe *)regs->tf_esp - 1;
|
||||
|
||||
@ -561,7 +563,7 @@ osendsig(catcher, sig, mask, code)
|
||||
sf.sf_siginfo.si_sc.sc_isp = regs->tf_isp;
|
||||
|
||||
/* Build the signal context to be used by osigreturn(). */
|
||||
sf.sf_siginfo.si_sc.sc_onstack = oonstack;
|
||||
sf.sf_siginfo.si_sc.sc_onstack = (oonstack) ? 1 : 0;
|
||||
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;
|
||||
@ -634,13 +636,15 @@ sendsig(catcher, sig, mask, code)
|
||||
return;
|
||||
}
|
||||
regs = p->p_md.md_regs;
|
||||
oonstack = p->p_sigstk.ss_flags & SS_ONSTACK;
|
||||
oonstack = sigonstack(regs->tf_esp);
|
||||
|
||||
/* Save user context. */
|
||||
bzero(&sf, sizeof(sf));
|
||||
sf.sf_uc.uc_sigmask = *mask;
|
||||
sf.sf_uc.uc_stack = p->p_sigstk;
|
||||
sf.sf_uc.uc_mcontext.mc_onstack = oonstack;
|
||||
sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK)
|
||||
? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
|
||||
sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
|
||||
sf.sf_uc.uc_mcontext.mc_gs = rgs();
|
||||
bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(*regs));
|
||||
|
||||
@ -649,7 +653,9 @@ sendsig(catcher, sig, mask, code)
|
||||
SIGISMEMBER(psp->ps_sigonstack, sig)) {
|
||||
sfp = (struct sigframe *)(p->p_sigstk.ss_sp +
|
||||
p->p_sigstk.ss_size - sizeof(struct sigframe));
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
#endif
|
||||
} else
|
||||
sfp = (struct sigframe *)regs->tf_esp - 1;
|
||||
|
||||
@ -850,10 +856,13 @@ osigreturn(p, uap)
|
||||
regs->tf_ss = scp->sc_ss;
|
||||
regs->tf_isp = scp->sc_isp;
|
||||
|
||||
if (scp->sc_onstack & 01)
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
if (scp->sc_onstack & 1)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
else
|
||||
p->p_sigstk.ss_flags &= ~SS_ONSTACK;
|
||||
#endif
|
||||
|
||||
SIGSETOLD(p->p_sigmask, scp->sc_mask);
|
||||
SIG_CANTMASK(p->p_sigmask);
|
||||
regs->tf_ebp = scp->sc_fp;
|
||||
@ -959,10 +968,13 @@ sigreturn(p, uap)
|
||||
|
||||
bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(*regs));
|
||||
}
|
||||
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
if (ucp->uc_mcontext.mc_onstack & 1)
|
||||
p->p_sigstk.ss_flags |= SS_ONSTACK;
|
||||
else
|
||||
p->p_sigstk.ss_flags &= ~SS_ONSTACK;
|
||||
#endif
|
||||
|
||||
p->p_sigmask = ucp->uc_sigmask;
|
||||
SIG_CANTMASK(p->p_sigmask);
|
||||
|
@ -395,6 +395,20 @@ MALLOC_DECLARE(M_ZOMBIE);
|
||||
MALLOC_DECLARE(M_PARGS);
|
||||
#endif
|
||||
|
||||
static __inline int
|
||||
sigonstack(size_t sp)
|
||||
{
|
||||
register struct proc *p = curproc;
|
||||
|
||||
return ((p->p_flag & P_ALTSTACK) ?
|
||||
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
||||
((p->p_sigstk.ss_size == 0) ? (p->p_sigstk.ss_flags & SS_ONSTACK) :
|
||||
((sp - (size_t)p->p_sigstk.ss_sp) < p->p_sigstk.ss_size))
|
||||
#else
|
||||
((sp - (size_t)p->p_sigstk.ss_sp) < p->p_sigstk.ss_size)
|
||||
#endif
|
||||
: 0);
|
||||
}
|
||||
|
||||
/* Handy macro to determine of p1 can mangle p2 */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user