svn commit: r298565 - in head/sys: kern sys
Jamie Gritton
jamie at FreeBSD.org
Mon Apr 25 04:24:01 UTC 2016
Author: jamie
Date: Mon Apr 25 04:24:00 2016
New Revision: 298565
URL: https://svnweb.freebsd.org/changeset/base/298565
Log:
Add a new jail OSD method, PR_METHOD_REMOVE. It's called when a jail is
removed from the user perspective, i.e. when the last pr_uref goes away,
even though the jail mail still exist in the dying state. It will also
be called if either PR_METHOD_CREATE or PR_METHOD_SET fail.
PR: 48471
MFC after: 5 days
Modified:
head/sys/kern/kern_jail.c
head/sys/sys/jail.h
Modified: head/sys/kern/kern_jail.c
==============================================================================
--- head/sys/kern/kern_jail.c Mon Apr 25 03:58:08 2016 (r298564)
+++ head/sys/kern/kern_jail.c Mon Apr 25 04:24:00 2016 (r298565)
@@ -556,7 +556,8 @@ kern_jail_set(struct thread *td, struct
#endif
unsigned long hid;
size_t namelen, onamelen;
- int created, cuflags, descend, enforce, error, errmsg_len, errmsg_pos;
+ int born, created, cuflags, descend, enforce;
+ int error, errmsg_len, errmsg_pos;
int gotchildmax, gotenforce, gothid, gotrsnum, gotslevel;
int fi, jid, jsys, len, level;
int childmax, osreldt, rsnum, slevel;
@@ -1767,6 +1768,7 @@ kern_jail_set(struct thread *td, struct
* for now, so new ones will remain unseen until after the module
* handlers have completed.
*/
+ born = pr->pr_uref == 0;
if (!created && (ch_flags & PR_PERSIST & (pr_flags ^ pr->pr_flags))) {
if (pr_flags & PR_PERSIST) {
pr->pr_ref++;
@@ -1836,15 +1838,20 @@ kern_jail_set(struct thread *td, struct
/* Let the modules do their work. */
sx_downgrade(&allprison_lock);
- if (created) {
+ if (born) {
error = osd_jail_call(pr, PR_METHOD_CREATE, opts);
if (error) {
- prison_deref(pr, PD_LIST_SLOCKED);
+ (void)osd_jail_call(pr, PR_METHOD_REMOVE, NULL);
+ prison_deref(pr, created
+ ? PD_LIST_SLOCKED
+ : PD_DEREF | PD_LIST_SLOCKED);
goto done_errmsg;
}
}
error = osd_jail_call(pr, PR_METHOD_SET, opts);
if (error) {
+ if (born)
+ (void)osd_jail_call(pr, PR_METHOD_REMOVE, NULL);
prison_deref(pr, created
? PD_LIST_SLOCKED
: PD_DEREF | PD_LIST_SLOCKED);
@@ -1896,7 +1903,7 @@ kern_jail_set(struct thread *td, struct
sx_sunlock(&allprison_lock);
}
- goto done_errmsg;
+ goto done_free;
done_deref_locked:
prison_deref(pr, created
@@ -2596,19 +2603,46 @@ static void
prison_deref(struct prison *pr, int flags)
{
struct prison *ppr, *tpr;
+ int ref, lasturef;
if (!(flags & PD_LOCKED))
mtx_lock(&pr->pr_mtx);
for (;;) {
if (flags & PD_DEUREF) {
pr->pr_uref--;
+ lasturef = pr->pr_uref == 0;
+ if (lasturef)
+ pr->pr_ref++;
KASSERT(prison0.pr_uref != 0, ("prison0 pr_uref=0"));
- }
+ } else
+ lasturef = 0;
if (flags & PD_DEREF)
pr->pr_ref--;
- /* If the prison still has references, nothing else to do. */
- if (pr->pr_ref > 0) {
+ ref = pr->pr_ref;
+ mtx_unlock(&pr->pr_mtx);
+
+ /*
+ * Tell the modules if the last user reference was removed
+ * (even it sticks around in dying state).
+ */
+ if (lasturef) {
+ if (!(flags & (PD_LIST_SLOCKED | PD_LIST_XLOCKED))) {
+ if (ref > 1) {
+ sx_slock(&allprison_lock);
+ flags |= PD_LIST_SLOCKED;
+ } else {
+ sx_xlock(&allprison_lock);
+ flags |= PD_LIST_XLOCKED;
+ }
+ }
+ (void)osd_jail_call(pr, PR_METHOD_REMOVE, NULL);
+ mtx_lock(&pr->pr_mtx);
+ ref = --pr->pr_ref;
mtx_unlock(&pr->pr_mtx);
+ }
+
+ /* If the prison still has references, nothing else to do. */
+ if (ref > 0) {
if (flags & PD_LIST_SLOCKED)
sx_sunlock(&allprison_lock);
else if (flags & PD_LIST_XLOCKED)
@@ -2616,7 +2650,6 @@ prison_deref(struct prison *pr, int flag
return;
}
- mtx_unlock(&pr->pr_mtx);
if (flags & PD_LIST_SLOCKED) {
if (!sx_try_upgrade(&allprison_lock)) {
sx_sunlock(&allprison_lock);
Modified: head/sys/sys/jail.h
==============================================================================
--- head/sys/sys/jail.h Mon Apr 25 03:58:08 2016 (r298564)
+++ head/sys/sys/jail.h Mon Apr 25 04:24:00 2016 (r298565)
@@ -241,7 +241,8 @@ struct prison_racct {
#define PR_METHOD_SET 2
#define PR_METHOD_CHECK 3
#define PR_METHOD_ATTACH 4
-#define PR_MAXMETHOD 5
+#define PR_METHOD_REMOVE 5
+#define PR_MAXMETHOD 6
/*
* Lock/unlock a prison.
More information about the svn-src-all
mailing list