svn commit: r315159 - head/sys/kern
Konstantin Belousov
kib at FreeBSD.org
Sun Mar 12 13:58:53 UTC 2017
Author: kib
Date: Sun Mar 12 13:58:51 2017
New Revision: 315159
URL: https://svnweb.freebsd.org/changeset/base/315159
Log:
Avoid reusing p_ksi while it is on queue.
When sending SIGCHLD informing reaper that a zombie was reparented to
it, we might race with the situation where the previous parent still
not finished delivering SIGCHLD and having its p_ksi structure on the
signal queue. While on queue, the ksi should not be used for another
send.
Fix this by copying p_ksi into newly allocated ksi, which is directly
put onto reaper sigqueue. The later ensures that siginfo for reaper
SIGCHLD is always present, similar to guarantees for siginfo of child.
Reported by: bdrewery
Discussed with: jilles
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Modified:
head/sys/kern/kern_exit.c
Modified: head/sys/kern/kern_exit.c
==============================================================================
--- head/sys/kern/kern_exit.c Sun Mar 12 13:53:13 2017 (r315158)
+++ head/sys/kern/kern_exit.c Sun Mar 12 13:58:51 2017 (r315159)
@@ -189,6 +189,7 @@ exit1(struct thread *td, int rval, int s
{
struct proc *p, *nq, *q, *t;
struct thread *tdt;
+ ksiginfo_t *ksi, *ksi1;
mtx_assert(&Giant, MA_NOTOWNED);
KASSERT(rval == 0 || signo == 0, ("exit1 rv %d sig %d", rval, signo));
@@ -449,14 +450,32 @@ exit1(struct thread *td, int rval, int s
wakeup(q->p_reaper);
for (; q != NULL; q = nq) {
nq = LIST_NEXT(q, p_sibling);
+ ksi = ksiginfo_alloc(TRUE);
PROC_LOCK(q);
q->p_sigparent = SIGCHLD;
if (!(q->p_flag & P_TRACED)) {
proc_reparent(q, q->p_reaper);
if (q->p_state == PRS_ZOMBIE) {
+ /*
+ * Inform reaper about the reparented
+ * zombie, since wait(2) has something
+ * new to report. Guarantee queueing
+ * of the SIGCHLD signal, similar to
+ * the _exit() behaviour, by providing
+ * our ksiginfo. Ksi is freed by the
+ * signal delivery.
+ */
+ if (q->p_ksi == NULL) {
+ ksi1 = NULL;
+ } else {
+ ksiginfo_copy(q->p_ksi, ksi);
+ ksi->ksi_flags |= KSI_INS;
+ ksi1 = ksi;
+ ksi = NULL;
+ }
PROC_LOCK(q->p_reaper);
- pksignal(q->p_reaper, SIGCHLD, q->p_ksi);
+ pksignal(q->p_reaper, SIGCHLD, ksi1);
PROC_UNLOCK(q->p_reaper);
}
} else {
@@ -489,6 +508,8 @@ exit1(struct thread *td, int rval, int s
kern_psignal(q, SIGKILL);
}
PROC_UNLOCK(q);
+ if (ksi != NULL)
+ ksiginfo_free(ksi);
}
/*
More information about the svn-src-all
mailing list