summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/msdosfs/msdosfs_vfsops.c67
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