Date: Mon, 24 Dec 2012 13:29:22 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r244660 - in stable/9/sys: compat/linux fs/nullfs fs/unionfs i386/ibcs2 kern ufs/ufs vm Message-ID: <201212241329.qBODTMq7013701@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201212241329.qBODTMq7013701>