svn commit: r241025 - in head/sys: compat/linux fs/coda fs/nfsserver kern nfsserver vm

Konstantin Belousov kib at FreeBSD.org
Fri Sep 28 11:25:03 UTC 2012


Author: kib
Date: Fri Sep 28 11:25:02 2012
New Revision: 241025
URL: http://svn.freebsd.org/changeset/base/241025

Log:
  Fix the mis-handling of the VV_TEXT on the nullfs vnodes.
  
  If you have a binary on a filesystem which is also mounted over by
  nullfs, you could execute the binary from the lower filesystem, or
  from the nullfs mount. When executed from lower filesystem, the lower
  vnode gets VV_TEXT flag set, and the file cannot be modified while the
  binary is active. But, if executed as the nullfs alias, only the
  nullfs vnode gets VV_TEXT set, and you still can open the lower vnode
  for write.
  
  Add a set of VOPs for the VV_TEXT query, set and clear operations,
  which are correctly bypassed to lower vnode.
  
  Tested by:	pho (previous version)
  MFC after:	2 weeks

Modified:
  head/sys/compat/linux/linux_misc.c
  head/sys/fs/coda/coda_subr.c
  head/sys/fs/nfsserver/nfs_nfsdport.c
  head/sys/kern/imgact_elf.c
  head/sys/kern/kern_exec.c
  head/sys/kern/vfs_default.c
  head/sys/kern/vfs_vnops.c
  head/sys/kern/vnode_if.src
  head/sys/nfsserver/nfs_serv.c
  head/sys/vm/vm_object.c
  head/sys/vm/vnode_pager.c

