--- vfs_mount.c.orig Tue Feb 3 10:30:56 2004 +++ vfs_mount.c Tue Feb 3 12:35:48 2004 @@ -111,8 +111,9 @@ static int vfs_mountroot_ask(void); static int vfs_mountroot_try(char *mountfrom); static int vfs_nmount(struct thread *td, int fsflags, struct uio *fsopts); -static int usermount = 0; /* if 1, non-root can mount fs. */ -SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, ""); +static int usermount = 0; +SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, + "Permit unprivileged users mount/unmount file systems"); MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount structure"); @@ -208,6 +209,25 @@ vfs_freeopts(struct vfsoptlist *opts) } /* + * Check if options are equal (with or without the "no" prefix). + */ +static int +vfs_equalopts(const char *opt1, const char *opt2) +{ + + /* "opt" vs. "opt" or "noopt" vs. "noopt" */ + if (strcmp(opt1, opt2) == 0) + return (1); + /* "noopt" vs. "opt" */ + if (strncmp(opt1, "no", 2) == 0 && strcmp(opt1 + 2, opt2) == 0) + return (1); + /* "opt" vs. "noopt" */ + if (strncmp(opt2, "no", 2) == 0 && strcmp(opt1, opt2 + 2) == 0) + return (1); + return (0); +} + +/* * If a mount option is specified several times, * (with or without the "no" prefix) only keep * the last occurence of it. @@ -216,19 +236,11 @@ static void vfs_sanitizeopts(struct vfsoptlist *opts) { struct vfsopt *opt, *opt2, *tmp; - int noopt; TAILQ_FOREACH_REVERSE(opt, opts, vfsoptlist, link) { - if (strncmp(opt->name, "no", 2) == 0) - noopt = 1; - else - noopt = 0; opt2 = TAILQ_PREV(opt, vfsoptlist, link); while (opt2 != NULL) { - if (strcmp(opt2->name, opt->name) == 0 || - (noopt && strcmp(opt->name + 2, opt2->name) == 0) || - (!noopt && strncmp(opt2->name, "no", 2) == 0 && - strcmp(opt2->name + 2, opt->name) == 0)) { + if (vfs_equalopts(opt->name, opt2->name)) { tmp = TAILQ_PREV(opt2, vfsoptlist, link); vfs_freeopt(opts, opt2); opt2 = tmp; @@ -286,7 +298,7 @@ vfs_buildopts(struct uio *auio, struct v } else { error = copyin(auio->uio_iov[i].iov_base, opt->name, namelen); - if (error) + if (error != 0) goto bad; } /* Ensure names are null-terminated strings. */ @@ -302,7 +314,7 @@ vfs_buildopts(struct uio *auio, struct v } else { error = copyin(auio->uio_iov[i + 1].iov_base, opt->value, optlen); - if (error) + if (error != 0) goto bad; } } @@ -395,7 +407,8 @@ nmount(td, uap) auio.uio_iov = iov; auio.uio_iovcnt = iovcnt; auio.uio_segflg = UIO_USERSPACE; - if ((error = copyin(uap->iovp, iov, iovlen))) + error = copyin(uap->iovp, iov, iovlen); + if (error != 0) goto finish; for (i = 0; i < iovcnt; i++) { @@ -548,7 +561,7 @@ vfs_nmount(struct thread *td, int fsflag int error, fstypelen, fspathlen; error = vfs_buildopts(fsoptions, &optlist); - if (error) + if (error != 0) return (error); /* @@ -558,13 +571,13 @@ vfs_nmount(struct thread *td, int fsflag */ fstypelen = 0; error = vfs_getopt(optlist, "fstype", (void **)&fstype, &fstypelen); - if (error || fstype[fstypelen - 1] != '\0') { + if (error != 0 || fstype[fstypelen - 1] != '\0') { error = EINVAL; goto bail; } fspathlen = 0; error = vfs_getopt(optlist, "fspath", (void **)&fspath, &fspathlen); - if (error || fspath[fspathlen - 1] != '\0') { + if (error != 0 || fspath[fspathlen - 1] != '\0') { error = EINVAL; goto bail; } @@ -581,7 +594,7 @@ vfs_nmount(struct thread *td, int fsflag error = vfs_domount(td, fstype, fspath, fsflags, optlist, 0); bail: - if (error) + if (error != 0) vfs_freeopts(optlist); return (error); } @@ -679,34 +692,34 @@ vfs_domount( if (strlen(fstype) >= MFSNAMELEN || strlen(fspath) >= MNAMELEN) return (ENAMETOOLONG); - /* mount(2) is not permitted inside the jail. */ if (jailed(td->td_ucred)) return (EPERM); - if (usermount == 0) { error = suser(td); - if (error) + if (error != 0) return (error); } + /* * Do not allow NFS export by non-root users. */ if (fsflags & MNT_EXPORTED) { error = suser(td); - if (error) + if (error != 0) return (error); } /* - * Silently enforce MNT_NOSUID, MNT_NODEV and MNT_USER - * for unprivileged users. + * Silently enforce MNT_NOSUID, MNT_NODEV and MNT_USER for + * unprivileged users. */ - if (suser(td)) + if (suser(td) != 0) fsflags |= MNT_NOSUID | MNT_NODEV | MNT_USER; /* * Get vnode to be covered */ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspath, td); - if ((error = namei(&nd)) != 0) + error = namei(&nd); + if (error != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); vp = nd.ni_vp; @@ -728,18 +741,13 @@ vfs_domount( return (EOPNOTSUPP); /* Needs translation */ } /* - * Only root, or the user that did the original mount is - * permitted to update it. + * Only privileged root, or (if MNT_USER is set) the user that + * did the original mount is permitted to update it. */ - if ((mp->mnt_flag & MNT_USER) != 0) { - if (mp->mnt_cred->cr_uid != td->td_ucred->cr_uid) { - if ((error = suser(td)) != 0) { - vput(vp); - return (error); - } - } - } else { - if ((error = suser(td)) != 0) { + if ((mp->mnt_flag & MNT_USER) == 0 || + mp->mnt_cred->cr_uid != td->td_ucred->cr_uid) { + error = suser(td); + if (error != 0) { vput(vp); return (error); } @@ -772,18 +780,19 @@ vfs_domount( * onto which we are attempting to mount. */ error = VOP_GETATTR(vp, &va, td->td_ucred, td); - if (error) { + if (error != 0) { vput(vp); return (error); } if (va.va_uid != td->td_ucred->cr_uid) { error = suser(td); - if (error) { + if (error != 0) { vput(vp); return (error); } } - if ((error = vinvalbuf(vp, V_SAVE, td->td_ucred, td, 0, 0)) != 0) { + error = vinvalbuf(vp, V_SAVE, td->td_ucred, td, 0, 0); + if (error != 0) { vput(vp); return (error); } @@ -792,17 +801,17 @@ vfs_domount( return (ENOTDIR); } for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) - if (!strcmp(vfsp->vfc_name, fstype)) + if (strcmp(vfsp->vfc_name, fstype) == 0) break; if (vfsp == NULL) { /* Only load modules for root (very important!). */ error = suser(td); - if (error) { + if (error != 0) { vput(vp); return (error); } error = securelevel_gt(td->td_ucred, 0); - if (error) { + if (error != 0) { vput(vp); return (error); } @@ -816,7 +825,7 @@ vfs_domount( lf->userrefs++; /* Look up again to see if the VFS was loaded. */ for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) - if (!strcmp(vfsp->vfc_name, fstype)) + if (strcmp(vfsp->vfc_name, fstype) == 0) break; if (vfsp == NULL) { lf->userrefs--; @@ -839,7 +848,7 @@ vfs_domount( * Allocate and initialize the filesystem. */ error = vfs_mount_alloc(vp, vfsp, fspath, td, &mp); - if (error) { + if (error != 0) { vput(vp); return (error); } @@ -855,7 +864,7 @@ update: */ if ((compat == 0) == (mp->mnt_op->vfs_mount != NULL)) { printf("%s doesn't support the %s mount syscall\n", - mp->mnt_vfc->vfc_name, compat? "old" : "new"); + mp->mnt_vfc->vfc_name, compat ? "old" : "new"); VI_LOCK(vp); vp->v_iflag &= ~VI_MOUNT; VI_UNLOCK(vp); @@ -881,9 +890,9 @@ update: * XXX The final recipients of VFS_MOUNT just overwrite the ndp they * get. No freeing of cn_pnbuf. */ - error = compat? VFS_MOUNT(mp, fspath, fsdata, &nd, td) : + error = compat ? VFS_MOUNT(mp, fspath, fsdata, &nd, td) : VFS_NMOUNT(mp, &nd, td); - if (!error) { + if (error == 0) { if (mp->mnt_opt != NULL) vfs_freeopts(mp->mnt_opt); mp->mnt_opt = mp->mnt_optnew; @@ -896,10 +905,10 @@ update: if (mp->mnt_flag & MNT_UPDATE) { if (mp->mnt_kern_flag & MNTK_WANTRDWR) mp->mnt_flag &= ~MNT_RDONLY; - mp->mnt_flag &=~ - (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_SNAPSHOT); - mp->mnt_kern_flag &=~ MNTK_WANTRDWR; - if (error) { + mp->mnt_flag &= + ~(MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_SNAPSHOT); + mp->mnt_kern_flag &= ~MNTK_WANTRDWR; + if (error != 0) { mp->mnt_flag = flag; mp->mnt_kern_flag = kern_flag; } @@ -923,7 +932,7 @@ update: * Put the new filesystem on the mount list after root. */ cache_purge(vp); - if (!error) { + if (error == 0) { struct vnode *newdp; VI_LOCK(vp); @@ -941,7 +950,8 @@ update: if ((mp->mnt_flag & MNT_RDONLY) == 0) error = vfs_allocate_syncvnode(mp); vfs_unbusy(mp, td); - if ((error = VFS_START(mp, 0, td)) != 0) + error = VFS_START(mp, 0, td); + if (error != 0) vrele(vp); } else { VI_LOCK(vp); @@ -1026,18 +1036,16 @@ unmount(td, uap) char *pathbuf; int error, id0, id1; - /* unmount(2) is not permitted inside the jail. */ if (jailed(td->td_ucred)) return (EPERM); - if (usermount == 0) { - if ((error = suser(td)) != 0) + error = suser(td); + if (error != 0) return (error); } - pathbuf = malloc(MNAMELEN, M_TEMP, M_WAITOK); error = copyinstr(uap->path, pathbuf, MNAMELEN, NULL); - if (error) { + if (error != 0) { free(pathbuf, M_TEMP); return (error); } @@ -1049,16 +1057,18 @@ unmount(td, uap) } mtx_lock(&mountlist_mtx); - TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) + TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) { if (mp->mnt_stat.f_fsid.val[0] == id0 && mp->mnt_stat.f_fsid.val[1] == id1) break; + } mtx_unlock(&mountlist_mtx); } else { mtx_lock(&mountlist_mtx); - TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) + TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) { if (strcmp(mp->mnt_stat.f_mntonname, pathbuf) == 0) break; + } mtx_unlock(&mountlist_mtx); } free(pathbuf, M_TEMP); @@ -1073,16 +1083,13 @@ unmount(td, uap) } /* - * Only root, or the user that did the original mount is - * permitted to unmount this filesystem. + * Only privileged root, or (if MNT_USER is set) the user that did the + * original mount is permitted to unmount this filesystem. */ - if ((mp->mnt_flag & MNT_USER) != 0) { - if (mp->mnt_cred->cr_uid != td->td_ucred->cr_uid) { - if ((error = suser(td)) != 0) - return (error); - } - } else { - if ((error = suser(td)) != 0) + if ((mp->mnt_flag & MNT_USER) == 0 || + mp->mnt_cred->cr_uid != td->td_ucred->cr_uid) { + error = suser(td); + if (error != 0) return (error); } @@ -1118,7 +1125,7 @@ dounmount(mp, flags, td) mp->mnt_kern_flag |= MNTK_UNMOUNTF; error = lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK | ((flags & MNT_FORCE) ? 0 : LK_NOWAIT), &mountlist_mtx, td); - if (error) { + if (error != 0) { mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF); if (mp->mnt_kern_flag & MNTK_MWAIT) wakeup(mp); @@ -1131,7 +1138,7 @@ dounmount(mp, flags, td) vfs_msync(mp, MNT_WAIT); async_flag = mp->mnt_flag & MNT_ASYNC; - mp->mnt_flag &=~ MNT_ASYNC; + mp->mnt_flag &= ~MNT_ASYNC; cache_purgevfs(mp); /* remove cache entries for this file sys */ if (mp->mnt_syncer != NULL) vrele(mp->mnt_syncer); @@ -1155,7 +1162,7 @@ dounmount(mp, flags, td) error = VFS_UNMOUNT(mp, flags, td); } vn_finished_write(mp); - if (error) { + if (error != 0) { /* Undo cdir/rdir and rootvnode changes made above. */ if ((flags & MNT_FORCE) && VFS_ROOT(mp, &fsrootvp) == 0) { if (mp->mnt_vnodecovered != NULL) @@ -1167,7 +1174,7 @@ dounmount(mp, flags, td) vput(fsrootvp); } if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL) - (void) vfs_allocate_syncvnode(mp); + vfs_allocate_syncvnode(mp); mtx_lock(&mountlist_mtx); mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF); mp->mnt_flag |= async_flag; @@ -1179,7 +1186,8 @@ dounmount(mp, flags, td) } mtx_lock(&mountlist_mtx); TAILQ_REMOVE(&mountlist, mp, mnt_list); - if ((coveredvp = mp->mnt_vnodecovered) != NULL) + coveredvp = mp->mnt_vnodecovered; + if (coveredvp != NULL) coveredvp->v_mountedhere = NULL; mtx_unlock(&mountlist_mtx); vfs_mount_destroy(mp, td); @@ -1207,13 +1215,14 @@ vfs_rootmountalloc(fstypename, devname, if (fstypename == NULL) return (ENODEV); - for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) - if (!strcmp(vfsp->vfc_name, fstypename)) + for (vfsp = vfsconf; vfsp != NULL; vfsp = vfsp->vfc_next) { + if (strcmp(vfsp->vfc_name, fstypename) == 0) break; + } if (vfsp == NULL) return (ENODEV); error = vfs_mount_alloc(NULLVP, vfsp, "/", td, &mp); - if (error) + if (error != 0) return (error); mp->mnt_flag |= MNT_RDONLY | MNT_ROOTFS; strlcpy(mp->mnt_stat.f_mntfromname, devname, MNAMELEN); @@ -1266,10 +1275,11 @@ vfs_mountroot(void) * supplied via some other means. This is the preferred * mechanism. */ - if ((cp = getenv("vfs.root.mountfrom")) != NULL) { + cp = getenv("vfs.root.mountfrom"); + if (cp != NULL) { error = vfs_mountroot_try(cp); freeenv(cp); - if (!error) + if (error == 0) return; } @@ -1287,9 +1297,10 @@ vfs_mountroot(void) * it now. */ #ifdef ROOTDEVNAME - if (!(boothowto & RB_DFLTROOT)) + if (!(boothowto & RB_DFLTROOT)) { if (!vfs_mountroot_try(ROOTDEVNAME)) return; + } #endif /* @@ -1335,8 +1346,8 @@ vfs_mountroot_try(char *mountfrom) goto done; /* allocate a root mount */ - error = vfs_rootmountalloc(vfsname, path[0] != 0 ? path : ROOTNAME, - &mp); + error = vfs_rootmountalloc(vfsname, + path[0] != '\0' ? path : ROOTNAME, &mp); if (error != 0) { printf("Can't allocate root mount for filesystem '%s': %d\n", vfsname, error); @@ -1344,7 +1355,7 @@ vfs_mountroot_try(char *mountfrom) } /* do our best to set rootdev */ - if ((path[0] != 0) && setrootbyname(path)) + if (path[0] != '\0' && setrootbyname(path)) printf("setrootbyname failed\n"); /* If the root device is a type "memory disk", mount RW */ @@ -1377,7 +1388,7 @@ done: vfs_unbusy(mp, curthread); error = VFS_START(mp, 0, curthread); } - return(error); + return (error); } /* @@ -1400,7 +1411,7 @@ vfs_mountroot_ask(void) printf(" Abort manual input\n"); printf("\nmountroot> "); gets(name); - if (name[0] == 0) + if (name[0] == '\0') return(1); if (name[0] == '?') { printf("\nList of GEOM managed disk devices:\n ");