Hi, When pulling and unmounting an umass USB stick, the file system may end up in an inconsistent state. The fstype dependent mp->mnt_data is NULL, but the general mp is still listed as a valid mount point. Next access to the file system will crash with a NULL pointer dereference.
If the close of the device fails, the file system specific unmount frees it structures and reports an error. Because of the error, the general unmount keeps the mount. This was introduced in 1987 here with an unrelated commit message. https://svnweb.freebsd.org/csrg/sys/ufs/ffs/ffs_vfsops.c?r1=30383&r2=30749&pathrev=30749 If closing the device fails, the mount point should go away anyway. There is nothing we can do about it. Pedro has added a workaround for EIO, but in my case the error is ENXIO. Remove the this general check and don't generate an error code in the file system specific unmount code. As multiple file system types are involved, tests are welcome. ok? bluhm Index: kern/vfs_syscalls.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/kern/vfs_syscalls.c,v retrieving revision 1.251 diff -u -p -r1.251 vfs_syscalls.c --- kern/vfs_syscalls.c 6 Jan 2016 17:59:30 -0000 1.251 +++ kern/vfs_syscalls.c 1 Feb 2016 15:11:39 -0000 @@ -437,7 +437,7 @@ dounmount(struct mount *mp, int flags, s (flags & MNT_FORCE)) error = VFS_UNMOUNT(mp, flags, p); - if (error && error != EIO && !(flags & MNT_DOOMED)) { + if (error && !(flags & MNT_DOOMED)) { if ((mp->mnt_flag & MNT_RDONLY) == 0 && hadsyncer) (void) vfs_allocate_syncvnode(mp); vfs_unbusy(mp); Index: isofs/cd9660/cd9660_vfsops.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/isofs/cd9660/cd9660_vfsops.c,v retrieving revision 1.71 diff -u -p -r1.71 cd9660_vfsops.c --- isofs/cd9660/cd9660_vfsops.c 9 Sep 2015 15:59:19 -0000 1.71 +++ isofs/cd9660/cd9660_vfsops.c 1 Feb 2016 15:04:46 -0000 @@ -457,7 +457,7 @@ out: if (isomp) { free((caddr_t)isomp, M_ISOFSMNT, 0); - mp->mnt_data = (qaddr_t)0; + mp->mnt_data = NULL; } return (error); } @@ -586,12 +586,12 @@ cd9660_unmount(mp, mntflags, p) isomp->im_devvp->v_specmountpoint = NULL; vn_lock(isomp->im_devvp, LK_EXCLUSIVE | LK_RETRY, p); - error = VOP_CLOSE(isomp->im_devvp, FREAD, NOCRED, p); + VOP_CLOSE(isomp->im_devvp, FREAD, NOCRED, p); vput(isomp->im_devvp); free((caddr_t)isomp, M_ISOFSMNT, 0); - mp->mnt_data = (qaddr_t)0; + mp->mnt_data = NULL; mp->mnt_flag &= ~MNT_LOCAL; - return (error); + return (0); } /* Index: isofs/udf/udf_vfsops.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/isofs/udf/udf_vfsops.c,v retrieving revision 1.46 diff -u -p -r1.46 udf_vfsops.c --- isofs/udf/udf_vfsops.c 31 Aug 2015 06:56:25 -0000 1.46 +++ isofs/udf/udf_vfsops.c 1 Feb 2016 15:03:29 -0000 @@ -476,10 +476,8 @@ udf_unmount(struct mount *mp, int mntfla vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); vinvalbuf(devvp, V_SAVE, NOCRED, p, 0, 0); - error = VOP_CLOSE(devvp, FREAD, NOCRED, p); + VOP_CLOSE(devvp, FREAD, NOCRED, p); VOP_UNLOCK(devvp, 0, p); - if (error) - return (error); devvp->v_specmountpoint = NULL; vrele(devvp); @@ -495,7 +493,7 @@ udf_unmount(struct mount *mp, int mntfla free(ump, M_UDFMOUNT, 0); - mp->mnt_data = (qaddr_t)0; + mp->mnt_data = NULL; mp->mnt_flag &= ~MNT_LOCAL; return (0); Index: miscfs/fuse/fuse_vfsops.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/miscfs/fuse/fuse_vfsops.c,v retrieving revision 1.16 diff -u -p -r1.16 fuse_vfsops.c --- miscfs/fuse/fuse_vfsops.c 19 Jul 2015 14:21:14 -0000 1.16 +++ miscfs/fuse/fuse_vfsops.c 1 Feb 2016 15:03:29 -0000 @@ -165,8 +165,9 @@ fusefs_unmount(struct mount *mp, int mnt fuse_device_cleanup(fmp->dev, NULL); fuse_device_set_fmp(fmp, 0); free(fmp, M_FUSEFS, 0); + mp->mnt_data = NULL; - return (error); + return (0); } int Index: msdosfs/msdosfs_vfsops.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/msdosfs/msdosfs_vfsops.c,v retrieving revision 1.73 diff -u -p -r1.73 msdosfs_vfsops.c --- msdosfs/msdosfs_vfsops.c 23 Oct 2015 17:21:34 -0000 1.73 +++ msdosfs/msdosfs_vfsops.c 1 Feb 2016 15:05:08 -0000 @@ -590,7 +590,7 @@ error_exit: if (pmp->pm_inusemap) free(pmp->pm_inusemap, M_MSDOSFSFAT, 0); free(pmp, M_MSDOSFSMNT, 0); - mp->mnt_data = (qaddr_t)0; + mp->mnt_data = NULL; } return (error); } @@ -626,14 +626,14 @@ msdosfs_unmount(struct mount *mp, int mn vprint("msdosfs_umount(): just before calling VOP_CLOSE()\n", vp); #endif vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); - error = VOP_CLOSE(vp, - pmp->pm_flags & MSDOSFSMNT_RONLY ? FREAD : FREAD|FWRITE, NOCRED, p); + VOP_CLOSE(vp, pmp->pm_flags & MSDOSFSMNT_RONLY ? FREAD : FREAD|FWRITE, + NOCRED, p); vput(vp); free(pmp->pm_inusemap, M_MSDOSFSFAT, 0); free(pmp, M_MSDOSFSMNT, 0); - mp->mnt_data = (qaddr_t)0; + mp->mnt_data = NULL; mp->mnt_flag &= ~MNT_LOCAL; - return (error); + return (0); } int Index: nfs/nfs_vfsops.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/nfs/nfs_vfsops.c,v retrieving revision 1.107 diff -u -p -r1.107 nfs_vfsops.c --- nfs/nfs_vfsops.c 14 Mar 2015 03:38:52 -0000 1.107 +++ nfs/nfs_vfsops.c 1 Feb 2016 15:03:29 -0000 @@ -702,6 +702,7 @@ nfs_unmount(struct mount *mp, int mntfla m_freem(nmp->nm_nam); timeout_del(&nmp->nm_rtimeout); free(nmp, M_NFSMNT, sizeof(*nmp)); + mp->mnt_data = NULL; return (0); } Index: ntfs/ntfs_vfsops.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/ntfs/ntfs_vfsops.c,v retrieving revision 1.44 diff -u -p -r1.44 ntfs_vfsops.c --- ntfs/ntfs_vfsops.c 14 Mar 2015 03:38:52 -0000 1.44 +++ ntfs/ntfs_vfsops.c 1 Feb 2016 15:03:29 -0000 @@ -523,21 +523,18 @@ ntfs_unmount(struct mount *mp, int mntfl /* lock the device vnode before calling VOP_CLOSE() */ VOP_LOCK(ntmp->ntm_devvp, LK_EXCLUSIVE | LK_RETRY, p); vinvalbuf(ntmp->ntm_devvp, V_SAVE, NOCRED, p, 0, 0); - - error = VOP_CLOSE(ntmp->ntm_devvp, ronly ? FREAD : FREAD|FWRITE, - NOCRED, p); - + VOP_CLOSE(ntmp->ntm_devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); vput(ntmp->ntm_devvp); /* free the toupper table, if this has been last mounted ntfs volume */ ntfs_toupper_unuse(p); DPRINTF("ntfs_unmount: freeing memory...\n"); - mp->mnt_data = NULL; - mp->mnt_flag &= ~MNT_LOCAL; free(ntmp->ntm_ad, M_NTFSMNT, 0); free(ntmp, M_NTFSMNT, 0); - return (error); + mp->mnt_data = NULL; + mp->mnt_flag &= ~MNT_LOCAL; + return (0); } int Index: ufs/ext2fs/ext2fs_vfsops.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/ufs/ext2fs/ext2fs_vfsops.c,v retrieving revision 1.85 diff -u -p -r1.85 ext2fs_vfsops.c --- ufs/ext2fs/ext2fs_vfsops.c 14 Mar 2015 03:38:52 -0000 1.85 +++ ufs/ext2fs/ext2fs_vfsops.c 1 Feb 2016 15:05:37 -0000 @@ -602,7 +602,7 @@ out: if (ump) { free(ump->um_e2fs, M_UFSMNT, sizeof *ump->um_e2fs); free(ump, M_UFSMNT, sizeof *ump); - mp->mnt_data = (qaddr_t)0; + mp->mnt_data = NULL; } return (error); } @@ -636,15 +636,15 @@ ext2fs_unmount(struct mount *mp, int mnt if (ump->um_devvp->v_type != VBAD) ump->um_devvp->v_specmountpoint = NULL; vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p); - error = VOP_CLOSE(ump->um_devvp, fs->e2fs_ronly ? FREAD : FREAD|FWRITE, + VOP_CLOSE(ump->um_devvp, fs->e2fs_ronly ? FREAD : FREAD|FWRITE, NOCRED, p); vput(ump->um_devvp); free(fs->e2fs_gd, M_UFSMNT, gdescs_space); free(fs, M_UFSMNT, sizeof *fs); free(ump, M_UFSMNT, sizeof *ump); - mp->mnt_data = (qaddr_t)0; + mp->mnt_data = NULL; mp->mnt_flag &= ~MNT_LOCAL; - return (error); + return (0); } /* Index: ufs/ffs/ffs_vfsops.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/ufs/ffs/ffs_vfsops.c,v retrieving revision 1.150 diff -u -p -r1.150 ffs_vfsops.c --- ufs/ffs/ffs_vfsops.c 12 Jan 2016 11:41:00 -0000 1.150 +++ ufs/ffs/ffs_vfsops.c 1 Feb 2016 15:03:29 -0000 @@ -1022,15 +1022,15 @@ ffs_unmount(struct mount *mp, int mntfla vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p); vinvalbuf(ump->um_devvp, V_SAVE, NOCRED, p, 0, 0); - error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE, - NOCRED, p); + VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE, + NOCRED, p); vput(ump->um_devvp); free(fs->fs_csp, M_UFSMNT, 0); free(fs, M_UFSMNT, fs->fs_sbsize); free(ump, M_UFSMNT, sizeof(*ump)); - mp->mnt_data = (qaddr_t)0; + mp->mnt_data = NULL; mp->mnt_flag &= ~MNT_LOCAL; - return (error); + return (0); } /*
