Author: kib
Date: Mon Dec 24 13:29:22 2012
New Revision: 244660
URL: http://svnweb.freebsd.org/changeset/base/244660

Log:
  MFC r242476:
  The r241025 fixed the case when a binary, executed from nullfs mount,
  was still possible to open for write from the lower filesystem.  There
  is a symmetric situation where the binary could already has file
  descriptors opened for write, but it can be executed from the nullfs
  overlay.
  
  Handle the issue by passing one v_writecount reference to the lower
  vnode if nullfs vnode has non-zero v_writecount.

Modified:
  stable/9/sys/compat/linux/linux_misc.c
  stable/9/sys/fs/nullfs/null_vnops.c
  stable/9/sys/fs/unionfs/union_subr.c
  stable/9/sys/i386/ibcs2/imgact_coff.c
  stable/9/sys/kern/kern_exec.c
  stable/9/sys/kern/vfs_default.c
  stable/9/sys/kern/vfs_vnops.c
  stable/9/sys/kern/vnode_if.src
  stable/9/sys/ufs/ufs/ufs_extattr.c
  stable/9/sys/vm/vnode_pager.c
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/fs/   (props changed)

Modified: stable/9/sys/compat/linux/linux_misc.c
==============================================================================
--- stable/9/sys/compat/linux/linux_misc.c      Mon Dec 24 13:24:55 2012        
(r244659)
+++ stable/9/sys/compat/linux/linux_misc.c      Mon Dec 24 13:29:22 2012        
(r244660)
@@ -232,8 +232,7 @@ linux_uselib(struct thread *td, struct l
        unsigned long bss_size;
        char *library;
        ssize_t aresid;
-       int error;
-       int locked, vfslocked;
+       int error, locked, vfslocked, writecount;
 
        LCONVPATHEXIST(td, args->library, &library);
 
@@ -265,7 +264,10 @@ linux_uselib(struct thread *td, struct l
        locked = 1;
 
        /* Writable? */
-       if (vp->v_writecount) {
+       error = VOP_GET_WRITECOUNT(vp, &writecount);
+       if (error != 0)
+               goto cleanup;
+       if (writecount != 0) {
                error = ETXTBSY;
                goto cleanup;
        }

Modified: stable/9/sys/fs/nullfs/null_vnops.c
==============================================================================
--- stable/9/sys/fs/nullfs/null_vnops.c Mon Dec 24 13:24:55 2012        
(r244659)
+++ stable/9/sys/fs/nullfs/null_vnops.c Mon Dec 24 13:29:22 2012        
(r244660)
@@ -329,6 +329,26 @@ null_bypass(struct vop_generic_args *ap)
        return (error);
 }
 
+static int
+null_add_writecount(struct vop_add_writecount_args *ap)
+{
+       struct vnode *lvp, *vp;
+       int error;
+
+       vp = ap->a_vp;
+       lvp = NULLVPTOLOWERVP(vp);
+       KASSERT(vp->v_writecount + ap->a_inc >= 0, ("wrong writecount inc"));
+       if (vp->v_writecount > 0 && vp->v_writecount + ap->a_inc == 0)
+               error = VOP_ADD_WRITECOUNT(lvp, -1);
+       else if (vp->v_writecount == 0 && vp->v_writecount + ap->a_inc > 0)
+               error = VOP_ADD_WRITECOUNT(lvp, 1);
+       else
+               error = 0;
+       if (error == 0)
+               vp->v_writecount += ap->a_inc;
+       return (error);
+}
+
 /*
  * We have to carry on the locking protocol on the null layer vnodes
  * as we progress through the tree. We also have to enforce read-only
@@ -826,4 +846,5 @@ struct vop_vector null_vnodeops = {
        .vop_unlock =           null_unlock,
        .vop_vptocnp =          null_vptocnp,
        .vop_vptofh =           null_vptofh,
+       .vop_add_writecount =   null_add_writecount,
 };

Modified: stable/9/sys/fs/unionfs/union_subr.c
==============================================================================
--- stable/9/sys/fs/unionfs/union_subr.c        Mon Dec 24 13:24:55 2012        
(r244659)
+++ stable/9/sys/fs/unionfs/union_subr.c        Mon Dec 24 13:29:22 2012        
(r244660)
@@ -954,7 +954,7 @@ unionfs_vn_create_on_upper(struct vnode 
                vput(vp);
                goto unionfs_vn_create_on_upper_free_out1;
        }
-       vp->v_writecount++;
+       VOP_ADD_WRITECOUNT(vp, 1);
        *vpp = vp;
 
 unionfs_vn_create_on_upper_free_out1:
@@ -1089,7 +1089,7 @@ unionfs_copyfile(struct unionfs_node *un
                }
        }
        VOP_CLOSE(uvp, FWRITE, cred, td);
-       uvp->v_writecount--;
+       VOP_ADD_WRITECOUNT(uvp, -1);
 
        vn_finished_write(mp);
 

Modified: stable/9/sys/i386/ibcs2/imgact_coff.c
==============================================================================
--- stable/9/sys/i386/ibcs2/imgact_coff.c       Mon Dec 24 13:24:55 2012        
(r244659)
+++ stable/9/sys/i386/ibcs2/imgact_coff.c       Mon Dec 24 13:29:22 2012        
(r244660)
@@ -168,7 +168,7 @@ coff_load_file(struct thread *td, char *
        unsigned long text_offset = 0, text_address = 0, text_size = 0;
        unsigned long data_offset = 0, data_address = 0, data_size = 0;
        unsigned long bss_size = 0;
-       int i;
+       int i, writecount;
 
        NDINIT(&nd, LOOKUP, ISOPEN | LOCKLEAF | FOLLOW | SAVENAME,
            UIO_SYSSPACE, name, td);
@@ -181,7 +181,10 @@ coff_load_file(struct thread *td, char *
        if (vp == NULL)
                return ENOEXEC;
 
-       if (vp->v_writecount) {
+       error = VOP_GET_WRITECOUNT(vp, &writecount);
+       if (error != 0)
+               goto fail;
+       if (writecount != 0) {
                error = ETXTBSY;
                goto fail;
        }

Modified: stable/9/sys/kern/kern_exec.c
==============================================================================
--- stable/9/sys/kern/kern_exec.c       Mon Dec 24 13:24:55 2012        
(r244659)
+++ stable/9/sys/kern/kern_exec.c       Mon Dec 24 13:29:22 2012        
(r244660)
@@ -1393,7 +1393,7 @@ exec_check_permissions(imgp)
        struct vnode *vp = imgp->vp;
        struct vattr *attr = imgp->attr;
        struct thread *td;
-       int error;
+       int error, writecount;
 
        td = curthread;
 
@@ -1438,7 +1438,10 @@ exec_check_permissions(imgp)
         * Check number of open-for-writes on the file and deny execution
         * if there are any.
         */
-       if (vp->v_writecount)
+       error = VOP_GET_WRITECOUNT(vp, &writecount);
+       if (error != 0)
+               return (error);
+       if (writecount != 0)
                return (ETXTBSY);
 
        /*

Modified: stable/9/sys/kern/vfs_default.c
==============================================================================
--- stable/9/sys/kern/vfs_default.c     Mon Dec 24 13:24:55 2012        
(r244659)
+++ stable/9/sys/kern/vfs_default.c     Mon Dec 24 13:29:22 2012        
(r244660)
@@ -81,6 +81,8 @@ static int    dirent_exists(struct vnode *v
 static int vop_stdis_text(struct vop_is_text_args *ap);
 static int vop_stdset_text(struct vop_set_text_args *ap);
 static int vop_stdunset_text(struct vop_unset_text_args *ap);
+static int vop_stdget_writecount(struct vop_get_writecount_args *ap);
+static int vop_stdadd_writecount(struct vop_add_writecount_args *ap);
 
 /*
  * This vnode table stores what we want to do if the filesystem doesn't
@@ -133,6 +135,8 @@ struct vop_vector default_vnodeops = {
        .vop_is_text =          vop_stdis_text,
        .vop_set_text =         vop_stdset_text,
        .vop_unset_text =       vop_stdunset_text,
+       .vop_get_writecount =   vop_stdget_writecount,
+       .vop_add_writecount =   vop_stdadd_writecount,
 };
 
 /*
@@ -1103,6 +1107,22 @@ vop_stdunset_text(struct vop_unset_text_
        return (0);
 }
 
+static int
+vop_stdget_writecount(struct vop_get_writecount_args *ap)
+{
+
+       *ap->a_writecount = ap->a_vp->v_writecount;
+       return (0);
+}
+
+static int
+vop_stdadd_writecount(struct vop_add_writecount_args *ap)
+{
+
+       ap->a_vp->v_writecount += ap->a_inc;
+       return (0);
+}
+
 /*
  * vfs default ops
  * used to fill the vfs function table to get reasonable default return values.

Modified: stable/9/sys/kern/vfs_vnops.c
==============================================================================
--- stable/9/sys/kern/vfs_vnops.c       Mon Dec 24 13:24:55 2012        
(r244659)
+++ stable/9/sys/kern/vfs_vnops.c       Mon Dec 24 13:29:22 2012        
(r244660)
@@ -252,7 +252,7 @@ restart:
                goto bad;
 
        if (fmode & FWRITE)
-               vp->v_writecount++;
+               VOP_ADD_WRITECOUNT(vp, 1);
        *flagp = fmode;
        ASSERT_VOP_LOCKED(vp, "vn_open_cred");
        if (!mpsafe)
@@ -314,7 +314,7 @@ vn_close(vp, flags, file_cred, td)
        if (flags & FWRITE) {
                VNASSERT(vp->v_writecount > 0, vp, 
                    ("vn_close: negative writecount"));
-               vp->v_writecount--;
+               VOP_ADD_WRITECOUNT(vp, -1);
        }
        error = VOP_CLOSE(vp, flags, file_cred, td);
        vput(vp);

Modified: stable/9/sys/kern/vnode_if.src
==============================================================================
--- stable/9/sys/kern/vnode_if.src      Mon Dec 24 13:24:55 2012        
(r244659)
+++ stable/9/sys/kern/vnode_if.src      Mon Dec 24 13:29:22 2012        
(r244660)
@@ -676,6 +676,20 @@ vop_unset_text {
        IN struct vnode *vp;
 };
 
+%% get_writecount      vp      L L L
+
+vop_get_writecount {
+       IN struct vnode *vp;
+       OUT int *writecount;
+};
+
+%% add_writecount      vp      E E E
+
+vop_add_writecount {
+       IN struct vnode *vp;
+       IN int inc;
+};
+
 # The VOPs below are spares at the end of the table to allow new VOPs to be
 # added in stable branches without breaking the KBI.  New VOPs in HEAD should
 # be added above these spares.  When merging a new VOP to a stable branch,

Modified: stable/9/sys/ufs/ufs/ufs_extattr.c
==============================================================================
--- stable/9/sys/ufs/ufs/ufs_extattr.c  Mon Dec 24 13:24:55 2012        
(r244659)
+++ stable/9/sys/ufs/ufs/ufs_extattr.c  Mon Dec 24 13:29:22 2012        
(r244660)
@@ -334,7 +334,7 @@ ufs_extattr_enable_with_open(struct ufsm
                return (error);
        }
 
-       vp->v_writecount++;
+       VOP_ADD_WRITECOUNT(vp, 1);
 
        vref(vp);
 

Modified: stable/9/sys/vm/vnode_pager.c
==============================================================================
--- stable/9/sys/vm/vnode_pager.c       Mon Dec 24 13:24:55 2012        
(r244659)
+++ stable/9/sys/vm/vnode_pager.c       Mon Dec 24 13:29:22 2012        
(r244660)
@@ -272,7 +272,7 @@ vnode_pager_dealloc(object)
        ASSERT_VOP_ELOCKED(vp, "vnode_pager_dealloc");
        if (object->un_pager.vnp.writemappings > 0) {
                object->un_pager.vnp.writemappings = 0;
-               vp->v_writecount--;
+               VOP_ADD_WRITECOUNT(vp, -1);
        }
        vp->v_object = NULL;
        VOP_UNSET_TEXT(vp);
@@ -1216,10 +1216,10 @@ vnode_pager_update_writecount(vm_object_
        vp = object->handle;
        if (old_wm == 0 && object->un_pager.vnp.writemappings != 0) {
                ASSERT_VOP_ELOCKED(vp, "v_writecount inc");
-               vp->v_writecount++;
+               VOP_ADD_WRITECOUNT(vp, 1);
        } else if (old_wm != 0 && object->un_pager.vnp.writemappings == 0) {
                ASSERT_VOP_ELOCKED(vp, "v_writecount dec");
-               vp->v_writecount--;
+               VOP_ADD_WRITECOUNT(vp, -1);
        }
        VM_OBJECT_UNLOCK(object);
 }
_______________________________________________
svn-src-stable-9@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-stable-9
To unsubscribe, send any mail to "svn-src-stable-9-unsubscr...@freebsd.org"

Reply via email to