Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F107510298
D34522.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D34522.diff
View Options
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -473,6 +473,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);
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -398,6 +398,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));
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -147,6 +147,8 @@
static void prison_cleanup(struct prison *pr);
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);
@@ -2648,6 +2650,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);
@@ -2919,6 +2922,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.
*/
@@ -2940,6 +2969,60 @@
prison_deref(pr, drflags);
}
+static void
+prison_kill_processes_cb(struct proc *p, void *arg __unused)
+{
+
+ kern_psignal(p, SIGKILL);
+}
+
+/*
+ * Note the iteration does not guarantee acting on all processes.
+ * Most notably there may be fork or jail_attach in progress.
+ */
+void
+prison_proc_iterate(struct prison *pr, void (*cb)(struct proc *, void *),
+ void *cbarg)
+{
+ struct prison *ppr;
+ struct proc *p;
+
+ if (atomic_load_int(&pr->pr_childcount) == 0) {
+ sx_slock(&allproc_lock);
+ LIST_FOREACH(p, &pr->pr_proclist, p_jaillist) {
+ if (p->p_state == PRS_NEW)
+ continue;
+ PROC_LOCK(p);
+ cb(p, cbarg);
+ PROC_UNLOCK(p);
+ }
+ sx_sunlock(&allproc_lock);
+ if (atomic_load_int(&pr->pr_childcount) == 0)
+ return;
+ /*
+ * Some jails popped up during the iteration, fall through to a
+ * system-wide search.
+ */
+ }
+
+ 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 == 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),
@@ -2953,7 +3036,6 @@
{
struct prisonlist freeprison;
struct prison *killpr, *rpr, *ppr, *tpr;
- struct proc *p;
killpr = NULL;
TAILQ_INIT(&freeprison);
@@ -3064,23 +3146,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
diff --git a/sys/sys/jail.h b/sys/sys/jail.h
--- a/sys/sys/jail.h
+++ b/sys/sys/jail.h
@@ -159,6 +159,7 @@
*
* Lock key:
* (a) allprison_lock
+ * (A) allproc_lock
* (c) set only during creation before the structure is shared, no mutex
* required to read
* (m) locked by pr_mtx
@@ -176,6 +177,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;
@@ -432,6 +434,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 *);
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -773,6 +773,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
Details
Attached
Mime Type
text/plain
Expires
Thu, Jan 16, 5:51 AM (19 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15820813
Default Alt Text
D34522.diff (5 KB)
Attached To
Mode
D34522: jail: add process iterator
Attached
Detach File
Event Timeline
Log In to Comment