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:
marcel 2000-11-30 05:23:49 +00:00
parent 673e30eada
commit 75c76bdc6b
18 changed files with 167 additions and 80 deletions

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