Modified: head/sys/compat/linux/linux_misc.c
==============================================================================
--- head/sys/compat/linux/linux_misc.c	Fri Sep 28 11:11:42 2012	(r241024)
+++ head/sys/compat/linux/linux_misc.c	Fri Sep 28 11:25:02 2012	(r241025)
@@ -386,7 +386,7 @@ linux_uselib(struct thread *td, struct l
 	 * XXX: Note that if any of the VM operations fail below we don't
 	 * clear this flag.
 	 */
-	vp->v_vflag |= VV_TEXT;
+	VOP_SET_TEXT(vp);
 
 	/*
 	 * Lock no longer needed

Modified: head/sys/fs/coda/coda_subr.c
==============================================================================
--- head/sys/fs/coda/coda_subr.c	Fri Sep 28 11:11:42 2012	(r241024)
+++ head/sys/fs/coda/coda_subr.c	Fri Sep 28 11:25:02 2012	(r241025)
@@ -486,7 +486,7 @@ handleDownCall(struct coda_mntinfo *mnt,
 			cache_purge(CTOV(cp));
 			cp->c_flags &= ~(C_VATTR | C_ACCCACHE);
 			ASSERT_VOP_LOCKED(CTOV(cp), "coda HandleDownCall");
-			if (CTOV(cp)->v_vflag & VV_TEXT)
+			if (VOP_IS_TEXT(CTOV(cp)))
 				error = coda_vmflush(cp);
 			CODADEBUG(CODA_ZAPFILE,
 			myprintf(("zapfile: fid = %s, refcnt = %d, error = "
@@ -532,7 +532,7 @@ handleDownCall(struct coda_mntinfo *mnt,
 			cp->c_flags &= ~(C_VATTR | C_ACCCACHE);
 			ASSERT_VOP_LOCKED(CTOV(cp), "coda HandleDownCall");
 			if (!(IS_DIR(out->coda_purgefid.Fid))
-			    && (CTOV(cp)->v_vflag & VV_TEXT))
+			    && VOP_IS_TEXT(CTOV(cp)))
 				error = coda_vmflush(cp);
 			CODADEBUG(CODA_PURGEFID, myprintf(("purgefid: fid "
 			    "= %s, refcnt = %d, error = %d\n",

Modified: head/sys/fs/nfsserver/nfs_nfsdport.c
==============================================================================
--- head/sys/fs/nfsserver/nfs_nfsdport.c	Fri Sep 28 11:11:42 2012	(r241024)
+++ head/sys/fs/nfsserver/nfs_nfsdport.c	Fri Sep 28 11:25:02 2012	(r241025)
@@ -252,7 +252,7 @@ nfsvno_accchk(struct vnode *vp, accmode_
 		 * the inode, try to free it up once.  If
 		 * we fail, we can't allow writing.
 		 */
-		if ((vp->v_vflag & VV_TEXT) != 0 && error == 0)
+		if (VOP_IS_TEXT(vp) && error == 0)
 			error = ETXTBSY;
 	}
 	if (error != 0) {

Modified: head/sys/kern/imgact_elf.c
==============================================================================
--- head/sys/kern/imgact_elf.c	Fri Sep 28 11:11:42 2012	(r241024)
+++ head/sys/kern/imgact_elf.c	Fri Sep 28 11:25:02 2012	(r241025)
@@ -647,7 +647,7 @@ __elfN(load_file)(struct proc *p, const 
 	 * Also make certain that the interpreter stays the same, so set
 	 * its VV_TEXT flag, too.
 	 */
-	nd->ni_vp->v_vflag |= VV_TEXT;
+	VOP_SET_TEXT(nd->ni_vp);
 
 	imgp->object = nd->ni_vp->v_object;
 

Modified: head/sys/kern/kern_exec.c
==============================================================================
--- head/sys/kern/kern_exec.c	Fri Sep 28 11:11:42 2012	(r241024)
+++ head/sys/kern/kern_exec.c	Fri Sep 28 11:25:02 2012	(r241025)
@@ -473,9 +473,8 @@ interpret:
 	 * Remember if this was set before and unset it in case this is not
 	 * actually an executable image.
 	 */
-	textset = imgp->vp->v_vflag & VV_TEXT;
-	ASSERT_VOP_ELOCKED(imgp->vp, "vv_text");
-	imgp->vp->v_vflag |= VV_TEXT;
+	textset = VOP_IS_TEXT(imgp->vp);
+	VOP_SET_TEXT(imgp->vp);
 
 	error = exec_map_first_page(imgp);
 	if (error)
@@ -506,10 +505,8 @@ interpret:
 
 	if (error) {
 		if (error == -1) {
-			if (textset == 0) {
-				ASSERT_VOP_ELOCKED(imgp->vp, "vv_text");
-				imgp->vp->v_vflag &= ~VV_TEXT;
-			}
+			if (textset == 0)
+				VOP_UNSET_TEXT(imgp->vp);
 			error = ENOEXEC;
 		}
 		goto exec_fail_dealloc;
@@ -527,7 +524,7 @@ interpret:
 		 * VV_TEXT will be set. The vnode lock is held over this
 		 * entire period so nothing should illegitimately be blocked.
 		 */
-		imgp->vp->v_vflag &= ~VV_TEXT;
+		VOP_UNSET_TEXT(imgp->vp);
 		/* free name buffer and old vnode */
 		if (args->fname != NULL)
 			NDFREE(&nd, NDF_ONLY_PNBUF);

Modified: head/sys/kern/vfs_default.c
==============================================================================
--- head/sys/kern/vfs_default.c	Fri Sep 28 11:11:42 2012	(r241024)
+++ head/sys/kern/vfs_default.c	Fri Sep 28 11:25:02 2012	(r241025)
@@ -78,6 +78,10 @@ static int	dirent_exists(struct vnode *v
 
 #define DIRENT_MINSIZE (sizeof(struct dirent) - (MAXNAMLEN+1) + 4)
 
+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);
+
 /*
  * This vnode table stores what we want to do if the filesystem doesn't
  * implement a particular VOP.
@@ -126,6 +130,9 @@ struct vop_vector default_vnodeops = {
 	.vop_unp_bind =		vop_stdunp_bind,
 	.vop_unp_connect =	vop_stdunp_connect,
 	.vop_unp_detach =	vop_stdunp_detach,
+	.vop_is_text =		vop_stdis_text,
+	.vop_set_text =		vop_stdset_text,
+	.vop_unset_text =	vop_stdunset_text,
 };
 
 /*
@@ -1073,6 +1080,29 @@ vop_stdunp_detach(struct vop_unp_detach_
 	return (0);
 }
 
+static int
+vop_stdis_text(struct vop_is_text_args *ap)
+{
+
+	return ((ap->a_vp->v_vflag & VV_TEXT) != 0);
+}
+
+static int
+vop_stdset_text(struct vop_set_text_args *ap)
+{
+
+	ap->a_vp->v_vflag |= VV_TEXT;
+	return (0);
+}
+
+static int
+vop_stdunset_text(struct vop_unset_text_args *ap)
+{
+
+	ap->a_vp->v_vflag &= ~VV_TEXT;
+	return (0);
+}
+
 /*
  * vfs default ops
  * used to fill the vfs function table to get reasonable default return values.

Modified: head/sys/kern/vfs_vnops.c
==============================================================================
--- head/sys/kern/vfs_vnops.c	Fri Sep 28 11:11:42 2012	(r241024)
+++ head/sys/kern/vfs_vnops.c	Fri Sep 28 11:25:02 2012	(r241025)
@@ -342,7 +342,7 @@ vn_writechk(vp)
 	 * the vnode, try to free it up once.  If
 	 * we fail, we can't allow writing.
 	 */
-	if (vp->v_vflag & VV_TEXT)
+	if (VOP_IS_TEXT(vp))
 		return (ETXTBSY);
 
 	return (0);

Modified: head/sys/kern/vnode_if.src
==============================================================================
--- head/sys/kern/vnode_if.src	Fri Sep 28 11:11:42 2012	(r241024)
+++ head/sys/kern/vnode_if.src	Fri Sep 28 11:25:02 2012	(r241025)
@@ -660,6 +660,24 @@ vop_unp_detach {
 	IN struct vnode *vp;
 };
 
+%% is_text	vp	L L L
+
+vop_is_text {
+	IN struct vnode *vp;
+};
+
+%% set_text	vp	E E E
+
+vop_set_text {
+	IN struct vnode *vp;
+};
+
+%% vop_unset_text	vp	E E E
+
+vop_unset_text {
+	IN struct vnode *vp;
+};
+
 # 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: head/sys/nfsserver/nfs_serv.c
==============================================================================
--- head/sys/nfsserver/nfs_serv.c	Fri Sep 28 11:11:42 2012	(r241024)
+++ head/sys/nfsserver/nfs_serv.c	Fri Sep 28 11:25:02 2012	(r241025)
@@ -3896,7 +3896,7 @@ nfsrv_access(struct vnode *vp, accmode_t
 		 * If there's shared text associated with
 		 * the inode, we can't allow writing.
 		 */
-		if (vp->v_vflag & VV_TEXT)
+		if (VOP_IS_TEXT(vp))
 			return (ETXTBSY);
 	}
 

Modified: head/sys/vm/vm_object.c
==============================================================================
--- head/sys/vm/vm_object.c	Fri Sep 28 11:11:42 2012	(r241024)
+++ head/sys/vm/vm_object.c	Fri Sep 28 11:25:02 2012	(r241025)
@@ -456,7 +456,7 @@ vm_object_vndeallocate(vm_object_t objec
 			VOP_UNLOCK(vp, 0);
 		} else {
 			if (object->ref_count == 0)
-				vp->v_vflag &= ~VV_TEXT;
+				VOP_UNSET_TEXT(vp);
 			VM_OBJECT_UNLOCK(object);
 			vput(vp);
 		}

Modified: head/sys/vm/vnode_pager.c
==============================================================================
--- head/sys/vm/vnode_pager.c	Fri Sep 28 11:11:42 2012	(r241024)
+++ head/sys/vm/vnode_pager.c	Fri Sep 28 11:25:02 2012	(r241025)
@@ -277,7 +277,7 @@ vnode_pager_dealloc(object)
 		    __func__, vp, vp->v_writecount);
 	}
 	vp->v_object = NULL;
-	vp->v_vflag &= ~VV_TEXT;
+	VOP_UNSET_TEXT(vp);
 	VM_OBJECT_UNLOCK(object);
 	while (refs-- > 0)
 		vunref(vp);


More information about the svn-src-all mailing list