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