summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbluhm <bluhm@openbsd.org>2019-05-13 19:21:31 +0000
committerbluhm <bluhm@openbsd.org>2019-05-13 19:21:31 +0000
commit788422d65be41111bc05f25ec194535e3ae7eb6c (patch)
tree2a0e4cfda82fe14e76fd02a67a366b04f0eddc90
parentDo not check for IFF_RUNNING inside bstp_initialization(). (diff)
downloadwireguard-openbsd-788422d65be41111bc05f25ec194535e3ae7eb6c.tar.xz
wireguard-openbsd-788422d65be41111bc05f25ec194535e3ae7eb6c.zip
When killing a process, the signal is handled by any thread that
does not block the signal. If all threads block the signal, we delivered it to the main thread. This does not conform to POSIX. If any thread unblocks the signal, it should be delivered immediately to this thread. Mark such signals pending at the process instead of a single thread. Then any thread can handle it later. OK kettenis@ guenther@
-rw-r--r--sys/kern/exec_elf.c4
-rw-r--r--sys/kern/kern_exit.c4
-rw-r--r--sys/kern/kern_sig.c54
-rw-r--r--sys/kern/tty.c6
-rw-r--r--sys/nfs/nfs_socket.c7
-rw-r--r--sys/sys/proc.h3
-rw-r--r--sys/sys/signalvar.h18
-rw-r--r--sys/sys/sysctl.h4
8 files changed, 59 insertions, 41 deletions
diff --git a/sys/kern/exec_elf.c b/sys/kern/exec_elf.c
index 9d5639a24a7..24adf0dbed6 100644
--- a/sys/kern/exec_elf.c
+++ b/sys/kern/exec_elf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: exec_elf.c,v 1.150 2019/05/11 19:59:26 deraadt Exp $ */
+/* $OpenBSD: exec_elf.c,v 1.151 2019/05/13 19:21:31 bluhm Exp $ */
/*
* Copyright (c) 1996 Per Fogelstrom
@@ -1211,7 +1211,7 @@ coredump_notes_elf(struct proc *p, void *iocookie, size_t *sizep)
cpi.cpi_signo = p->p_sisig;
cpi.cpi_sigcode = p->p_sicode;
- cpi.cpi_sigpend = p->p_siglist;
+ cpi.cpi_sigpend = p->p_siglist | pr->ps_siglist;
cpi.cpi_sigmask = p->p_sigmask;
cpi.cpi_sigignore = pr->ps_sigacts->ps_sigignore;
cpi.cpi_sigcatch = pr->ps_sigacts->ps_sigcatch;
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 918ea4dc1bd..bff9a2c5ef7 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_exit.c,v 1.173 2019/01/23 22:39:47 tedu Exp $ */
+/* $OpenBSD: kern_exit.c,v 1.174 2019/05/13 19:21:31 bluhm Exp $ */
/* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */
/*
@@ -180,6 +180,8 @@ exit1(struct proc *p, int rv, int flags)
}
}
p->p_siglist = 0;
+ if ((p->p_flag & P_THREAD) == 0)
+ pr->ps_siglist = 0;
#if NKCOV > 0
kcov_exit(p);
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index fc538174c1a..4e3efa9c736 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sig.c,v 1.229 2019/05/01 06:26:42 dlg Exp $ */
+/* $OpenBSD: kern_sig.c,v 1.230 2019/05/13 19:21:31 bluhm Exp $ */
/* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */
/*
@@ -364,7 +364,8 @@ setsigvec(struct proc *p, int signum, struct sigaction *sa)
*/
if (sa->sa_handler == SIG_IGN ||
(sigprop[signum] & SA_IGNORE && sa->sa_handler == SIG_DFL)) {
- atomic_clearbits_int(&p->p_siglist, bit);
+ atomic_clearbits_int(&p->p_siglist, bit);
+ atomic_clearbits_int(&p->p_p->ps_siglist, bit);
if (signum != SIGCONT)
ps->ps_sigignore |= bit; /* easier in psignal */
ps->ps_sigcatch &= ~bit;
@@ -419,6 +420,7 @@ execsigs(struct proc *p)
if (nc != SIGCONT)
ps->ps_sigignore |= mask;
atomic_clearbits_int(&p->p_siglist, mask);
+ atomic_clearbits_int(&p->p_p->ps_siglist, mask);
}
ps->ps_sigact[nc] = SIG_DFL;
}
@@ -472,7 +474,7 @@ int
sys_sigpending(struct proc *p, void *v, register_t *retval)
{
- *retval = p->p_siglist;
+ *retval = p->p_siglist | p->p_p->ps_siglist;
return (0);
}
@@ -875,7 +877,6 @@ psignal(struct proc *p, int signum)
/*
* type = SPROCESS process signal, can be diverted (sigwait())
- * XXX if blocked in all threads, mark as pending in struct process
* type = STHREAD thread signal, but should be propagated if unhandled
* type = SPROPAGATED propagated to this thread, so don't propagate again
*/
@@ -885,6 +886,7 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
int s, prop;
sig_t action;
int mask;
+ int *siglist;
struct process *pr = p->p_p;
struct proc *q;
int wakeparent = 0;
@@ -907,7 +909,7 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
if (pr->ps_flags & PS_COREDUMP && signum == SIGKILL) {
if (pr->ps_single != NULL)
p = pr->ps_single;
- atomic_setbits_int(&p->p_siglist, mask);
+ atomic_setbits_int(&p->p_p->ps_siglist, mask);
return;
}
@@ -962,7 +964,6 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
*/
if (pr->ps_flags & PS_TRACED) {
action = SIG_DFL;
- atomic_setbits_int(&p->p_siglist, mask);
} else {
/*
* If the signal is being ignored,
@@ -992,17 +993,23 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
if (prop & SA_TTYSTOP && pr->ps_pgrp->pg_jobc == 0)
return;
}
-
- atomic_setbits_int(&p->p_siglist, mask);
}
-
- if (prop & SA_CONT)
- atomic_clearbits_int(&p->p_siglist, stopsigmask);
-
+ /*
+ * If delivered to process, mark as pending there. Continue and stop
+ * signals will be propagated to all threads. So they are always
+ * marked at thread level.
+ */
+ siglist = (type == SPROCESS) ? &pr->ps_siglist : &p->p_siglist;
+ if (prop & SA_CONT) {
+ siglist = &p->p_siglist;
+ atomic_clearbits_int(siglist, stopsigmask);
+ }
if (prop & SA_STOP) {
- atomic_clearbits_int(&p->p_siglist, contsigmask);
+ siglist = &p->p_siglist;
+ atomic_clearbits_int(siglist, contsigmask);
atomic_clearbits_int(&p->p_flag, P_CONTINUED);
}
+ atomic_setbits_int(siglist, mask);
/*
* XXX delay processing of SA_STOP signals unless action == SIG_DFL?
@@ -1045,7 +1052,7 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
* be awakened.
*/
if ((prop & SA_CONT) && action == SIG_DFL) {
- atomic_clearbits_int(&p->p_siglist, mask);
+ atomic_clearbits_int(siglist, mask);
goto out;
}
/*
@@ -1059,7 +1066,7 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
*/
if (pr->ps_flags & PS_PPWAIT)
goto out;
- atomic_clearbits_int(&p->p_siglist, mask);
+ atomic_clearbits_int(siglist, mask);
p->p_xstat = signum;
proc_stop(p, 0);
goto out;
@@ -1102,7 +1109,7 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
atomic_clearbits_int(&p->p_flag, P_SUSPSIG);
wakeparent = 1;
if (action == SIG_DFL)
- atomic_clearbits_int(&p->p_siglist, mask);
+ atomic_clearbits_int(siglist, mask);
if (action == SIG_CATCH)
goto runfast;
if (p->p_wchan == 0)
@@ -1116,7 +1123,7 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
* Already stopped, don't need to stop again.
* (If we did the shell could get confused.)
*/
- atomic_clearbits_int(&p->p_siglist, mask);
+ atomic_clearbits_int(siglist, mask);
goto out;
}
@@ -1181,7 +1188,7 @@ issignal(struct proc *p)
int s;
for (;;) {
- mask = p->p_siglist & ~p->p_sigmask;
+ mask = SIGPENDING(p);
if (pr->ps_flags & PS_PPWAIT)
mask &= ~stopsigmask;
if (mask == 0) /* no signal to send */
@@ -1189,6 +1196,7 @@ issignal(struct proc *p)
signum = ffs((long)mask);
mask = sigmask(signum);
atomic_clearbits_int(&p->p_siglist, mask);
+ atomic_clearbits_int(&p->p_p->ps_siglist, mask);
/*
* We should see pending but ignored signals
@@ -1243,6 +1251,7 @@ issignal(struct proc *p)
/* take the signal! */
atomic_clearbits_int(&p->p_siglist, mask);
+ atomic_clearbits_int(&p->p_p->ps_siglist, mask);
}
prop = sigprop[signum];
@@ -1638,7 +1647,8 @@ coredump_write(void *cookie, enum uio_seg segflg, const void *data, size_t len)
csize = len;
do {
- if (io->io_proc->p_siglist & sigmask(SIGKILL))
+ if (sigmask(SIGKILL) &
+ (io->io_proc->p_siglist | io->io_proc->p_p->ps_siglist))
return (EINTR);
/* Rest of the loop sleeps with lock held, so... */
@@ -1740,8 +1750,8 @@ sys___thrsigdivert(struct proc *p, void *v, register_t *retval)
if (smask & mask) {
if (p->p_siglist & smask)
m = &p->p_siglist;
- else if (pr->ps_mainproc->p_siglist & smask)
- m = &pr->ps_mainproc->p_siglist;
+ else if (pr->ps_siglist & smask)
+ m = &pr->ps_siglist;
else {
/* signal got eaten by someone else? */
continue;
@@ -1868,7 +1878,7 @@ userret(struct proc *p)
KERNEL_UNLOCK();
}
- if (SIGPENDING(p)) {
+ if (SIGPENDING(p) != 0) {
KERNEL_LOCK();
while ((signum = CURSIG(p)) != 0)
postsig(p, signum);
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index c57e8ca9a4f..fd54b0fca75 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tty.c,v 1.143 2018/09/06 11:50:54 jsg Exp $ */
+/* $OpenBSD: tty.c,v 1.144 2019/05/13 19:21:31 bluhm Exp $ */
/* $NetBSD: tty.c,v 1.68.4.2 1996/06/06 16:04:52 thorpej Exp $ */
/*-
@@ -1676,11 +1676,11 @@ ttycheckoutq(struct tty *tp, int wait)
hiwat = tp->t_hiwat;
s = spltty();
- oldsig = wait ? curproc->p_siglist : 0;
+ oldsig = wait ? SIGPENDING(curproc) : 0;
if (tp->t_outq.c_cc > hiwat + TTHIWATMINSPACE)
while (tp->t_outq.c_cc > hiwat) {
ttstart(tp);
- if (wait == 0 || curproc->p_siglist != oldsig) {
+ if (wait == 0 || SIGPENDING(curproc) != oldsig) {
splx(s);
return (0);
}
diff --git a/sys/nfs/nfs_socket.c b/sys/nfs/nfs_socket.c
index bbde6883301..7d5a76a5a32 100644
--- a/sys/nfs/nfs_socket.c
+++ b/sys/nfs/nfs_socket.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nfs_socket.c,v 1.132 2018/11/09 14:14:32 claudio Exp $ */
+/* $OpenBSD: nfs_socket.c,v 1.133 2019/05/13 19:21:31 bluhm Exp $ */
/* $NetBSD: nfs_socket.c,v 1.27 1996/04/15 20:20:00 thorpej Exp $ */
/*
@@ -1225,9 +1225,8 @@ nfs_sigintr(struct nfsmount *nmp, struct nfsreq *rep, struct proc *p)
return (EINTR);
if (!(nmp->nm_flag & NFSMNT_INT))
return (0);
- if (p && p->p_siglist &&
- (((p->p_siglist & ~p->p_sigmask) &
- ~p->p_p->ps_sigacts->ps_sigignore) & NFSINT_SIGMASK))
+ if (p && (SIGPENDING(p) & ~p->p_p->ps_sigacts->ps_sigignore &
+ NFSINT_SIGMASK))
return (EINTR);
return (0);
}
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index ac4b33cd867..1886a7d3826 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: proc.h,v 1.264 2019/05/12 13:18:58 mpi Exp $ */
+/* $OpenBSD: proc.h,v 1.265 2019/05/13 19:21:31 bluhm Exp $ */
/* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */
/*-
@@ -186,6 +186,7 @@ struct process {
#define ps_startzero ps_klist
struct klist ps_klist; /* knotes attached to this process */
int ps_flags; /* PS_* flags. */
+ int ps_siglist; /* Signals pending for the process. */
struct proc *ps_single; /* Single threading to this thread. */
int ps_singlecount; /* Not yet suspended threads. */
diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h
index 11c0b68a70e..6181b28c63c 100644
--- a/sys/sys/signalvar.h
+++ b/sys/sys/signalvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: signalvar.h,v 1.35 2018/12/17 14:51:57 visa Exp $ */
+/* $OpenBSD: signalvar.h,v 1.36 2019/05/13 19:21:31 bluhm Exp $ */
/* $NetBSD: signalvar.h,v 1.17 1996/04/22 01:23:31 christos Exp $ */
/*
@@ -67,24 +67,30 @@ struct sigacts {
/*
* Check if process p has an unmasked signal pending.
+ * Return mask of pending signals.
*/
-#define SIGPENDING(p) (((p)->p_siglist & ~(p)->p_sigmask) != 0)
+#define SIGPENDING(p) \
+ (((p)->p_siglist | (p)->p_p->ps_siglist) & ~(p)->p_sigmask)
/*
* Determine signal that should be delivered to process p, the current
* process, 0 if none. If there is a pending stop signal with default
* action, the process stops in issignal().
*/
-#define CURSIG(p) \
- (((p)->p_siglist == 0 || \
+#define CURSIG(p) \
+ ((((p)->p_siglist | (p)->p_p->ps_siglist) == 0 || \
(((p)->p_p->ps_flags & PS_TRACED) == 0 && \
- ((p)->p_siglist & ~(p)->p_sigmask) == 0)) ? \
+ SIGPENDING(p) == 0)) ? \
0 : issignal(p))
/*
* Clear a pending signal from a process.
*/
-#define CLRSIG(p, sig) atomic_clearbits_int(&(p)->p_siglist, sigmask(sig))
+#define CLRSIG(p, sig) do { \
+ int _mask = sigmask(sig); \
+ atomic_clearbits_int(&(p)->p_siglist, _mask); \
+ atomic_clearbits_int(&(p)->p_p->ps_siglist, _mask); \
+} while (0)
/*
* Signal properties and actions.
diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
index 60c67f511c7..4599ca70ce6 100644
--- a/sys/sys/sysctl.h
+++ b/sys/sys/sysctl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sysctl.h,v 1.185 2019/05/09 14:59:30 claudio Exp $ */
+/* $OpenBSD: sysctl.h,v 1.186 2019/05/13 19:21:31 bluhm Exp $ */
/* $NetBSD: sysctl.h,v 1.16 1996/04/09 20:55:36 cgd Exp $ */
/*
@@ -595,7 +595,7 @@ do { \
(kp)->p_tracep = PTRTOINT64((pr)->ps_tracevp); \
(kp)->p_traceflag = (pr)->ps_traceflag; \
\
- (kp)->p_siglist = (p)->p_siglist; \
+ (kp)->p_siglist = (p)->p_siglist | (pr)->ps_siglist; \
(kp)->p_sigmask = (p)->p_sigmask; \
(kp)->p_sigignore = (sa) ? (sa)->ps_sigignore : 0; \
(kp)->p_sigcatch = (sa) ? (sa)->ps_sigcatch : 0; \