From owner-svn-src-all@FreeBSD.ORG Tue May 29 19:47:07 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 539181065673; Tue, 29 May 2012 19:47:07 +0000 (UTC) (envelope-from trasz@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 33A198FC14; Tue, 29 May 2012 19:47:07 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q4TJl7dd099059; Tue, 29 May 2012 19:47:07 GMT (envelope-from trasz@svn.freebsd.org) Received: (from trasz@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q4TJl6Zf099055; Tue, 29 May 2012 19:47:06 GMT (envelope-from trasz@svn.freebsd.org) Message-Id: <201205291947.q4TJl6Zf099055@svn.freebsd.org> From: Edward Tomasz Napierala Date: Tue, 29 May 2012 19:47:06 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r236253 - in stable/9/sys: kern sys X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 29 May 2012 19:47:07 -0000 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_ */