Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/ufs/ffs PR/16136: Chris Jepeway: Bogus entry in /etc/fst...
details: https://anonhg.NetBSD.org/src/rev/903ac8599f7d
branches: trunk
changeset: 524851:903ac8599f7d
user: christos <christos%NetBSD.org@localhost>
date: Sun Mar 31 20:53:25 2002 +0000
description:
PR/16136: Chris Jepeway: Bogus entry in /etc/fstab can panic kernel.
diffstat:
sys/ufs/ffs/ffs_vfsops.c | 182 ++++++++++++++++++++++++++++------------------
1 files changed, 109 insertions(+), 73 deletions(-)
diffs (233 lines):
diff -r a6863d868260 -r 903ac8599f7d sys/ufs/ffs/ffs_vfsops.c
--- a/sys/ufs/ffs/ffs_vfsops.c Sun Mar 31 19:47:39 2002 +0000
+++ b/sys/ufs/ffs/ffs_vfsops.c Sun Mar 31 20:53:25 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ffs_vfsops.c,v 1.94 2002/03/17 00:02:34 chs Exp $ */
+/* $NetBSD: ffs_vfsops.c,v 1.95 2002/03/31 20:53:25 christos Exp $ */
/*
* Copyright (c) 1989, 1991, 1993, 1994
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.94 2002/03/17 00:02:34 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.95 2002/03/31 20:53:25 christos Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@@ -186,7 +186,7 @@
struct ufsmount *ump = NULL;
struct fs *fs;
size_t size;
- int error, flags;
+ int error, flags, update;
mode_t accessmode;
error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args));
@@ -197,14 +197,115 @@
mp->mnt_flag &= ~MNT_SOFTDEP;
#endif
+ update = mp->mnt_flag & MNT_UPDATE;
+
+ /* Check arguments */
+ if (update) {
+ /* Use the extant mount */
+ ump = VFSTOUFS(mp);
+ devvp = ump->um_devvp;
+ } else {
+ /* New mounts must have a filename for the device */
+ if (args.fspec == NULL)
+ return EINVAL;
+
+ /* Check for update-only flags */
+ if (mp->mnt_flag &
+ (MNT_WANTRDWR | /*
+ * Upgrading from read-only to
+ * read-write can only occur after
+ * the initial mount
+ */
+ MNT_EXRDONLY |
+ MNT_DEFEXPORTED |
+ MNT_EXPORTANON |
+ MNT_EXKERB | /* Only update mounts are allowed */
+ MNT_EXNORESPORT | /* to affect exporting */
+ MNT_EXPUBLIC |
+ MNT_DELEXPORT))
+ return EINVAL;
+ }
+
+ error = 0;
+
+ if (args.fspec) {
+ /*
+ * Look up the name and verify that it's sane.
+ */
+ NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
+ if ((error = namei(ndp)) != 0)
+ return (error);
+ devvp = ndp->ni_vp;
+
+ if (!update) {
+ /*
+ * Be sure this is a valid block device
+ */
+ if (devvp->v_type != VBLK)
+ error = ENOTBLK;
+ else if (major(devvp->v_rdev) >= nblkdev)
+ error = ENXIO;
+ } else {
+ /*
+ * Be sure we're still naming the same device
+ * used for our initial mount
+ */
+ if (devvp != ump->um_devvp)
+ error = EINVAL;
+ else
+ /*
+ * The initial mount got a reference on this
+ * device, so drop the one obtained via
+ * namei(), above
+ */
+ vrele(devvp);
+ }
+ }
+
/*
- * If updating, check whether changing from read-only to
- * read/write; if there is no device name, that's all we do.
+ * If mount by non-root, then verify that user has necessary
+ * permissions on the device.
*/
- if (mp->mnt_flag & MNT_UPDATE) {
+ if (error == 0 && p->p_ucred->cr_uid != 0) {
+ accessmode = VREAD;
+ if ((!update && (mp->mnt_flag & MNT_RDONLY) == 0) ||
+ (update && (mp->mnt_flag & MNT_WANTRDWR)))
+ accessmode |= VWRITE;
+ vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
+ error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p);
+ VOP_UNLOCK(devvp, 0);
+ }
+
+ if (error) {
+ vrele(devvp);
+ return (error);
+ }
+
+ if (!update) {
+ error = ffs_mountfs(devvp, mp, p);
+ if (error) {
+ vrele(devvp);
+ return (error);
+ }
+
ump = VFSTOUFS(mp);
fs = ump->um_fs;
+ if ((mp->mnt_flag & (MNT_SOFTDEP | MNT_ASYNC)) ==
+ (MNT_SOFTDEP | MNT_ASYNC)) {
+ printf("%s fs uses soft updates, "
+ "ignoring async mode\n",
+ fs->fs_fsmnt);
+ mp->mnt_flag &= ~MNT_ASYNC;
+ }
+ } else {
+ /*
+ * Update the mount
+ */
+ fs = ump->um_fs;
if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
+ /*
+ * Changing from r/w to r/o
+ */
flags = WRITECLOSE;
if (mp->mnt_flag & MNT_FORCE)
flags |= FORCECLOSE;
@@ -275,20 +376,11 @@
if (error)
return (error);
}
+
if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
/*
- * If upgrade to read-write by non-root, then verify
- * that user has necessary permissions on the device.
+ * Changing from read-only to read/write
*/
- devvp = ump->um_devvp;
- if (p->p_ucred->cr_uid != 0) {
- vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
- error = VOP_ACCESS(devvp, VREAD | VWRITE,
- p->p_ucred, p);
- VOP_UNLOCK(devvp, 0);
- if (error)
- return (error);
- }
fs->fs_ronly = 0;
fs->fs_clean <<= 1;
fs->fs_fmod = 1;
@@ -312,63 +404,7 @@
mp->mnt_flag &= ~MNT_ASYNC;
}
}
- /*
- * Not an update, or updating the name: look up the name
- * and verify that it refers to a sensible block device.
- */
- NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
- if ((error = namei(ndp)) != 0)
- return (error);
- devvp = ndp->ni_vp;
- if (devvp->v_type != VBLK) {
- vrele(devvp);
- return (ENOTBLK);
- }
- if (major(devvp->v_rdev) >= nblkdev) {
- vrele(devvp);
- return (ENXIO);
- }
- /*
- * If mount by non-root, then verify that user has necessary
- * permissions on the device.
- */
- if (p->p_ucred->cr_uid != 0) {
- accessmode = VREAD;
- if ((mp->mnt_flag & MNT_RDONLY) == 0)
- accessmode |= VWRITE;
- vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
- error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p);
- VOP_UNLOCK(devvp, 0);
- if (error) {
- vrele(devvp);
- return (error);
- }
- }
- if ((mp->mnt_flag & MNT_UPDATE) == 0) {
- error = ffs_mountfs(devvp, mp, p);
- if (!error) {
- ump = VFSTOUFS(mp);
- fs = ump->um_fs;
- if ((mp->mnt_flag & (MNT_SOFTDEP | MNT_ASYNC)) ==
- (MNT_SOFTDEP | MNT_ASYNC)) {
- printf("%s fs uses soft updates, "
- "ignoring async mode\n",
- fs->fs_fsmnt);
- mp->mnt_flag &= ~MNT_ASYNC;
- }
- }
- }
- else {
- if (devvp != ump->um_devvp)
- error = EINVAL; /* needs translation */
- else
- vrele(devvp);
- }
- if (error) {
- vrele(devvp);
- return (error);
- }
(void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
memset(fs->fs_fsmnt + size, 0, sizeof(fs->fs_fsmnt) - size);
memcpy(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN);
Home |
Main Index |
Thread Index |
Old Index