diff --git a/sys/compat/linprocfs/linprocfs_vfsops.c b/sys/compat/linprocfs/linprocfs_vfsops.c index 0caa113eb86b..1e4bc87c7da2 100644 --- a/sys/compat/linprocfs/linprocfs_vfsops.c +++ b/sys/compat/linprocfs/linprocfs_vfsops.c @@ -90,9 +90,6 @@ linprocfs_mount(mp, path, data, ndp, p) mp->mnt_data = 0; vfs_getnewfsid(mp); - (void) copyinstr(path, (caddr_t)mp->mnt_stat.f_mntonname, MNAMELEN, &size); - bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); - size = sizeof("linprocfs") - 1; bcopy("linprocfs", mp->mnt_stat.f_mntfromname, size); bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c index 492742f2b057..6f246af68c6e 100644 --- a/sys/compat/linux/linux_file.c +++ b/sys/compat/linux/linux_file.c @@ -901,14 +901,16 @@ linux_pwrite(p, uap) int linux_mount(struct proc *p, struct linux_mount_args *args) { - struct mount_args bsd_args; struct ufs_args ufs; char fstypename[MFSNAMELEN]; char mntonname[MNAMELEN], mntfromname[MNAMELEN]; - int error = 0; + int error; + int fsflags; + const char *fstype; + void *fsdata; - error = copyinstr(args->filesystemtype, fstypename, - MFSNAMELEN - 1, NULL); + error = copyinstr(args->filesystemtype, fstypename, MFSNAMELEN - 1, + NULL); if (error) return (error); error = copyinstr(args->specialfile, mntfromname, MFSNAMELEN - 1, NULL); @@ -925,22 +927,21 @@ linux_mount(struct proc *p, struct linux_mount_args *args) #endif if (strcmp(fstypename, "ext2") == 0) { - bsd_args.type = "ext2fs"; - bsd_args.data = (void *)&ufs; + fstype = "ext2fs"; + fsdata = &ufs; ufs.fspec = mntfromname; #define DEFAULT_ROOTID -2 ufs.export.ex_root = DEFAULT_ROOTID; ufs.export.ex_flags = args->rwflag & LINUX_MS_RDONLY ? MNT_EXRDONLY : 0; } else if (strcmp(fstypename, "proc") == 0) { - bsd_args.type = "linprocfs"; - bsd_args.data = NULL; + fstype = "linprocfs"; + fsdata = NULL; } else { return (ENODEV); } - bsd_args.path = mntonname; - bsd_args.flags = 0; + fsflags = 0; if ((args->rwflag & 0xffff0000) == 0xc0ed0000) { /* @@ -948,18 +949,18 @@ linux_mount(struct proc *p, struct linux_mount_args *args) * FreeBSD has is !ASYNC, which is our default. */ if (args->rwflag & LINUX_MS_RDONLY) - bsd_args.flags |= MNT_RDONLY; + fsflags |= MNT_RDONLY; if (args->rwflag & LINUX_MS_NOSUID) - bsd_args.flags |= MNT_NOSUID; + fsflags |= MNT_NOSUID; if (args->rwflag & LINUX_MS_NODEV) - bsd_args.flags |= MNT_NODEV; + fsflags |= MNT_NODEV; if (args->rwflag & LINUX_MS_NOEXEC) - bsd_args.flags |= MNT_NOEXEC; + fsflags |= MNT_NOEXEC; if (args->rwflag & LINUX_MS_REMOUNT) - bsd_args.flags |= MNT_UPDATE; + fsflags |= MNT_UPDATE; } - return (mount1(p, &bsd_args, UIO_SYSSPACE)); + return (vfs_mount(p, fstype, mntonname, fsflags, fsdata)); } int diff --git a/sys/fs/cd9660/cd9660_vfsops.c b/sys/fs/cd9660/cd9660_vfsops.c index 3017339f2251..606f9d379413 100644 --- a/sys/fs/cd9660/cd9660_vfsops.c +++ b/sys/fs/cd9660/cd9660_vfsops.c @@ -249,8 +249,6 @@ cd9660_mount(mp, path, data, ndp, p) return error; } imp = VFSTOISOFS(mp); - (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); bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); diff --git a/sys/fs/devfs/devfs_vfsops.c b/sys/fs/devfs/devfs_vfsops.c index eb13d8f719cb..ee369e16ee81 100644 --- a/sys/fs/devfs/devfs_vfsops.c +++ b/sys/fs/devfs/devfs_vfsops.c @@ -67,7 +67,6 @@ devfs_mount(mp, path, data, ndp, p) struct proc *p; { int error; - size_t size; struct devfs_mount *fmp; struct vnode *rvp; @@ -100,13 +99,6 @@ devfs_mount(mp, path, data, ndp, p) } VOP_UNLOCK(rvp, 0, p); - if (path != NULL) { - (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); - } else { - strcpy(mp->mnt_stat.f_mntonname, "/"); - size = 1; - } - bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); bcopy("devfs", mp->mnt_stat.f_mntfromname, sizeof("devfs")); (void)devfs_statfs(mp, &mp->mnt_stat, p); diff --git a/sys/fs/fdescfs/fdesc_vfsops.c b/sys/fs/fdescfs/fdesc_vfsops.c index 84940c70a745..7737e37dd5c7 100644 --- a/sys/fs/fdescfs/fdesc_vfsops.c +++ b/sys/fs/fdescfs/fdesc_vfsops.c @@ -74,7 +74,6 @@ fdesc_mount(mp, path, data, ndp, p) struct proc *p; { int error = 0; - u_int size; struct fdescmount *fmp; struct vnode *rvp; @@ -98,8 +97,6 @@ fdesc_mount(mp, path, data, ndp, p) mp->mnt_data = (qaddr_t) fmp; vfs_getnewfsid(mp); - (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); - bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); bcopy("fdesc", mp->mnt_stat.f_mntfromname, sizeof("fdesc")); (void)fdesc_statfs(mp, &mp->mnt_stat, p); diff --git a/sys/fs/hpfs/hpfs_vfsops.c b/sys/fs/hpfs/hpfs_vfsops.c index 1581851da1ca..2d40b2da1253 100644 --- a/sys/fs/hpfs/hpfs_vfsops.c +++ b/sys/fs/hpfs/hpfs_vfsops.c @@ -272,16 +272,12 @@ hpfs_mount ( /* * Since this is a new mount, we want the names for * the device and the mount point copied in. If an - * error occurs, the mountpoint is discarded by the - * upper level code. + * error occurs, the mountpoint is discarded by the + * upper level code. Note that vfs_mount() handles + * copying the mountpoint f_mntonname for us, so we + * don't have to do it here unless we want to set it + * to something other than "path" for some rason. */ - /* Save "last mounted on" info for mount point (NULL pad)*/ - copyinstr( path, /* mount point*/ - mp->mnt_stat.f_mntonname, /* save area*/ - MNAMELEN - 1, /* max size*/ - &size); /* real size*/ - bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size); - /* Save "mounted from" info for mount point (NULL pad)*/ copyinstr( args.fspec, /* device name*/ mp->mnt_stat.f_mntfromname, /* save area*/ diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c index 3088d7a2bd6a..672ea5df2e2f 100644 --- a/sys/fs/msdosfs/msdosfs_vfsops.c +++ b/sys/fs/msdosfs/msdosfs_vfsops.c @@ -345,9 +345,6 @@ msdosfs_mount(mp, path, data, ndp, p) msdosfs_unmount(mp, MNT_FORCE, p); return error; } - - (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); bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); diff --git a/sys/fs/ntfs/ntfs_vfsops.c b/sys/fs/ntfs/ntfs_vfsops.c index 384883e81159..89a7dd7bc0f4 100644 --- a/sys/fs/ntfs/ntfs_vfsops.c +++ b/sys/fs/ntfs/ntfs_vfsops.c @@ -376,16 +376,12 @@ ntfs_mount ( /* * Since this is a new mount, we want the names for * the device and the mount point copied in. If an - * error occurs, the mountpoint is discarded by the - * upper level code. + * error occurs, the mountpoint is discarded by the + * upper level code. Note that vfs_mount() handles + * copying the mountpoint f_mntonname for us, so we + * don't have to do it here unless we want to set it + * to something other than "path" for some rason. */ - /* Save "last mounted on" info for mount point (NULL pad)*/ - copyinstr( path, /* mount point*/ - mp->mnt_stat.f_mntonname, /* save area*/ - MNAMELEN - 1, /* max size*/ - &size); /* real size*/ - bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size); - /* Save "mounted from" info for mount point (NULL pad)*/ copyinstr( args.fspec, /* device name*/ mp->mnt_stat.f_mntfromname, /* save area*/ diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c index 333916237b4b..b852cc45ff1e 100644 --- a/sys/fs/nullfs/null_vfsops.c +++ b/sys/fs/nullfs/null_vfsops.c @@ -191,8 +191,6 @@ nullfs_mount(mp, path, data, ndp, p) mp->mnt_data = (qaddr_t) xmp; vfs_getnewfsid(mp); - (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); - bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size); bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); diff --git a/sys/fs/nwfs/nwfs_vfsops.c b/sys/fs/nwfs/nwfs_vfsops.c index 3e76b30ac1a9..7d17e7d0247d 100644 --- a/sys/fs/nwfs/nwfs_vfsops.c +++ b/sys/fs/nwfs/nwfs_vfsops.c @@ -146,7 +146,6 @@ static int nwfs_mount(struct mount *mp, char *path, caddr_t data, struct nameidata *ndp, struct proc *p) { struct nwfs_args args; /* will hold data from mount request */ - size_t size; int error; struct nwmount *nmp = NULL; struct ncp_conn *conn = NULL; @@ -198,8 +197,6 @@ static int nwfs_mount(struct mount *mp, char *path, caddr_t data, nmp->m.dir_mode = (nmp->m.dir_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR; if ((error = nwfs_initnls(nmp)) != 0) goto bad; - (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); - bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); pc = mp->mnt_stat.f_mntfromname; pe = pc+sizeof(mp->mnt_stat.f_mntfromname); bzero(pc, MNAMELEN); diff --git a/sys/fs/portalfs/portal_vfsops.c b/sys/fs/portalfs/portal_vfsops.c index 139746d3d35b..3f7903ca2577 100644 --- a/sys/fs/portalfs/portal_vfsops.c +++ b/sys/fs/portalfs/portal_vfsops.c @@ -133,8 +133,6 @@ portal_mount(mp, path, data, ndp, p) mp->mnt_data = (qaddr_t) fmp; vfs_getnewfsid(mp); - (void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); - bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); (void)copyinstr(args.pa_config, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size); bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); diff --git a/sys/fs/umapfs/umap_vfsops.c b/sys/fs/umapfs/umap_vfsops.c index 6457897c46a7..768ad48334ec 100644 --- a/sys/fs/umapfs/umap_vfsops.c +++ b/sys/fs/umapfs/umap_vfsops.c @@ -221,8 +221,6 @@ umapfs_mount(mp, path, data, ndp, p) mp->mnt_data = (qaddr_t) amp; vfs_getnewfsid(mp); - (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); - bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size); bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); diff --git a/sys/fs/unionfs/union_vfsops.c b/sys/fs/unionfs/union_vfsops.c index dfa6eae70098..5018f094653f 100644 --- a/sys/fs/unionfs/union_vfsops.c +++ b/sys/fs/unionfs/union_vfsops.c @@ -253,9 +253,6 @@ union_mount(mp, path, data, ndp, p) mp->mnt_data = (qaddr_t) um; vfs_getnewfsid(mp); - (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); - bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); - switch (um->um_op) { case UNMNT_ABOVE: cp = ":"; diff --git a/sys/gnu/ext2fs/ext2_vfsops.c b/sys/gnu/ext2fs/ext2_vfsops.c index 5ef3819025a5..263db6dcf090 100644 --- a/sys/gnu/ext2fs/ext2_vfsops.c +++ b/sys/gnu/ext2fs/ext2_vfsops.c @@ -192,7 +192,11 @@ ext2_mount(mp, path, data, ndp, p) int error, flags; mode_t accessmode; - if ((error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) != 0) + /* Double-check the length of path.. */ + if (strlen(path) >= MAXMNTLEN - 1) + return (ENAMETOOLONG); + error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)); + if (error != 0) return (error); /* * If updating, check whether changing from read-only to @@ -308,10 +312,12 @@ ext2_mount(mp, path, data, ndp, p) } ump = VFSTOUFS(mp); fs = ump->um_e2fs; - (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); - bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); - bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, - MNAMELEN); + /* + * Note that this strncpy() is ok because of a check at the start + * of ext2_mount(). + */ + strncpy(fs->fs_fsmnt, path, MAXMNTLEN); + fs->fs_fsmnt[MAXMNTLEN - 1] = '\0'; (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size); bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); diff --git a/sys/gnu/fs/ext2fs/ext2_vfsops.c b/sys/gnu/fs/ext2fs/ext2_vfsops.c index 5ef3819025a5..263db6dcf090 100644 --- a/sys/gnu/fs/ext2fs/ext2_vfsops.c +++ b/sys/gnu/fs/ext2fs/ext2_vfsops.c @@ -192,7 +192,11 @@ ext2_mount(mp, path, data, ndp, p) int error, flags; mode_t accessmode; - if ((error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) != 0) + /* Double-check the length of path.. */ + if (strlen(path) >= MAXMNTLEN - 1) + return (ENAMETOOLONG); + error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)); + if (error != 0) return (error); /* * If updating, check whether changing from read-only to @@ -308,10 +312,12 @@ ext2_mount(mp, path, data, ndp, p) } ump = VFSTOUFS(mp); fs = ump->um_e2fs; - (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); - bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); - bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, - MNAMELEN); + /* + * Note that this strncpy() is ok because of a check at the start + * of ext2_mount(). + */ + strncpy(fs->fs_fsmnt, path, MAXMNTLEN); + fs->fs_fsmnt[MAXMNTLEN - 1] = '\0'; (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size); bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); diff --git a/sys/isofs/cd9660/cd9660_vfsops.c b/sys/isofs/cd9660/cd9660_vfsops.c index 3017339f2251..606f9d379413 100644 --- a/sys/isofs/cd9660/cd9660_vfsops.c +++ b/sys/isofs/cd9660/cd9660_vfsops.c @@ -249,8 +249,6 @@ cd9660_mount(mp, path, data, ndp, p) return error; } imp = VFSTOISOFS(mp); - (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); bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); diff --git a/sys/kern/vfs_conf.c b/sys/kern/vfs_conf.c index c1447ffeb4b5..34fba7846a1e 100644 --- a/sys/kern/vfs_conf.c +++ b/sys/kern/vfs_conf.c @@ -214,6 +214,14 @@ vfs_mountroot_try(char *mountfrom) (devsw(rootdev)->d_flags & D_MEMDISK)) mp->mnt_flag &= ~MNT_RDONLY; + /* + * Set the mount path to be something useful, because the + * filesystem code isn't responsible now for initialising + * f_mntonname unless they want to override the default + * (which is `path'.) + */ + strncpy(mp->mnt_stat.f_mntonname, "/", MNAMELEN); + error = VFS_MOUNT(mp, NULL, NULL, NULL, curproc); done: diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index 8f9565390155..0b1bcca96f76 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -107,14 +107,6 @@ struct mount_args { /* ARGSUSED */ int mount(p, uap) - struct proc *p; - struct mount_args *uap; -{ - return (mount1(p, uap, UIO_USERSPACE)); -} - -int -mount1(p, uap, segflag) struct proc *p; struct mount_args /* { syscallarg(char *) type; @@ -122,7 +114,47 @@ mount1(p, uap, segflag) syscallarg(int) flags; syscallarg(caddr_t) data; } */ *uap; - int segflag; +{ + char *fstype; + char *fspath; + int error; + + fstype = malloc(MFSNAMELEN, M_TEMP, M_WAITOK | M_ZERO); + fspath = malloc(MNAMELEN, M_TEMP, M_WAITOK | M_ZERO); + + /* + * vfs_mount() actually takes a kernel string for `type' and + * `path' now, so extract them. + */ + error = copyinstr(SCARG(uap, type), fstype, MFSNAMELEN, NULL); + if (error) + goto finish; + error = copyinstr(SCARG(uap, path), fspath, MNAMELEN, NULL); + if (error) + goto finish; + error = vfs_mount(p, fstype, fspath, SCARG(uap, flags), + SCARG(uap, data)); +finish: + free(fstype, M_TEMP); + free(fspath, M_TEMP); + return (error); +} + +/* + * vfs_mount(): actually attempt a filesystem mount. + * + * This routine is designed to be a "generic" entry point for routines + * that wish to mount a filesystem. All parameters except `fsdata' are + * pointers into kernel space. `fsdata' is currently still a pointer + * into userspace. + */ +int +vfs_mount(p, fstype, fspath, fsflags, fsdata) + struct proc *p; + char *fstype; + char *fspath; + int fsflags; + void *fsdata; { struct vnode *vp; struct mount *mp; @@ -130,14 +162,22 @@ mount1(p, uap, segflag) int error, flag = 0, flag2 = 0; struct vattr va; struct nameidata nd; - char fstypename[MFSNAMELEN]; + + /* + * Be ultra-paranoid about making sure the type and fspath + * variables will fit in our mp buffers, including the + * terminating NUL. + */ + if ((strlen(fstype) >= MNAMELEN - 1) || + (strlen(fspath) >= MFSNAMELEN - 1)) + return (ENAMETOOLONG); if (usermount == 0 && (error = suser(p))) return (error); /* * Do not allow NFS export by non-root users. */ - if (SCARG(uap, flags) & MNT_EXPORTED) { + if (fsflags & MNT_EXPORTED) { error = suser(p); if (error) return (error); @@ -146,16 +186,16 @@ mount1(p, uap, segflag) * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users */ if (suser_xxx(p->p_ucred, 0, 0)) - SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; + fsflags |= MNT_NOSUID | MNT_NODEV; /* * Get vnode to be covered */ - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, segflag, SCARG(uap, path), p); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspath, p); if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); vp = nd.ni_vp; - if (SCARG(uap, flags) & MNT_UPDATE) { + if (fsflags & MNT_UPDATE) { if ((vp->v_flag & VROOT) == 0) { vput(vp); return (EINVAL); @@ -167,7 +207,7 @@ mount1(p, uap, segflag) * We only allow the filesystem to be reloaded if it * is currently mounted read-only. */ - if ((SCARG(uap, flags) & MNT_RELOAD) && + if ((fsflags & MNT_RELOAD) && ((mp->mnt_flag & MNT_RDONLY) == 0)) { vput(vp); return (EOPNOTSUPP); /* Needs translation */ @@ -195,7 +235,7 @@ mount1(p, uap, segflag) } vp->v_flag |= VMOUNT; mtx_unlock(&vp->v_interlock); - mp->mnt_flag |= SCARG(uap, flags) & + mp->mnt_flag |= fsflags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_SNAPSHOT); VOP_UNLOCK(vp, 0, p); goto update; @@ -218,13 +258,8 @@ mount1(p, uap, segflag) vput(vp); return (ENOTDIR); } - if ((error = copyinstrfrom(SCARG(uap, type), - fstypename, MFSNAMELEN, NULL, segflag)) != 0) { - vput(vp); - return (error); - } for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) - if (!strcmp(vfsp->vfc_name, fstypename)) + if (!strcmp(vfsp->vfc_name, fstype)) break; if (vfsp == NULL) { linker_file_t lf; @@ -234,7 +269,7 @@ mount1(p, uap, segflag) vput(vp); return error; } - error = linker_load_file(fstypename, &lf); + error = linker_load_file(fstype, &lf); if (error || lf == NULL) { vput(vp); if (lf == NULL) @@ -244,7 +279,7 @@ mount1(p, uap, segflag) lf->userrefs++; /* lookup again, see if the VFS was loaded */ for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) - if (!strcmp(vfsp->vfc_name, fstypename)) + if (!strcmp(vfsp->vfc_name, fstype)) break; if (vfsp == NULL) { lf->userrefs--; @@ -274,16 +309,19 @@ mount1(p, uap, segflag) vfsp->vfc_refcount++; mp->mnt_stat.f_type = vfsp->vfc_typenum; mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; - strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); + strncpy(mp->mnt_stat.f_fstypename, fstype, MFSNAMELEN); + mp->mnt_stat.f_fstypename[MFSNAMELEN - 1] = '\0'; mp->mnt_vnodecovered = vp; mp->mnt_stat.f_owner = p->p_ucred->cr_uid; + strncpy(mp->mnt_stat.f_mntonname, fspath, MNAMELEN); + mp->mnt_stat.f_mntonname[MNAMELEN - 1] = '\0'; mp->mnt_iosize_max = DFLTPHYS; VOP_UNLOCK(vp, 0, p); update: /* * Set the mount level flags. */ - if (SCARG(uap, flags) & MNT_RDONLY) + if (fsflags & MNT_RDONLY) mp->mnt_flag |= MNT_RDONLY; else if (mp->mnt_flag & MNT_RDONLY) mp->mnt_kern_flag |= MNTK_WANTRDWR; @@ -291,7 +329,7 @@ update: MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOATIME | MNT_NOSYMFOLLOW | MNT_IGNORE | MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR); - mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC | + mp->mnt_flag |= fsflags & (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE | MNT_NOSYMFOLLOW | MNT_IGNORE | MNT_NOATIME | MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR); @@ -300,7 +338,7 @@ update: * XXX The final recipients of VFS_MOUNT just overwrite the ndp they * get. No freeing of cn_pnbuf. */ - error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p); + error = VFS_MOUNT(mp, fspath, fsdata, &nd, p); if (mp->mnt_flag & MNT_UPDATE) { if (mp->mnt_kern_flag & MNTK_WANTRDWR) mp->mnt_flag &= ~MNT_RDONLY; diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index c1447ffeb4b5..34fba7846a1e 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -214,6 +214,14 @@ vfs_mountroot_try(char *mountfrom) (devsw(rootdev)->d_flags & D_MEMDISK)) mp->mnt_flag &= ~MNT_RDONLY; + /* + * Set the mount path to be something useful, because the + * filesystem code isn't responsible now for initialising + * f_mntonname unless they want to override the default + * (which is `path'.) + */ + strncpy(mp->mnt_stat.f_mntonname, "/", MNAMELEN); + error = VFS_MOUNT(mp, NULL, NULL, NULL, curproc); done: diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 8f9565390155..0b1bcca96f76 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -107,14 +107,6 @@ struct mount_args { /* ARGSUSED */ int mount(p, uap) - struct proc *p; - struct mount_args *uap; -{ - return (mount1(p, uap, UIO_USERSPACE)); -} - -int -mount1(p, uap, segflag) struct proc *p; struct mount_args /* { syscallarg(char *) type; @@ -122,7 +114,47 @@ mount1(p, uap, segflag) syscallarg(int) flags; syscallarg(caddr_t) data; } */ *uap; - int segflag; +{ + char *fstype; + char *fspath; + int error; + + fstype = malloc(MFSNAMELEN, M_TEMP, M_WAITOK | M_ZERO); + fspath = malloc(MNAMELEN, M_TEMP, M_WAITOK | M_ZERO); + + /* + * vfs_mount() actually takes a kernel string for `type' and + * `path' now, so extract them. + */ + error = copyinstr(SCARG(uap, type), fstype, MFSNAMELEN, NULL); + if (error) + goto finish; + error = copyinstr(SCARG(uap, path), fspath, MNAMELEN, NULL); + if (error) + goto finish; + error = vfs_mount(p, fstype, fspath, SCARG(uap, flags), + SCARG(uap, data)); +finish: + free(fstype, M_TEMP); + free(fspath, M_TEMP); + return (error); +} + +/* + * vfs_mount(): actually attempt a filesystem mount. + * + * This routine is designed to be a "generic" entry point for routines + * that wish to mount a filesystem. All parameters except `fsdata' are + * pointers into kernel space. `fsdata' is currently still a pointer + * into userspace. + */ +int +vfs_mount(p, fstype, fspath, fsflags, fsdata) + struct proc *p; + char *fstype; + char *fspath; + int fsflags; + void *fsdata; { struct vnode *vp; struct mount *mp; @@ -130,14 +162,22 @@ mount1(p, uap, segflag) int error, flag = 0, flag2 = 0; struct vattr va; struct nameidata nd; - char fstypename[MFSNAMELEN]; + + /* + * Be ultra-paranoid about making sure the type and fspath + * variables will fit in our mp buffers, including the + * terminating NUL. + */ + if ((strlen(fstype) >= MNAMELEN - 1) || + (strlen(fspath) >= MFSNAMELEN - 1)) + return (ENAMETOOLONG); if (usermount == 0 && (error = suser(p))) return (error); /* * Do not allow NFS export by non-root users. */ - if (SCARG(uap, flags) & MNT_EXPORTED) { + if (fsflags & MNT_EXPORTED) { error = suser(p); if (error) return (error); @@ -146,16 +186,16 @@ mount1(p, uap, segflag) * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users */ if (suser_xxx(p->p_ucred, 0, 0)) - SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; + fsflags |= MNT_NOSUID | MNT_NODEV; /* * Get vnode to be covered */ - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, segflag, SCARG(uap, path), p); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspath, p); if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); vp = nd.ni_vp; - if (SCARG(uap, flags) & MNT_UPDATE) { + if (fsflags & MNT_UPDATE) { if ((vp->v_flag & VROOT) == 0) { vput(vp); return (EINVAL); @@ -167,7 +207,7 @@ mount1(p, uap, segflag) * We only allow the filesystem to be reloaded if it * is currently mounted read-only. */ - if ((SCARG(uap, flags) & MNT_RELOAD) && + if ((fsflags & MNT_RELOAD) && ((mp->mnt_flag & MNT_RDONLY) == 0)) { vput(vp); return (EOPNOTSUPP); /* Needs translation */ @@ -195,7 +235,7 @@ mount1(p, uap, segflag) } vp->v_flag |= VMOUNT; mtx_unlock(&vp->v_interlock); - mp->mnt_flag |= SCARG(uap, flags) & + mp->mnt_flag |= fsflags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_SNAPSHOT); VOP_UNLOCK(vp, 0, p); goto update; @@ -218,13 +258,8 @@ mount1(p, uap, segflag) vput(vp); return (ENOTDIR); } - if ((error = copyinstrfrom(SCARG(uap, type), - fstypename, MFSNAMELEN, NULL, segflag)) != 0) { - vput(vp); - return (error); - } for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) - if (!strcmp(vfsp->vfc_name, fstypename)) + if (!strcmp(vfsp->vfc_name, fstype)) break; if (vfsp == NULL) { linker_file_t lf; @@ -234,7 +269,7 @@ mount1(p, uap, segflag) vput(vp); return error; } - error = linker_load_file(fstypename, &lf); + error = linker_load_file(fstype, &lf); if (error || lf == NULL) { vput(vp); if (lf == NULL) @@ -244,7 +279,7 @@ mount1(p, uap, segflag) lf->userrefs++; /* lookup again, see if the VFS was loaded */ for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) - if (!strcmp(vfsp->vfc_name, fstypename)) + if (!strcmp(vfsp->vfc_name, fstype)) break; if (vfsp == NULL) { lf->userrefs--; @@ -274,16 +309,19 @@ mount1(p, uap, segflag) vfsp->vfc_refcount++; mp->mnt_stat.f_type = vfsp->vfc_typenum; mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; - strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); + strncpy(mp->mnt_stat.f_fstypename, fstype, MFSNAMELEN); + mp->mnt_stat.f_fstypename[MFSNAMELEN - 1] = '\0'; mp->mnt_vnodecovered = vp; mp->mnt_stat.f_owner = p->p_ucred->cr_uid; + strncpy(mp->mnt_stat.f_mntonname, fspath, MNAMELEN); + mp->mnt_stat.f_mntonname[MNAMELEN - 1] = '\0'; mp->mnt_iosize_max = DFLTPHYS; VOP_UNLOCK(vp, 0, p); update: /* * Set the mount level flags. */ - if (SCARG(uap, flags) & MNT_RDONLY) + if (fsflags & MNT_RDONLY) mp->mnt_flag |= MNT_RDONLY; else if (mp->mnt_flag & MNT_RDONLY) mp->mnt_kern_flag |= MNTK_WANTRDWR; @@ -291,7 +329,7 @@ update: MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOATIME | MNT_NOSYMFOLLOW | MNT_IGNORE | MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR); - mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC | + mp->mnt_flag |= fsflags & (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE | MNT_NOSYMFOLLOW | MNT_IGNORE | MNT_NOATIME | MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR); @@ -300,7 +338,7 @@ update: * XXX The final recipients of VFS_MOUNT just overwrite the ndp they * get. No freeing of cn_pnbuf. */ - error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p); + error = VFS_MOUNT(mp, fspath, fsdata, &nd, p); if (mp->mnt_flag & MNT_UPDATE) { if (mp->mnt_kern_flag & MNTK_WANTRDWR) mp->mnt_flag &= ~MNT_RDONLY; diff --git a/sys/miscfs/fdesc/fdesc_vfsops.c b/sys/miscfs/fdesc/fdesc_vfsops.c index 84940c70a745..7737e37dd5c7 100644 --- a/sys/miscfs/fdesc/fdesc_vfsops.c +++ b/sys/miscfs/fdesc/fdesc_vfsops.c @@ -74,7 +74,6 @@ fdesc_mount(mp, path, data, ndp, p) struct proc *p; { int error = 0; - u_int size; struct fdescmount *fmp; struct vnode *rvp; @@ -98,8 +97,6 @@ fdesc_mount(mp, path, data, ndp, p) mp->mnt_data = (qaddr_t) fmp; vfs_getnewfsid(mp); - (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); - bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); bcopy("fdesc", mp->mnt_stat.f_mntfromname, sizeof("fdesc")); (void)fdesc_statfs(mp, &mp->mnt_stat, p); diff --git a/sys/miscfs/nullfs/null_vfsops.c b/sys/miscfs/nullfs/null_vfsops.c index 333916237b4b..b852cc45ff1e 100644 --- a/sys/miscfs/nullfs/null_vfsops.c +++ b/sys/miscfs/nullfs/null_vfsops.c @@ -191,8 +191,6 @@ nullfs_mount(mp, path, data, ndp, p) mp->mnt_data = (qaddr_t) xmp; vfs_getnewfsid(mp); - (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); - bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size); bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); diff --git a/sys/miscfs/portal/portal_vfsops.c b/sys/miscfs/portal/portal_vfsops.c index 139746d3d35b..3f7903ca2577 100644 --- a/sys/miscfs/portal/portal_vfsops.c +++ b/sys/miscfs/portal/portal_vfsops.c @@ -133,8 +133,6 @@ portal_mount(mp, path, data, ndp, p) mp->mnt_data = (qaddr_t) fmp; vfs_getnewfsid(mp); - (void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); - bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); (void)copyinstr(args.pa_config, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size); bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); diff --git a/sys/miscfs/umapfs/umap_vfsops.c b/sys/miscfs/umapfs/umap_vfsops.c index 6457897c46a7..768ad48334ec 100644 --- a/sys/miscfs/umapfs/umap_vfsops.c +++ b/sys/miscfs/umapfs/umap_vfsops.c @@ -221,8 +221,6 @@ umapfs_mount(mp, path, data, ndp, p) mp->mnt_data = (qaddr_t) amp; vfs_getnewfsid(mp); - (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); - bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size); bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); diff --git a/sys/miscfs/union/union_vfsops.c b/sys/miscfs/union/union_vfsops.c index dfa6eae70098..5018f094653f 100644 --- a/sys/miscfs/union/union_vfsops.c +++ b/sys/miscfs/union/union_vfsops.c @@ -253,9 +253,6 @@ union_mount(mp, path, data, ndp, p) mp->mnt_data = (qaddr_t) um; vfs_getnewfsid(mp); - (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); - bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); - switch (um->um_op) { case UNMNT_ABOVE: cp = ":"; diff --git a/sys/msdosfs/msdosfs_vfsops.c b/sys/msdosfs/msdosfs_vfsops.c index 3088d7a2bd6a..672ea5df2e2f 100644 --- a/sys/msdosfs/msdosfs_vfsops.c +++ b/sys/msdosfs/msdosfs_vfsops.c @@ -345,9 +345,6 @@ msdosfs_mount(mp, path, data, ndp, p) msdosfs_unmount(mp, MNT_FORCE, p); return error; } - - (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); bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); diff --git a/sys/nfs/nfs_vfsops.c b/sys/nfs/nfs_vfsops.c index e839d8ba603a..b22a8554e954 100644 --- a/sys/nfs/nfs_vfsops.c +++ b/sys/nfs/nfs_vfsops.c @@ -764,7 +764,7 @@ nfs_mount(mp, path, data, ndp, p) struct nfs_args args; struct sockaddr *nam; struct vnode *vp; - char pth[MNAMELEN], hst[MNAMELEN]; + char hst[MNAMELEN]; size_t len; u_char nfh[NFSX_V3FHMAX]; @@ -810,10 +810,6 @@ nfs_mount(mp, path, data, ndp, p) error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize); if (error) return (error); - error = copyinstr(path, pth, MNAMELEN-1, &len); - if (error) - return (error); - bzero(&pth[len], MNAMELEN - len); error = copyinstr(args.hostname, hst, MNAMELEN-1, &len); if (error) return (error); @@ -823,7 +819,7 @@ nfs_mount(mp, path, data, ndp, p) if (error) return (error); args.fh = nfh; - error = mountnfs(&args, mp, nam, pth, hst, &vp); + error = mountnfs(&args, mp, nam, path, hst, &vp); return (error); } diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c index e839d8ba603a..b22a8554e954 100644 --- a/sys/nfsclient/nfs_vfsops.c +++ b/sys/nfsclient/nfs_vfsops.c @@ -764,7 +764,7 @@ nfs_mount(mp, path, data, ndp, p) struct nfs_args args; struct sockaddr *nam; struct vnode *vp; - char pth[MNAMELEN], hst[MNAMELEN]; + char hst[MNAMELEN]; size_t len; u_char nfh[NFSX_V3FHMAX]; @@ -810,10 +810,6 @@ nfs_mount(mp, path, data, ndp, p) error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize); if (error) return (error); - error = copyinstr(path, pth, MNAMELEN-1, &len); - if (error) - return (error); - bzero(&pth[len], MNAMELEN - len); error = copyinstr(args.hostname, hst, MNAMELEN-1, &len); if (error) return (error); @@ -823,7 +819,7 @@ nfs_mount(mp, path, data, ndp, p) if (error) return (error); args.fh = nfh; - error = mountnfs(&args, mp, nam, pth, hst, &vp); + error = mountnfs(&args, mp, nam, path, hst, &vp); return (error); } diff --git a/sys/ntfs/ntfs_vfsops.c b/sys/ntfs/ntfs_vfsops.c index 384883e81159..89a7dd7bc0f4 100644 --- a/sys/ntfs/ntfs_vfsops.c +++ b/sys/ntfs/ntfs_vfsops.c @@ -376,16 +376,12 @@ ntfs_mount ( /* * Since this is a new mount, we want the names for * the device and the mount point copied in. If an - * error occurs, the mountpoint is discarded by the - * upper level code. + * error occurs, the mountpoint is discarded by the + * upper level code. Note that vfs_mount() handles + * copying the mountpoint f_mntonname for us, so we + * don't have to do it here unless we want to set it + * to something other than "path" for some rason. */ - /* Save "last mounted on" info for mount point (NULL pad)*/ - copyinstr( path, /* mount point*/ - mp->mnt_stat.f_mntonname, /* save area*/ - MNAMELEN - 1, /* max size*/ - &size); /* real size*/ - bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size); - /* Save "mounted from" info for mount point (NULL pad)*/ copyinstr( args.fspec, /* device name*/ mp->mnt_stat.f_mntfromname, /* save area*/ diff --git a/sys/nwfs/nwfs_vfsops.c b/sys/nwfs/nwfs_vfsops.c index 3e76b30ac1a9..7d17e7d0247d 100644 --- a/sys/nwfs/nwfs_vfsops.c +++ b/sys/nwfs/nwfs_vfsops.c @@ -146,7 +146,6 @@ static int nwfs_mount(struct mount *mp, char *path, caddr_t data, struct nameidata *ndp, struct proc *p) { struct nwfs_args args; /* will hold data from mount request */ - size_t size; int error; struct nwmount *nmp = NULL; struct ncp_conn *conn = NULL; @@ -198,8 +197,6 @@ static int nwfs_mount(struct mount *mp, char *path, caddr_t data, nmp->m.dir_mode = (nmp->m.dir_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR; if ((error = nwfs_initnls(nmp)) != 0) goto bad; - (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); - bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); pc = mp->mnt_stat.f_mntfromname; pe = pc+sizeof(mp->mnt_stat.f_mntfromname); bzero(pc, MNAMELEN); diff --git a/sys/sys/mount.h b/sys/sys/mount.h index 345f5a0e8623..70d84f3d07e5 100644 --- a/sys/sys/mount.h +++ b/sys/sys/mount.h @@ -404,7 +404,8 @@ extern char *mountrootfsname; * exported vnode operations */ int dounmount __P((struct mount *, int, struct proc *)); -int mount1 __P((struct proc *p, struct mount_args *uap, int segflag)); +int vfs_mount __P((struct proc *p, char *type, char *path, int flags, + void *data)); int vfs_setpublicfs /* set publicly exported fs */ __P((struct mount *, struct netexport *, struct export_args *)); int vfs_lock __P((struct mount *)); /* lock a vfs */ diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index 2d48115e636b..4558780a54a2 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -323,9 +323,8 @@ ffs_mount(mp, path, data, ndp, p) * We need the name for the mount point (also used for * "last mounted on") copied in. If an error occurs, * the mount point is discarded by the upper level code. + * Note that vfs_mount() populates f_mntonname for us. */ - copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); - bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size); if ((error = ffs_mountfs(devvp, mp, p, M_FFSNODE)) != 0) { vrele(devvp); return (error);