summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2017-11-30 14:19:47 +0000
committerkib <kib@FreeBSD.org>2017-11-30 14:19:47 +0000
commit0b2a3c56aecae9e26b20770d50852ed085d9f2d6 (patch)
treef57974fdbb41666b9c441ba15dcd597cb6883d06
parentc0cf69ad8b844c24520a60fbfe6e8095d1843abd (diff)
downloadFreeBSD-src-0b2a3c56aecae9e26b20770d50852ed085d9f2d6.zip
FreeBSD-src-0b2a3c56aecae9e26b20770d50852ed085d9f2d6.tar.gz
MFC r326122:
Kill all descendants of the reaper, even if they are descendants of a subordinate reaper. Also, mark reapers when listing pids. PR: 223745
-rw-r--r--lib/libc/sys/procctl.27
-rw-r--r--sys/kern/kern_procctl.c95
-rw-r--r--sys/sys/procctl.h1
3 files changed, 78 insertions, 25 deletions
diff --git a/lib/libc/sys/procctl.2 b/lib/libc/sys/procctl.2
index da73fb0..9d90f56 100644
--- a/lib/libc/sys/procctl.2
+++ b/lib/libc/sys/procctl.2
@@ -29,7 +29,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 27, 2016
+.Dd November 21, 2017
.Dt PROCCTL 2
.Os
.Sh NAME
@@ -211,7 +211,7 @@ of the process.
The
.Fa pi_flags
field returns the following flags, further describing the descendant:
-.Bl -tag -width "Dv REAPER_PIDINFO_VALID"
+.Bl -tag -width "Dv REAPER_PIDINFO_REAPER"
.It Dv REAPER_PIDINFO_VALID
Set to indicate that the
.Vt procctl_reaper_pidinfo
@@ -226,6 +226,9 @@ of the returned array.
The
.Fa pi_pid
field identifies the direct child of the reaper.
+.It Dv REAPER_PIDINFO_REAPER
+The reported process is itself a reaper.
+The descendants of the subordinate reaper are not reported.
.El
.It Dv PROC_REAP_KILL
Request to deliver a signal to some subset of the descendants of the reaper.
diff --git a/sys/kern/kern_procctl.c b/sys/kern/kern_procctl.c
index e875170..dddc6b9 100644
--- a/sys/kern/kern_procctl.c
+++ b/sys/kern/kern_procctl.c
@@ -221,6 +221,8 @@ reap_getpids(struct thread *td, struct proc *p, struct procctl_reaper_pids *rp)
pip->pi_flags = REAPER_PIDINFO_VALID;
if (proc_realparent(p2) == reap)
pip->pi_flags |= REAPER_PIDINFO_CHILD;
+ if ((p2->p_treeflag & P_TREE_REAPER) != 0)
+ pip->pi_flags |= REAPER_PIDINFO_REAPER;
i++;
}
sx_sunlock(&proctree_lock);
@@ -231,19 +233,59 @@ reap_getpids(struct thread *td, struct proc *p, struct procctl_reaper_pids *rp)
return (error);
}
+static void
+reap_kill_proc(struct thread *td, struct proc *p2, ksiginfo_t *ksi,
+ struct procctl_reaper_kill *rk, int *error)
+{
+ int error1;
+
+ PROC_LOCK(p2);
+ error1 = p_cansignal(td, p2, rk->rk_sig);
+ if (error1 == 0) {
+ pksignal(p2, rk->rk_sig, ksi);
+ rk->rk_killed++;
+ *error = error1;
+ } else if (*error == ESRCH) {
+ rk->rk_fpid = p2->p_pid;
+ *error = error1;
+ }
+ PROC_UNLOCK(p2);
+}
+
+struct reap_kill_tracker {
+ struct proc *parent;
+ TAILQ_ENTRY(reap_kill_tracker) link;
+};
+
+TAILQ_HEAD(reap_kill_tracker_head, reap_kill_tracker);
+
+static void
+reap_kill_sched(struct reap_kill_tracker_head *tracker, struct proc *p2)
+{
+ struct reap_kill_tracker *t;
+
+ t = malloc(sizeof(struct reap_kill_tracker), M_TEMP, M_WAITOK);
+ t->parent = p2;
+ TAILQ_INSERT_TAIL(tracker, t, link);
+}
+
static int
reap_kill(struct thread *td, struct proc *p, struct procctl_reaper_kill *rk)
{
struct proc *reap, *p2;
ksiginfo_t ksi;
- int error, error1;
+ struct reap_kill_tracker_head tracker;
+ struct reap_kill_tracker *t;
+ int error;
sx_assert(&proctree_lock, SX_LOCKED);
if (IN_CAPABILITY_MODE(td))
return (ECAPMODE);
- if (rk->rk_sig <= 0 || rk->rk_sig > _SIG_MAXSIG)
- return (EINVAL);
- if ((rk->rk_flags & ~(REAPER_KILL_CHILDREN | REAPER_KILL_SUBTREE)) != 0)
+ if (rk->rk_sig <= 0 || rk->rk_sig > _SIG_MAXSIG ||
+ (rk->rk_flags & ~(REAPER_KILL_CHILDREN |
+ REAPER_KILL_SUBTREE)) != 0 || (rk->rk_flags &
+ (REAPER_KILL_CHILDREN | REAPER_KILL_SUBTREE)) ==
+ (REAPER_KILL_CHILDREN | REAPER_KILL_SUBTREE))
return (EINVAL);
PROC_UNLOCK(p);
reap = (p->p_treeflag & P_TREE_REAPER) == 0 ? p->p_reaper : p;
@@ -255,26 +297,33 @@ reap_kill(struct thread *td, struct proc *p, struct procctl_reaper_kill *rk)
error = ESRCH;
rk->rk_killed = 0;
rk->rk_fpid = -1;
- for (p2 = (rk->rk_flags & REAPER_KILL_CHILDREN) != 0 ?
- LIST_FIRST(&reap->p_children) : LIST_FIRST(&reap->p_reaplist);
- p2 != NULL;
- p2 = (rk->rk_flags & REAPER_KILL_CHILDREN) != 0 ?
- LIST_NEXT(p2, p_sibling) : LIST_NEXT(p2, p_reapsibling)) {
- if ((rk->rk_flags & REAPER_KILL_SUBTREE) != 0 &&
- p2->p_reapsubtree != rk->rk_subtree)
- continue;
- PROC_LOCK(p2);
- error1 = p_cansignal(td, p2, rk->rk_sig);
- if (error1 == 0) {
- pksignal(p2, rk->rk_sig, &ksi);
- rk->rk_killed++;
- error = error1;
- } else if (error == ESRCH) {
- error = error1;
- rk->rk_fpid = p2->p_pid;
+ if ((rk->rk_flags & REAPER_KILL_CHILDREN) != 0) {
+ for (p2 = LIST_FIRST(&reap->p_children); p2 != NULL;
+ p2 = LIST_NEXT(p2, p_sibling)) {
+ reap_kill_proc(td, p2, &ksi, rk, &error);
+ /*
+ * Do not end the loop on error, signal
+ * everything we can.
+ */
+ }
+ } else {
+ TAILQ_INIT(&tracker);
+ reap_kill_sched(&tracker, reap);
+ while ((t = TAILQ_FIRST(&tracker)) != NULL) {
+ MPASS((t->parent->p_treeflag & P_TREE_REAPER) != 0);
+ TAILQ_REMOVE(&tracker, t, link);
+ for (p2 = LIST_FIRST(&t->parent->p_reaplist); p2 != NULL;
+ p2 = LIST_NEXT(p2, p_reapsibling)) {
+ if (t->parent == reap &&
+ (rk->rk_flags & REAPER_KILL_SUBTREE) != 0 &&
+ p2->p_reapsubtree != rk->rk_subtree)
+ continue;
+ if ((p2->p_treeflag & P_TREE_REAPER) != 0)
+ reap_kill_sched(&tracker, p2);
+ reap_kill_proc(td, p2, &ksi, rk, &error);
+ }
+ free(t, M_TEMP);
}
- PROC_UNLOCK(p2);
- /* Do not end the loop on error, signal everything we can. */
}
PROC_LOCK(p);
return (error);
diff --git a/sys/sys/procctl.h b/sys/sys/procctl.h
index 53bb6ca..8c938c5 100644
--- a/sys/sys/procctl.h
+++ b/sys/sys/procctl.h
@@ -83,6 +83,7 @@ struct procctl_reaper_pidinfo {
#define REAPER_PIDINFO_VALID 0x00000001
#define REAPER_PIDINFO_CHILD 0x00000002
+#define REAPER_PIDINFO_REAPER 0x00000004
struct procctl_reaper_pids {
u_int rp_count;
OpenPOWER on IntegriCloud