From d034d459daf039d21ff432e30dfb48c27ac4d09d Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Thu, 30 Nov 2000 05:23:49 +0000 Subject: [PATCH] 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 --- sys/alpha/alpha/machdep.c | 19 +++++++--- sys/alpha/include/cpu.h | 2 ++ sys/alpha/osf1/osf1_signal.c | 4 +-- sys/amd64/amd64/machdep.c | 22 +++++++++--- sys/amd64/include/cpu.h | 3 +- sys/compat/svr4/svr4_signal.c | 2 +- sys/i386/i386/machdep.c | 22 +++++++++--- sys/i386/include/cpu.h | 3 +- sys/i386/linux/linux.h | 1 - sys/i386/linux/linux_machdep.c | 2 -- sys/i386/linux/linux_sysvec.c | 29 +++++++-------- sys/i386/svr4/svr4_machdep.c | 2 +- sys/ia64/ia64/machdep.c | 10 ++++-- sys/ia64/include/cpu.h | 2 ++ sys/kern/kern_sig.c | 66 +++++++++++++++++++--------------- sys/pc98/i386/machdep.c | 22 +++++++++--- sys/pc98/pc98/machdep.c | 22 +++++++++--- sys/sys/proc.h | 14 ++++++++ 18 files changed, 167 insertions(+), 80 deletions(-) diff --git a/sys/alpha/alpha/machdep.c b/sys/alpha/alpha/machdep.c index f048bbbc483..9c3ace5ff70 100644 --- a/sys/alpha/alpha/machdep.c +++ b/sys/alpha/alpha/machdep.c @@ -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); diff --git a/sys/alpha/include/cpu.h b/sys/alpha/include/cpu.h index a0be38fe0f5..3da213f66d1 100644 --- a/sys/alpha/include/cpu.h +++ b/sys/alpha/include/cpu.h @@ -52,6 +52,8 @@ #include +#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 diff --git a/sys/alpha/osf1/osf1_signal.c b/sys/alpha/osf1/osf1_signal.c index 738b0a45d05..770ccf32d01 100644 --- a/sys/alpha/osf1/osf1_signal.c +++ b/sys/alpha/osf1/osf1_signal.c @@ -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]; diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 2e6416745bb..5c059291c6b 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -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); diff --git a/sys/amd64/include/cpu.h b/sys/amd64/include/cpu.h index 669af64c1b4..9293ba29b74 100644 --- a/sys/amd64/include/cpu.h +++ b/sys/amd64/include/cpu.h @@ -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)) diff --git a/sys/compat/svr4/svr4_signal.c b/sys/compat/svr4/svr4_signal.c index c80538edb42..84f8ce07725 100644 --- a/sys/compat/svr4/svr4_signal.c +++ b/sys/compat/svr4/svr4_signal.c @@ -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: diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 2e6416745bb..5c059291c6b 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -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); diff --git a/sys/i386/include/cpu.h b/sys/i386/include/cpu.h index 669af64c1b4..9293ba29b74 100644 --- a/sys/i386/include/cpu.h +++ b/sys/i386/include/cpu.h @@ -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)) diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h index d253897cd94..8aff68a2ec9 100644 --- a/sys/i386/linux/linux.h +++ b/sys/i386/linux/linux.h @@ -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 diff --git a/sys/i386/linux/linux_machdep.c b/sys/i386/linux/linux_machdep.c index c152a108d2b..7e4b37e4b32 100644 --- a/sys/i386/linux/linux_machdep.c +++ b/sys/i386/linux/linux_machdep.c @@ -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); } diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index 7d7fccbdfc2..cd944a2a488 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -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); diff --git a/sys/i386/svr4/svr4_machdep.c b/sys/i386/svr4/svr4_machdep.c index 38c5cc8fb50..018fb74d3b0 100644 --- a/sys/i386/svr4/svr4_machdep.c +++ b/sys/i386/svr4/svr4_machdep.c @@ -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. diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index bed49d53010..bc0ae1becb4 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -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); diff --git a/sys/ia64/include/cpu.h b/sys/ia64/include/cpu.h index c6ebd1c6145..d581447357a 100644 --- a/sys/ia64/include/cpu.h +++ b/sys/ia64/include/cpu.h @@ -52,6 +52,8 @@ #include +#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 diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 345bc31e49d..434420beab2 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -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); } diff --git a/sys/pc98/i386/machdep.c b/sys/pc98/i386/machdep.c index 0320ad0fa07..a7567492aab 100644 --- a/sys/pc98/i386/machdep.c +++ b/sys/pc98/i386/machdep.c @@ -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); diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c index 0320ad0fa07..a7567492aab 100644 --- a/sys/pc98/pc98/machdep.c +++ b/sys/pc98/pc98/machdep.c @@ -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); diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 67d525ca0fb..f52b2d2e653 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -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 */