svn commit: r236253 - in stable/9/sys: kern sys
Edward Tomasz Napierala
trasz at FreeBSD.org
Tue May 29 19:47:07 UTC 2012
Author: trasz
Date: Tue May 29 19:47:06 2012
New Revision: 236253
URL: http://svn.freebsd.org/changeset/base/236253
Log:
MFC r232598:
Make racct and rctl correctly handle jail renaming. Previously
they would continue using old name, the one jail was created with.
PR: bin/165207
MFC r235795:
Don't leak locks in prison_racct_modify().
MFC r235803:
Fix use-after-free in kern_jail_set() triggered e.g. by attempts
to clear "persist" flag from empty persistent jail, like this:
jail -c persist=1
jail -n 1 -m persist=0
Modified:
stable/9/sys/kern/kern_jail.c
stable/9/sys/kern/kern_racct.c
stable/9/sys/sys/racct.h
Directory Properties:
stable/9/sys/ (props changed)
Modified: stable/9/sys/kern/kern_jail.c
==============================================================================
--- stable/9/sys/kern/kern_jail.c Tue May 29 19:46:42 2012 (r236252)
+++ stable/9/sys/kern/kern_jail.c Tue May 29 19:47:06 2012 (r236253)
@@ -130,6 +130,7 @@ static char *prison_path(struct prison *
static void prison_remove_one(struct prison *pr);
#ifdef RACCT
static void prison_racct_attach(struct prison *pr);
+static void prison_racct_modify(struct prison *pr);
static void prison_racct_detach(struct prison *pr);
#endif
#ifdef INET
@@ -1810,6 +1811,16 @@ kern_jail_set(struct thread *td, struct
}
}
+#ifdef RACCT
+ if (!created) {
+ sx_sunlock(&allprison_lock);
+ prison_racct_modify(pr);
+ sx_slock(&allprison_lock);
+ }
+#endif
+
+ td->td_retval[0] = pr->pr_id;
+
/*
* Now that it is all there, drop the temporary reference from existing
* prisons. Or add a reference to newly created persistent prisons
@@ -1830,7 +1841,7 @@ kern_jail_set(struct thread *td, struct
if (!(flags & JAIL_ATTACH))
sx_sunlock(&allprison_lock);
}
- td->td_retval[0] = pr->pr_id;
+
goto done_errmsg;
done_deref_locked:
@@ -4427,24 +4438,32 @@ prison_racct_hold(struct prison_racct *p
refcount_acquire(&prr->prr_refcount);
}
+static void
+prison_racct_free_locked(struct prison_racct *prr)
+{
+
+ sx_assert(&allprison_lock, SA_XLOCKED);
+
+ if (refcount_release(&prr->prr_refcount)) {
+ racct_destroy(&prr->prr_racct);
+ LIST_REMOVE(prr, prr_next);
+ free(prr, M_PRISON_RACCT);
+ }
+}
+
void
prison_racct_free(struct prison_racct *prr)
{
int old;
+ sx_assert(&allprison_lock, SA_UNLOCKED);
+
old = prr->prr_refcount;
if (old > 1 && atomic_cmpset_int(&prr->prr_refcount, old, old - 1))
return;
sx_xlock(&allprison_lock);
- if (refcount_release(&prr->prr_refcount)) {
- racct_destroy(&prr->prr_racct);
- LIST_REMOVE(prr, prr_next);
- sx_xunlock(&allprison_lock);
- free(prr, M_PRISON_RACCT);
-
- return;
- }
+ prison_racct_free_locked(prr);
sx_xunlock(&allprison_lock);
}
@@ -4454,15 +4473,66 @@ prison_racct_attach(struct prison *pr)
{
struct prison_racct *prr;
+ sx_assert(&allprison_lock, SA_XLOCKED);
+
prr = prison_racct_find_locked(pr->pr_name);
KASSERT(prr != NULL, ("cannot find prison_racct"));
pr->pr_prison_racct = prr;
}
+/*
+ * Handle jail renaming. From the racct point of view, renaming means
+ * moving from one prison_racct to another.
+ */
+static void
+prison_racct_modify(struct prison *pr)
+{
+ struct proc *p;
+ struct ucred *cred;
+ struct prison_racct *oldprr;
+
+ sx_slock(&allproc_lock);
+ sx_xlock(&allprison_lock);
+
+ if (strcmp(pr->pr_name, pr->pr_prison_racct->prr_name) == 0) {
+ sx_xunlock(&allprison_lock);
+ sx_sunlock(&allproc_lock);
+ return;
+ }
+
+ oldprr = pr->pr_prison_racct;
+ pr->pr_prison_racct = NULL;
+
+ prison_racct_attach(pr);
+
+ /*
+ * Move resource utilisation records.
+ */
+ racct_move(pr->pr_prison_racct->prr_racct, oldprr->prr_racct);
+
+ /*
+ * Force rctl to reattach rules to processes.
+ */
+ FOREACH_PROC_IN_SYSTEM(p) {
+ PROC_LOCK(p);
+ cred = crhold(p->p_ucred);
+ PROC_UNLOCK(p);
+ racct_proc_ucred_changed(p, cred, cred);
+ crfree(cred);
+ }
+
+ sx_sunlock(&allproc_lock);
+ prison_racct_free_locked(oldprr);
+ sx_xunlock(&allprison_lock);
+}
+
static void
prison_racct_detach(struct prison *pr)
{
+
+ sx_assert(&allprison_lock, SA_UNLOCKED);
+
prison_racct_free(pr->pr_prison_racct);
pr->pr_prison_racct = NULL;
}
Modified: stable/9/sys/kern/kern_racct.c
==============================================================================
--- stable/9/sys/kern/kern_racct.c Tue May 29 19:46:42 2012 (r236252)
+++ stable/9/sys/kern/kern_racct.c Tue May 29 19:47:06 2012 (r236253)
@@ -679,6 +679,18 @@ racct_proc_ucred_changed(struct proc *p,
#endif
}
+void
+racct_move(struct racct *dest, struct racct *src)
+{
+
+ mtx_lock(&racct_lock);
+
+ racct_add_racct(dest, src);
+ racct_sub_racct(src, src);
+
+ mtx_unlock(&racct_lock);
+}
+
static void
racctd(void)
{
Modified: stable/9/sys/sys/racct.h
==============================================================================
--- stable/9/sys/sys/racct.h Tue May 29 19:46:42 2012 (r236252)
+++ stable/9/sys/sys/racct.h Tue May 29 19:47:06 2012 (r236253)
@@ -142,5 +142,6 @@ void racct_proc_exit(struct proc *p);
void racct_proc_ucred_changed(struct proc *p, struct ucred *oldcred,
struct ucred *newcred);
+void racct_move(struct racct *dest, struct racct *src);
#endif /* !_RACCT_H_ */
More information about the svn-src-stable-9
mailing list