From owner-svn-src-head@freebsd.org Mon Apr 25 04:24:01 2016 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id C72E8B1B705; Mon, 25 Apr 2016 04:24:01 +0000 (UTC) (envelope-from jamie@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id A39E01065; Mon, 25 Apr 2016 04:24:01 +0000 (UTC) (envelope-from jamie@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u3P4O0iE093718; Mon, 25 Apr 2016 04:24:00 GMT (envelope-from jamie@FreeBSD.org) Received: (from jamie@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u3P4O0rY093716; Mon, 25 Apr 2016 04:24:00 GMT (envelope-from jamie@FreeBSD.org) Message-Id: <201604250424.u3P4O0rY093716@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jamie set sender to jamie@FreeBSD.org using -f From: Jamie Gritton Date: Mon, 25 Apr 2016 04:24:00 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r298565 - in head/sys: kern sys X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 25 Apr 2016 04:24:01 -0000 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.