Module Name: src Committed By: christos Date: Wed Nov 15 21:21:18 UTC 2017
Modified Files: src/sys/ufs/ffs: ffs_vfsops.c Log Message: PR/52728: Izumi Tsutsui: "mount -u /dev/ /" triggers kernel panic Simplify the control flow of the mount code and make sure that the mountfrom argument can be converted to a block device in the update case. XXX: pullup-8 To generate a diff of this commit: cvs rdiff -u -r1.354 -r1.355 src/sys/ufs/ffs/ffs_vfsops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/ufs/ffs/ffs_vfsops.c diff -u src/sys/ufs/ffs/ffs_vfsops.c:1.354 src/sys/ufs/ffs/ffs_vfsops.c:1.355 --- src/sys/ufs/ffs/ffs_vfsops.c:1.354 Sun Aug 20 08:51:38 2017 +++ src/sys/ufs/ffs/ffs_vfsops.c Wed Nov 15 16:21:18 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ffs_vfsops.c,v 1.354 2017/08/20 12:51:38 maya Exp $ */ +/* $NetBSD: ffs_vfsops.c,v 1.355 2017/11/15 21:21:18 christos Exp $ */ /*- * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. @@ -61,7 +61,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.354 2017/08/20 12:51:38 maya Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.355 2017/11/15 21:21:18 christos Exp $"); #if defined(_KERNEL_OPT) #include "opt_ffs.h" @@ -418,12 +418,13 @@ ffs_mount(struct mount *mp, const char * return EINVAL; } + ump = VFSTOUFS(mp); + if ((mp->mnt_flag & (MNT_GETARGS|MNT_UPDATE)) && ump == NULL) { + DPRINTF("no ump"); + return EIO; + } + if (mp->mnt_flag & MNT_GETARGS) { - ump = VFSTOUFS(mp); - if (ump == NULL) { - DPRINTF("no ump"); - return EIO; - } args->fspec = NULL; *data_len = sizeof *args; return 0; @@ -432,7 +433,13 @@ ffs_mount(struct mount *mp, const char * update = mp->mnt_flag & MNT_UPDATE; /* Check arguments */ - if (args->fspec != NULL) { + if (args->fspec == NULL) { + if (!update) { + /* New mounts must have a filename for the device */ + DPRINTF("no filename for mount"); + return EINVAL; + } + } else { /* * Look up the name and verify that it's sane. */ @@ -443,48 +450,43 @@ ffs_mount(struct mount *mp, const char * return error; } - if (!update) { - /* - * Be sure this is a valid block device - */ - if (devvp->v_type != VBLK) { - DPRINTF("non block device %d", devvp->v_type); - error = ENOTBLK; - } else if (bdevsw_lookup(devvp->v_rdev) == NULL) { - DPRINTF("can't find block device 0x%jx", - devvp->v_rdev); - error = ENXIO; - } - } else { + /* + * Be sure this is a valid block device + */ + if (devvp->v_type != VBLK) { + DPRINTF("non block device %d", devvp->v_type); + error = ENOTBLK; + goto fail; + } + + if (bdevsw_lookup(devvp->v_rdev) == NULL) { + DPRINTF("can't find block device 0x%jx", + devvp->v_rdev); + error = ENXIO; + goto fail; + } + + if (update) { /* * Be sure we're still naming the same device * used for our initial mount */ - ump = VFSTOUFS(mp); - if (devvp != ump->um_devvp) { - if (devvp->v_rdev != ump->um_devvp->v_rdev) { - DPRINTF("wrong device 0x%jx != 0x%jx", - (uintmax_t)devvp->v_rdev, - (uintmax_t)ump->um_devvp->v_rdev); - error = EINVAL; - } else { - vrele(devvp); - devvp = ump->um_devvp; - vref(devvp); - } + if (devvp != ump->um_devvp && + devvp->v_rdev != ump->um_devvp->v_rdev) { + DPRINTF("wrong device 0x%jx != 0x%jx", + (uintmax_t)devvp->v_rdev, + (uintmax_t)ump->um_devvp->v_rdev); + error = EINVAL; + goto fail; } + vrele(devvp); + devvp = NULL; } - } else { - if (!update) { - /* New mounts must have a filename for the device */ - DPRINTF("no filename for mount"); - return EINVAL; - } else { - /* Use the extant mount */ - ump = VFSTOUFS(mp); - devvp = ump->um_devvp; - vref(devvp); - } + } + + if (devvp == NULL) { + devvp = ump->um_devvp; + vref(devvp); } /* @@ -495,25 +497,17 @@ ffs_mount(struct mount *mp, const char * * updating the mount is okay (for example, as far as securelevel goes) * which leaves us with the normal check. */ - if (error == 0) { - accessmode = VREAD; - if (update ? - (mp->mnt_iflag & IMNT_WANTRDWR) != 0 : - (mp->mnt_flag & MNT_RDONLY) == 0) - accessmode |= VWRITE; - vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); - error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, - KAUTH_REQ_SYSTEM_MOUNT_DEVICE, mp, devvp, - KAUTH_ARG(accessmode)); - if (error) { - DPRINTF("kauth returned %d", error); - } - VOP_UNLOCK(devvp); - } - + accessmode = VREAD; + if (update ? (mp->mnt_iflag & IMNT_WANTRDWR) != 0 : + (mp->mnt_flag & MNT_RDONLY) == 0) + accessmode |= VWRITE; + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); + error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, + KAUTH_REQ_SYSTEM_MOUNT_DEVICE, mp, devvp, KAUTH_ARG(accessmode)); + VOP_UNLOCK(devvp); if (error) { - vrele(devvp); - return (error); + DPRINTF("kauth returned %d", error); + goto fail; } #ifdef WAPBL