summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_default.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2012-09-28 11:25:02 +0000
committerkib <kib@FreeBSD.org>2012-09-28 11:25:02 +0000
commit8f845e475e69e9777c5f940109bf0c45b87aadda (patch)
tree2c2a67940ecbf715c5dc909f32de63a9eed6f793 /sys/kern/vfs_default.c
parent025fb75eb6e2720e82276647d1f8fad9515c281c (diff)
downloadFreeBSD-src-8f845e475e69e9777c5f940109bf0c45b87aadda.zip
FreeBSD-src-8f845e475e69e9777c5f940109bf0c45b87aadda.tar.gz
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
Diffstat (limited to 'sys/kern/vfs_default.c')
-rw-r--r--sys/kern/vfs_default.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c
index b807db8..31a650c 100644
--- a/sys/kern/vfs_default.c
+++ b/sys/kern/vfs_default.c
@@ -78,6 +78,10 @@ static int dirent_exists(struct vnode *vp, const char *dirname,
#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_args *ap)
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.
OpenPOWER on IntegriCloud