diff options
author | melifaro <melifaro@FreeBSD.org> | 2014-08-23 14:58:31 +0000 |
---|---|---|
committer | melifaro <melifaro@FreeBSD.org> | 2014-08-23 14:58:31 +0000 |
commit | cf94663e69b2c927e4a44dcb922c93483f11bc29 (patch) | |
tree | f43a461c97f3db054606f6367939a61652f0db97 /sys/kern/kern_sig.c | |
parent | 2e65f120c886a9d09b274b1953783df2b995e799 (diff) | |
parent | 19be009a4f8eb0d239ec3e465b0a9b2a2947dcf8 (diff) | |
download | FreeBSD-src-cf94663e69b2c927e4a44dcb922c93483f11bc29.zip FreeBSD-src-cf94663e69b2c927e4a44dcb922c93483f11bc29.tar.gz |
Sync to HEAD@r270409.
Diffstat (limited to 'sys/kern/kern_sig.c')
-rw-r--r-- | sys/kern/kern_sig.c | 81 |
1 files changed, 48 insertions, 33 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 561ea0a..8810bf3 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -621,6 +621,15 @@ sig_ffs(sigset_t *set) return (0); } +static bool +sigact_flag_test(struct sigaction *act, int flag) +{ + + return ((act->sa_flags & flag) != 0 && + (__sighandler_t *)act->sa_sigaction != SIG_IGN && + (__sighandler_t *)act->sa_sigaction != SIG_DFL); +} + /* * kern_sigaction * sigaction @@ -639,6 +648,10 @@ kern_sigaction(td, sig, act, oact, flags) if (!_SIG_VALID(sig)) return (EINVAL); + if (act != NULL && (act->sa_flags & ~(SA_ONSTACK | SA_RESTART | + SA_RESETHAND | SA_NOCLDSTOP | SA_NODEFER | SA_NOCLDWAIT | + SA_SIGINFO)) != 0) + return (EINVAL); PROC_LOCK(p); ps = p->p_sigacts; @@ -679,7 +692,7 @@ kern_sigaction(td, sig, act, oact, flags) ps->ps_catchmask[_SIG_IDX(sig)] = act->sa_mask; SIG_CANTMASK(ps->ps_catchmask[_SIG_IDX(sig)]); - if (act->sa_flags & SA_SIGINFO) { + if (sigact_flag_test(act, SA_SIGINFO)) { ps->ps_sigact[_SIG_IDX(sig)] = (__sighandler_t *)act->sa_sigaction; SIGADDSET(ps->ps_siginfo, sig); @@ -687,19 +700,19 @@ kern_sigaction(td, sig, act, oact, flags) ps->ps_sigact[_SIG_IDX(sig)] = act->sa_handler; SIGDELSET(ps->ps_siginfo, sig); } - if (!(act->sa_flags & SA_RESTART)) + if (!sigact_flag_test(act, SA_RESTART)) SIGADDSET(ps->ps_sigintr, sig); else SIGDELSET(ps->ps_sigintr, sig); - if (act->sa_flags & SA_ONSTACK) + if (sigact_flag_test(act, SA_ONSTACK)) SIGADDSET(ps->ps_sigonstack, sig); else SIGDELSET(ps->ps_sigonstack, sig); - if (act->sa_flags & SA_RESETHAND) + if (sigact_flag_test(act, SA_RESETHAND)) SIGADDSET(ps->ps_sigreset, sig); else SIGDELSET(ps->ps_sigreset, sig); - if (act->sa_flags & SA_NODEFER) + if (sigact_flag_test(act, SA_NODEFER)) SIGADDSET(ps->ps_signodefer, sig); else SIGDELSET(ps->ps_signodefer, sig); @@ -900,14 +913,36 @@ siginit(p) PROC_LOCK(p); ps = p->p_sigacts; mtx_lock(&ps->ps_mtx); - for (i = 1; i <= NSIG; i++) - if (sigprop(i) & SA_IGNORE && i != SIGCONT) + for (i = 1; i <= NSIG; i++) { + if (sigprop(i) & SA_IGNORE && i != SIGCONT) { SIGADDSET(ps->ps_sigignore, i); + SIGADDSET(ps->ps_sigintr, i); + } + } mtx_unlock(&ps->ps_mtx); PROC_UNLOCK(p); } /* + * Reset specified signal to the default disposition. + */ +static void +sigdflt(struct sigacts *ps, int sig) +{ + + mtx_assert(&ps->ps_mtx, MA_OWNED); + SIGDELSET(ps->ps_sigcatch, sig); + if ((sigprop(sig) & SA_IGNORE) != 0 && sig != SIGCONT) + SIGADDSET(ps->ps_sigignore, sig); + ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL; + SIGDELSET(ps->ps_siginfo, sig); + SIGADDSET(ps->ps_sigintr, sig); + SIGDELSET(ps->ps_sigonstack, sig); + SIGDELSET(ps->ps_sigreset, sig); + SIGDELSET(ps->ps_signodefer, sig); +} + +/* * Reset signals for an exec of the specified process. */ void @@ -928,13 +963,9 @@ execsigs(struct proc *p) mtx_lock(&ps->ps_mtx); while (SIGNOTEMPTY(ps->ps_sigcatch)) { sig = sig_ffs(&ps->ps_sigcatch); - SIGDELSET(ps->ps_sigcatch, sig); - if (sigprop(sig) & SA_IGNORE) { - if (sig != SIGCONT) - SIGADDSET(ps->ps_sigignore, sig); + sigdflt(ps, sig); + if ((sigprop(sig) & SA_IGNORE) != 0) sigqueue_delete_proc(p, sig); - } - ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL; } /* * Reset stack state to the user stack. @@ -1888,16 +1919,8 @@ trapsignal(struct thread *td, ksiginfo_t *ksi) SIGADDSET(mask, sig); kern_sigprocmask(td, SIG_BLOCK, &mask, NULL, SIGPROCMASK_PROC_LOCKED | SIGPROCMASK_PS_LOCKED); - if (SIGISMEMBER(ps->ps_sigreset, sig)) { - /* - * See kern_sigaction() for origin of this code. - */ - SIGDELSET(ps->ps_sigcatch, sig); - if (sig != SIGCONT && - sigprop(sig) & SA_IGNORE) - SIGADDSET(ps->ps_sigignore, sig); - ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL; - } + if (SIGISMEMBER(ps->ps_sigreset, sig)) + sigdflt(ps, sig); mtx_unlock(&ps->ps_mtx); } else { /* @@ -2840,16 +2863,8 @@ postsig(sig) kern_sigprocmask(td, SIG_BLOCK, &mask, NULL, SIGPROCMASK_PROC_LOCKED | SIGPROCMASK_PS_LOCKED); - if (SIGISMEMBER(ps->ps_sigreset, sig)) { - /* - * See kern_sigaction() for origin of this code. - */ - SIGDELSET(ps->ps_sigcatch, sig); - if (sig != SIGCONT && - sigprop(sig) & SA_IGNORE) - SIGADDSET(ps->ps_sigignore, sig); - ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL; - } + if (SIGISMEMBER(ps->ps_sigreset, sig)) + sigdflt(ps, sig); td->td_ru.ru_nsignals++; if (p->p_sig == sig) { p->p_code = 0; |