Author: jamie
Date: Wed Jun 15 01:56:20 2016
New Revision: 301907
URL: https://svnweb.freebsd.org/changeset/base/301907

Log:
  MFC r301745:
  
    Make sure the OSD methods for jail set and remove can't run concurrently,
    by holding allprison_lock exclusively (even if only for a moment before
    downgrading) on all paths that call PR_METHOD_REMOVE.  Since they may run
    on a downgraded lock, it's still possible for them to run concurrently
    with PR_METHOD_GET, which will need to use the prison lock.

Modified:
  stable/10/sys/kern/kern_jail.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/kern/kern_jail.c
==============================================================================
--- stable/10/sys/kern/kern_jail.c      Wed Jun 15 01:54:17 2016        
(r301906)
+++ stable/10/sys/kern/kern_jail.c      Wed Jun 15 01:56:20 2016        
(r301907)
@@ -2400,7 +2400,14 @@ sys_jail_attach(struct thread *td, struc
        if (error)
                return (error);
 
-       sx_slock(&allprison_lock);
+       /*
+        * Start with exclusive hold on allprison_lock to ensure that a possible
+        * PR_METHOD_REMOVE call isn't concurrent with jail_set or jail_remove.
+        * But then immediately downgrade it since we don't need to stop
+        * readers.
+        */
+       sx_xlock(&allprison_lock);
+       sx_downgrade(&allprison_lock);
        pr = prison_find_child(td->td_ucred->cr_prison, uap->jid);
        if (pr == NULL) {
                sx_sunlock(&allprison_lock);
@@ -2618,9 +2625,11 @@ prison_complete(void *context, int pendi
 {
        struct prison *pr = context;
 
+       sx_xlock(&allprison_lock);
        mtx_lock(&pr->pr_mtx);
        prison_deref(pr, pr->pr_uref
-           ? PD_DEREF | PD_DEUREF | PD_LOCKED : PD_LOCKED);
+           ? PD_DEREF | PD_DEUREF | PD_LOCKED | PD_LIST_XLOCKED
+           : PD_LOCKED | PD_LIST_XLOCKED);
 }
 
 /*
@@ -2664,13 +2673,8 @@ prison_deref(struct prison *pr, int flag
                 */
                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;
-                               }
+                               sx_xlock(&allprison_lock);
+                               flags |= PD_LIST_XLOCKED;
                        }
                        (void)osd_jail_call(pr, PR_METHOD_REMOVE, NULL);
                        mtx_lock(&pr->pr_mtx);
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to