diff options
-rw-r--r-- | sys/msdosfs/msdosfs_vfsops.c | 67 |
1 files changed, 45 insertions, 22 deletions
diff --git a/sys/msdosfs/msdosfs_vfsops.c b/sys/msdosfs/msdosfs_vfsops.c index 7c6d21660b3..d5412e3df9b 100644 --- a/sys/msdosfs/msdosfs_vfsops.c +++ b/sys/msdosfs/msdosfs_vfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: msdosfs_vfsops.c,v 1.58 2010/09/23 18:40:00 oga Exp $ */ +/* $OpenBSD: msdosfs_vfsops.c,v 1.59 2010/11/17 12:27:03 jsing Exp $ */ /* $NetBSD: msdosfs_vfsops.c,v 1.48 1997/10/18 02:54:57 briggs Exp $ */ /*- @@ -62,6 +62,7 @@ #include <sys/ioctl.h> #include <sys/malloc.h> #include <sys/dirent.h> +#include <sys/disk.h> #include <msdosfs/bpb.h> #include <msdosfs/bootsect.h> @@ -103,10 +104,12 @@ msdosfs_mount(struct mount *mp, const char *path, void *data, size_t size; int error, flags; mode_t accessmode; + char *fspec = NULL; error = copyin(data, &args, sizeof(struct msdosfs_args)); if (error) return (error); + /* * If updating, check whether changing from read-only to * read/write; if there is no device name, that's all we do. @@ -114,7 +117,8 @@ msdosfs_mount(struct mount *mp, const char *path, void *data, if (mp->mnt_flag & MNT_UPDATE) { pmp = VFSTOMSDOSFS(mp); error = 0; - if (!(pmp->pm_flags & MSDOSFSMNT_RONLY) && (mp->mnt_flag & MNT_RDONLY)) { + if (!(pmp->pm_flags & MSDOSFSMNT_RONLY) && + (mp->mnt_flag & MNT_RDONLY)) { flags = WRITECLOSE; if (mp->mnt_flag & MNT_FORCE) flags |= FORCECLOSE; @@ -125,7 +129,8 @@ msdosfs_mount(struct mount *mp, const char *path, void *data, error = EOPNOTSUPP; if (error) return (error); - if ((pmp->pm_flags & MSDOSFSMNT_RONLY) && (mp->mnt_flag & MNT_WANTRDWR)) { + if ((pmp->pm_flags & MSDOSFSMNT_RONLY) && + (mp->mnt_flag & MNT_WANTRDWR)) { /* * If upgrade to read-write by non-root, then verify * that user has necessary permissions on the device. @@ -157,23 +162,32 @@ msdosfs_mount(struct mount *mp, const char *path, void *data, &args.export_info)); } } + /* * 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); + fspec = malloc(MNAMELEN, M_MOUNT, M_WAITOK); + error = copyinstr(args.fspec, fspec, MNAMELEN - 1, &size); + if (error) + goto error; + disk_map(fspec, fspec, MNAMELEN, DM_OPENBLCK); + + NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fspec, p); if ((error = namei(ndp)) != 0) - return (error); + goto error; + devvp = ndp->ni_vp; if (devvp->v_type != VBLK) { - vrele(devvp); - return (ENOTBLK); + error = ENOTBLK; + goto error_devvp; } if (major(devvp->v_rdev) >= nblkdev) { - vrele(devvp); - return (ENXIO); + error = ENXIO; + goto error_devvp; } + /* * If mount by non-root, then verify that user has necessary * permissions on the device. @@ -184,12 +198,11 @@ msdosfs_mount(struct mount *mp, const char *path, void *data, accessmode |= VWRITE; vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p); - if (error) { - vput(devvp); - return (error); - } VOP_UNLOCK(devvp, 0, p); + if (error) + goto error_devvp; } + if ((mp->mnt_flag & MNT_UPDATE) == 0) error = msdosfs_mountfs(devvp, mp, p, &args); else { @@ -198,10 +211,9 @@ msdosfs_mount(struct mount *mp, const char *path, void *data, else vrele(devvp); } - if (error) { - vrele(devvp); - return (error); - } + if (error) + goto error_devvp; + pmp = VFSTOMSDOSFS(mp); pmp->pm_gid = args.gid; pmp->pm_uid = args.uid; @@ -210,7 +222,8 @@ msdosfs_mount(struct mount *mp, const char *path, void *data, if (pmp->pm_flags & MSDOSFSMNT_NOWIN95) pmp->pm_flags |= MSDOSFSMNT_SHORTNAME; - else if (!(pmp->pm_flags & (MSDOSFSMNT_SHORTNAME | MSDOSFSMNT_LONGNAME))) { + else if (!(pmp->pm_flags & + (MSDOSFSMNT_SHORTNAME | MSDOSFSMNT_LONGNAME))) { struct vnode *rvp; /* @@ -221,7 +234,7 @@ msdosfs_mount(struct mount *mp, const char *path, void *data, else { if ((error = msdosfs_root(mp, &rvp)) != 0) { msdosfs_unmount(mp, MNT_FORCE, p); - return (error); + goto error; } pmp->pm_flags |= findwin95(VTODE(rvp)) ? MSDOSFSMNT_LONGNAME @@ -231,14 +244,24 @@ msdosfs_mount(struct mount *mp, const char *path, void *data, } (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); - (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, - &size); + + size = strlcpy(mp->mnt_stat.f_mntfromname, fspec, MNAMELEN - 1); bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); bcopy(&args, &mp->mnt_stat.mount_info.msdosfs_args, sizeof(args)); #ifdef MSDOSFS_DEBUG - printf("msdosfs_mount(): mp %x, pmp %x, inusemap %x\n", mp, pmp, pmp->pm_inusemap); + printf("msdosfs_mount(): mp %x, pmp %x, inusemap %x\n", mp, + pmp, pmp->pm_inusemap); #endif return (0); + +error_devvp: + vrele(devvp); + +error: + if (fspec) + free(fspec, M_MOUNT); + + return (error); } int |