Page MenuHomeFreeBSD

D34522.id103757.diff
No OneTemporary

D34522.id103757.diff

Index: sys/kern/kern_exit.c
===================================================================
--- sys/kern/kern_exit.c
+++ sys/kern/kern_exit.c
@@ -471,6 +471,7 @@
*/
p->p_list.le_prev = NULL;
#endif
+ prison_proc_unlink(p->p_ucred->cr_prison, p);
sx_xunlock(&allproc_lock);
sx_xlock(&proctree_lock);
Index: sys/kern/kern_fork.c
===================================================================
--- sys/kern/kern_fork.c
+++ sys/kern/kern_fork.c
@@ -397,6 +397,7 @@
sx_xlock(&allproc_lock);
LIST_INSERT_HEAD(&allproc, p2, p_list);
allproc_gen++;
+ prison_proc_link(p2->p_ucred->cr_prison, p2);
sx_xunlock(&allproc_lock);
sx_xlock(PIDHASHLOCK(p2->p_pid));
Index: sys/kern/kern_jail.c
===================================================================
--- sys/kern/kern_jail.c
+++ sys/kern/kern_jail.c
@@ -145,6 +145,8 @@
static int prison_lock_xlock(struct prison *pr, int flags);
static void prison_free_not_last(struct prison *pr);
static void prison_proc_free_not_last(struct prison *pr);
+static void prison_proc_relink(struct prison *opr, struct prison *npr,
+ struct proc *p);
static void prison_set_allow_locked(struct prison *pr, unsigned flag,
int enable);
static char *prison_path(struct prison *pr1, struct prison *pr2);
@@ -2646,6 +2648,7 @@
rctl_proc_ucred_changed(p, newcred);
crfree(newcred);
#endif
+ prison_proc_relink(oldcred->cr_prison, pr, p);
prison_deref(oldcred->cr_prison, drflags);
crfree(oldcred);
@@ -2917,6 +2920,32 @@
#endif
}
+void
+prison_proc_link(struct prison *pr, struct proc *p)
+{
+
+ sx_assert(&allproc_lock, SA_XLOCKED);
+ LIST_INSERT_HEAD(&pr->pr_proclist, p, p_jaillist);
+}
+
+void
+prison_proc_unlink(struct prison *pr, struct proc *p)
+{
+
+ sx_assert(&allproc_lock, SA_XLOCKED);
+ LIST_REMOVE(p, p_jaillist);
+}
+
+static void
+prison_proc_relink(struct prison *opr, struct prison *npr, struct proc *p)
+{
+
+ sx_xlock(&allproc_lock);
+ prison_proc_unlink(opr, p);
+ prison_proc_link(npr, p);
+ sx_xunlock(&allproc_lock);
+}
+
/*
* Complete a call to either prison_free or prison_proc_free.
*/
@@ -2938,6 +2967,58 @@
prison_deref(pr, drflags);
}
+static void
+prison_kill_processes_cb(struct proc *p, void *arg __unused)
+{
+
+ kern_psignal(p, SIGKILL);
+}
+
+void
+prison_proc_iterate(struct prison *pr, void (*cb)(struct proc *, void *),
+ void *cbarg)
+{
+ struct prison *ppr;
+ struct proc *p;
+
+ MPASS(pr != NULL);
+
+ if (pr->pr_childcount == 0) {
+ if (LIST_EMPTY(&pr->pr_proclist)) {
+ return;
+ }
+ sx_slock(&allproc_lock);
+ FOREACH_PROC_IN_PRISON(p, pr) {
+ if (p->p_state == PRS_NEW)
+ continue;
+ PROC_LOCK(p);
+ cb(p, cbarg);
+ PROC_UNLOCK(p);
+ }
+ sx_sunlock(&allproc_lock);
+ return;
+ }
+
+ sx_slock(&allproc_lock);
+ FOREACH_PROC_IN_SYSTEM(p) {
+ if (p->p_state == PRS_NEW)
+ continue;
+ PROC_LOCK(p);
+ if (p->p_ucred != NULL) {
+ for (ppr = p->p_ucred->cr_prison;
+ ppr != &prison0;
+ ppr = ppr->pr_parent) {
+ if (ppr == pr) {
+ cb(p, cbarg);
+ break;
+ }
+ }
+ }
+ PROC_UNLOCK(p);
+ }
+ sx_sunlock(&allproc_lock);
+}
+
/*
* Remove a prison reference and/or user reference (usually).
* This assumes context that allows sleeping (for allprison_lock),
@@ -2951,7 +3032,6 @@
{
struct prisonlist freeprison;
struct prison *killpr, *rpr, *ppr, *tpr;
- struct proc *p;
killpr = NULL;
TAILQ_INIT(&freeprison);
@@ -3063,23 +3143,8 @@
sx_xunlock(&allprison_lock);
/* Kill any processes attached to a killed prison. */
- if (killpr != NULL) {
- sx_slock(&allproc_lock);
- FOREACH_PROC_IN_SYSTEM(p) {
- PROC_LOCK(p);
- if (p->p_state != PRS_NEW && p->p_ucred != NULL) {
- for (ppr = p->p_ucred->cr_prison;
- ppr != &prison0;
- ppr = ppr->pr_parent)
- if (ppr == killpr) {
- kern_psignal(p, SIGKILL);
- break;
- }
- }
- PROC_UNLOCK(p);
- }
- sx_sunlock(&allproc_lock);
- }
+ if (killpr != NULL)
+ prison_proc_iterate(killpr, prison_kill_processes_cb, NULL);
/*
* Finish removing any unreferenced prisons, which couldn't happen
Index: sys/kern/kern_sig.c
===================================================================
--- sys/kern/kern_sig.c
+++ sys/kern/kern_sig.c
@@ -1713,18 +1713,13 @@
};
static void
-killpg1_sendsig(struct proc *p, bool notself, struct killpg1_ctx *arg)
+killpg1_sendsig_locked(struct proc *p, struct killpg1_ctx *arg)
{
int err;
- if (p->p_pid <= 1 || (p->p_flag & P_SYSTEM) != 0 ||
- (notself && p == arg->td->td_proc) || p->p_state == PRS_NEW)
- return;
- PROC_LOCK(p);
err = p_cansignal(arg->td, p, arg->sig);
if (err == 0 && arg->sig != 0)
pksignal(p, arg->sig, arg->ksi);
- PROC_UNLOCK(p);
if (err != ESRCH)
arg->found = true;
if (err == 0)
@@ -1733,6 +1728,31 @@
arg->ret = err;
}
+static void
+killpg1_sendsig(struct proc *p, bool notself, struct killpg1_ctx *arg)
+{
+
+ if (p->p_pid <= 1 || (p->p_flag & P_SYSTEM) != 0 ||
+ (notself && p == arg->td->td_proc) || p->p_state == PRS_NEW)
+ return;
+
+ PROC_LOCK(p);
+ killpg1_sendsig_locked(p, arg);
+ PROC_UNLOCK(p);
+}
+
+static void
+kill_processes_prison_cb(struct proc *p, void *arg)
+{
+ struct killpg1_ctx *ctx = arg;
+
+ if (p->p_pid <= 1 || (p->p_flag & P_SYSTEM) != 0 ||
+ (p == ctx->td->td_proc) || p->p_state == PRS_NEW)
+ return;
+
+ killpg1_sendsig_locked(p, ctx);
+}
+
/*
* Common code for kill process group/broadcast kill.
* cp is calling process.
@@ -1754,11 +1774,8 @@
/*
* broadcast
*/
- sx_slock(&allproc_lock);
- FOREACH_PROC_IN_SYSTEM(p) {
- killpg1_sendsig(p, true, &arg);
- }
- sx_sunlock(&allproc_lock);
+ prison_proc_iterate(td->td_ucred->cr_prison,
+ kill_processes_prison_cb, &arg);
} else {
sx_slock(&proctree_lock);
if (pgid == 0) {
Index: sys/sys/jail.h
===================================================================
--- sys/sys/jail.h
+++ sys/sys/jail.h
@@ -176,6 +176,7 @@
volatile u_int pr_uref; /* (r) user (alive) refcount */
unsigned pr_flags; /* (p) PR_* flags */
LIST_HEAD(, prison) pr_children; /* (a) list of child jails */
+ LIST_HEAD(, proc) pr_proclist; /* (a) list of jailed processes */
LIST_ENTRY(prison) pr_sibling; /* (a) next in parent's list */
struct prison *pr_parent; /* (c) containing jail */
struct mtx pr_mtx;
@@ -359,6 +360,9 @@
? LIST_NEXT(cpr, pr_sibling) \
: cpr->pr_parent) != (ppr);)
+#define FOREACH_PROC_IN_PRISON(p, pr) \
+ LIST_FOREACH((p), &pr->pr_proclist, p_jaillist)
+
/*
* Attributes of the physical system, and the root of the jail tree.
*/
@@ -432,6 +436,9 @@
void prison_hold_locked(struct prison *pr);
void prison_proc_hold(struct prison *);
void prison_proc_free(struct prison *);
+void prison_proc_link(struct prison *, struct proc *);
+void prison_proc_unlink(struct prison *, struct proc *);
+void prison_proc_iterate(struct prison *, void (*)(struct proc *, void *), void *);
void prison_set_allow(struct ucred *cred, unsigned flag, int enable);
int prison_ischild(struct prison *, struct prison *);
bool prison_isalive(const struct prison *);
Index: sys/sys/proc.h
===================================================================
--- sys/sys/proc.h
+++ sys/sys/proc.h
@@ -744,6 +744,7 @@
LIST_HEAD(, proc) p_orphans; /* (e) Pointer to list of orphans. */
TAILQ_HEAD(, kq_timer_cb_data) p_kqtim_stop; /* (c) */
+ LIST_ENTRY(proc) p_jaillist; /* (d) Jail process linkage. */
};
#define p_session p_pgrp->pg_session

File Metadata

Mime Type
text/plain
Expires
Sun, Feb 15, 11:45 PM (21 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28760448
Default Alt Text
D34522.id103757.diff (7 KB)

Event Timeline