Subject: MNT_NODEV and nullfs and derived filesystems
To: None <tech-kern@netbsd.org, art@stacken.kth.se>
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
List: tech-kern
Date: 03/17/1999 16:23:28
--tKW2IUtsqtDRztdT
Content-Type: text/plain; charset=us-ascii
Hi,
As pointed out to me by Artur Grabowski, there is a problem with nullfs
and derived (umap, union): MNT_NODEV has to be checked at open(), which is not
done for these filesystems (MNT_NODEV on the underlying filesystem is
handled, however, so this is not really a problem as big as MNT_NOEXEC).
Below is a patch that should fix this for null, umap, union (this was
fixed some time ago in OpenBSD, but for nullfs only).
In my sense this is more a semantic problem than a security problem.
Comments ?
--
Manuel Bouyer, LIP6, Universite Paris VI. Manuel.Bouyer@lip6.fr
--
--tKW2IUtsqtDRztdT
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff
Index: miscfs/nullfs/null_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/nullfs/null_vnops.c,v
retrieving revision 1.13
diff -u -r1.13 null_vnops.c
--- null_vnops.c 1998/03/01 02:21:43 1.13
+++ null_vnops.c 1999/03/17 15:11:53
@@ -203,6 +203,7 @@
int null_lookup __P((void *));
int null_setattr __P((void *));
int null_access __P((void *));
+int null_open __P((void *));
/*
@@ -495,6 +496,24 @@
}
/*
+ * We must handle open to be able to catch MNT_NODEV and friends.
+ */
+int
+null_open(v)
+ void *v;
+{
+ struct vop_open_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ enum vtype lower_type = NULLVPTOLOWERVP(vp)->v_type;
+
+ if (((lower_type == VBLK) || (lower_type == VCHR)) &&
+ (vp->v_mount->mnt_flag & MNT_NODEV))
+ return ENXIO;
+
+ return null_bypass(ap);
+}
+
+/*
* We need to process our own vnode lock and then clear the
* interlock flag as it applies only to our vnode, not the
* vnodes below us on the stack.
@@ -666,6 +685,8 @@
{ &vop_inactive_desc, null_inactive },
{ &vop_reclaim_desc, null_reclaim },
{ &vop_print_desc, null_print },
+
+ { &vop_open_desc, null_open }, /* mount option handling */
{ &vop_strategy_desc, null_strategy },
{ &vop_bwrite_desc, null_bwrite },
Index: miscfs/umapfs/umap_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/umapfs/umap_vnops.c,v
retrieving revision 1.10
diff -u -r1.10 umap_vnops.c
--- umap_vnops.c 1998/03/01 02:21:51 1.10
+++ umap_vnops.c 1999/03/17 15:11:54
@@ -67,6 +67,7 @@
int umap_bwrite __P((void *));
int umap_lock __P((void *));
int umap_unlock __P((void *));
+int umap_open __P((void *));
extern int null_bypass __P((void *));
@@ -88,6 +89,9 @@
{ &vop_inactive_desc, umap_inactive },
{ &vop_reclaim_desc, umap_reclaim },
{ &vop_print_desc, umap_print },
+
+ { &vop_open_desc, umap_open }, /* mount option handling */
+
{ &vop_rename_desc, umap_rename },
{ &vop_strategy_desc, umap_strategy },
@@ -413,6 +417,25 @@
ap->a_vap->va_gid = (gid_t) NULLGROUP;
return (0);
+}
+
+/*
+ * We must handle open to be able to catch MNT_NODEV and friends.
+ */
+int
+umap_open(v)
+ void *v;
+{
+ struct vop_open_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ enum vtype lower_type = UMAPVPTOLOWERVP(vp)->v_type;
+
+
+ if (((lower_type == VBLK) || (lower_type == VCHR)) &&
+ (vp->v_mount->mnt_flag & MNT_NODEV))
+ return ENXIO;
+
+ return umap_bypass(ap);
}
/*ARGSUSED*/
Index: miscfs/union/union_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/union/union_vnops.c,v
retrieving revision 1.42
diff -u -r1.42 union_vnops.c
--- union_vnops.c 1998/06/05 19:53:00 1.42
+++ union_vnops.c 1999/03/17 15:11:55
@@ -639,8 +639,11 @@
}
/*
- * Just open the lower vnode
+ * Just open the lower vnode, but check for nodev mount flag
*/
+ if ((tvp->v_type == VBLK || tvp->v_type == VCHR) &&
+ (ap->a_vp->v_mount->mnt_flag & MNT_NODEV))
+ return ENXIO;
un->un_openl++;
vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY);
error = VOP_OPEN(tvp, mode, cred, p);
@@ -648,6 +651,12 @@
return (error);
}
+ /*
+ * Just open the upper vnode, checking for nodev mount flag first
+ */
+ if ((tvp->v_type == VBLK || tvp->v_type == VCHR) &&
+ (ap->a_vp->v_mount->mnt_flag & MNT_NODEV))
+ return ENXIO;
FIXUP(un);
--tKW2IUtsqtDRztdT--