Kill all descendants of the reaper, even if they are descendants of a
subordinate reaper. Also, mark reapers when listing pids. Reported by: Michael Zuo <muh.muhten@gmail.com> PR: 223745 Reviewed by: bapt Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D13183
This commit is contained in:
parent
a72d6c8975
commit
ee50062cfb
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=326122
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user