From faaa2dc21f1a608ad5900b982c54b74851ba71b9 Mon Sep 17 00:00:00 2001 From: jamie Date: Fri, 26 Aug 2011 16:03:34 +0000 Subject: [PATCH] Delay the recursive decrement of pr_uref when jails are made invisible but not removed; decrement it instead when the child jail actually goes away. This avoids letting the counter go below zero in the case where dying (pr_uref==0) jails are "resurrected", and an associated KASSERT panic. Submitted by: Steven Hartland Approved by: re (bz) MFC after: 1 week --- sys/kern/kern_jail.c | 31 +++++-------------------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index 050563be9a9b..8ce8327bde15 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -2470,32 +2470,11 @@ prison_deref(struct prison *pr, int flags) if (!(flags & PD_LOCKED)) mtx_lock(&pr->pr_mtx); - /* Decrement the user references in a separate loop. */ - if (flags & PD_DEUREF) { - for (tpr = pr;; tpr = tpr->pr_parent) { - if (tpr != pr) - mtx_lock(&tpr->pr_mtx); - if (--tpr->pr_uref > 0) - break; - KASSERT(tpr != &prison0, ("prison0 pr_uref=0")); - mtx_unlock(&tpr->pr_mtx); - } - /* Done if there were only user references to remove. */ - if (!(flags & PD_DEREF)) { - mtx_unlock(&tpr->pr_mtx); - if (flags & PD_LIST_SLOCKED) - sx_sunlock(&allprison_lock); - else if (flags & PD_LIST_XLOCKED) - sx_xunlock(&allprison_lock); - return; - } - if (tpr != pr) { - mtx_unlock(&tpr->pr_mtx); - mtx_lock(&pr->pr_mtx); - } - } - for (;;) { + if (flags & PD_DEUREF) { + pr->pr_uref--; + KASSERT(prison0.pr_uref != 0, ("prison0 pr_uref=0")); + } if (flags & PD_DEREF) pr->pr_ref--; /* If the prison still has references, nothing else to do. */ @@ -2551,7 +2530,7 @@ prison_deref(struct prison *pr, int flags) /* Removing a prison frees a reference on its parent. */ pr = ppr; mtx_lock(&pr->pr_mtx); - flags = PD_DEREF; + flags = PD_DEREF | PD_DEUREF; } }