summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_sig.c
diff options
context:
space:
mode:
authormelifaro <melifaro@FreeBSD.org>2014-08-23 14:58:31 +0000
committermelifaro <melifaro@FreeBSD.org>2014-08-23 14:58:31 +0000
commitcf94663e69b2c927e4a44dcb922c93483f11bc29 (patch)
treef43a461c97f3db054606f6367939a61652f0db97 /sys/kern/kern_sig.c
parent2e65f120c886a9d09b274b1953783df2b995e799 (diff)
parent19be009a4f8eb0d239ec3e465b0a9b2a2947dcf8 (diff)
downloadFreeBSD-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.c81
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;
OpenPOWER on IntegriCloud