Index: sys/kern/kern_jail.c =================================================================== --- sys/kern/kern_jail.c (revision 224527) +++ sys/kern/kern_jail.c (working copy) @@ -3858,7 +3858,8 @@ case PRIV_VFS_UNMOUNT: case PRIV_VFS_MOUNT_NONUSER: case PRIV_VFS_MOUNT_OWNER: - if (cred->cr_prison->pr_allow & PR_ALLOW_MOUNT) + if (cred->cr_prison->pr_allow & PR_ALLOW_MOUNT && + cred->cr_prison->pr_enforce_statfs < 2) return (0); else return (EPERM); Index: sys/kern/vfs_mount.c =================================================================== --- sys/kern/vfs_mount.c (revision 224527) +++ sys/kern/vfs_mount.c (working copy) @@ -745,7 +745,6 @@ vfs_domount_first( struct thread *td, /* Calling thread. */ struct vfsconf *vfsp, /* File system type. */ - char *fspath, /* Mount path. */ struct vnode *vp, /* Vnode to be covered. */ int fsflags, /* Flags common to all filesystems. */ struct vfsoptlist **optlist /* Options local to the filesystem. */ @@ -755,11 +754,24 @@ struct mount *mp; struct vnode *newdp; int error; + char *fspath, *fbuf; mtx_assert(&Giant, MA_OWNED); ASSERT_VOP_ELOCKED(vp, __func__); KASSERT((fsflags & MNT_UPDATE) == 0, ("MNT_UPDATE shouldn't be here")); + /* Construct global filesystem path from vp */ + error = vn_fullpath_global(td, vp, &fspath, &fbuf); + if (error != 0) { + vput(vp); + return(error); + } + if (strlen(fspath) >= MNAMELEN) { + vput(vp); + free(fbuf, M_TEMP); + return (ENAMETOOLONG); + } + /* * If the user is not root, ensure that they own the directory * onto which we are attempting to mount. @@ -781,12 +793,14 @@ } if (error != 0) { vput(vp); + free(fbuf, M_TEMP); return (error); } VOP_UNLOCK(vp, 0); /* Allocate and initialize the filesystem. */ mp = vfs_mount_alloc(vp, vfsp, fspath, td->td_ucred); + free(fbuf, M_TEMP); /* XXXMAC: pass to vfs_mount_alloc? */ mp->mnt_optnew = *optlist; /* Set the mount level flags. */ @@ -1070,11 +1084,9 @@ NDFREE(&nd, NDF_ONLY_PNBUF); vp = nd.ni_vp; if ((fsflags & MNT_UPDATE) == 0) { - error = vfs_domount_first(td, vfsp, fspath, vp, fsflags, - optlist); - } else { + error = vfs_domount_first(td, vfsp, vp, fsflags, optlist); + } else error = vfs_domount_update(td, vp, fsflags, optlist); - } mtx_unlock(&Giant); ASSERT_VI_UNLOCKED(vp, __func__); @@ -1105,7 +1117,7 @@ } */ *uap; { struct mount *mp; - char *pathbuf; + char *pathbuf, *rpathbuf; int error, id0, id1; AUDIT_ARG_VALUE(uap->flags); @@ -1140,12 +1152,27 @@ mtx_unlock(&mountlist_mtx); } else { AUDIT_ARG_UPATH1(td, pathbuf); + /* + * If we are jailed and enforce_statfs == 1 + * construct real filesystem path + */ + rpathbuf = malloc(MNAMELEN, M_TEMP, M_WAITOK); + if (jailed(td->td_ucred) && + td->td_ucred->cr_prison->pr_enforce_statfs == 1 && + strcmp(td->td_ucred->cr_prison->pr_path, "/") != 0) { + strlcpy(rpathbuf, td->td_ucred->cr_prison->pr_path, + MNAMELEN); + strlcat(rpathbuf, pathbuf, MNAMELEN); + } else { + strlcpy(rpathbuf, pathbuf, MNAMELEN); + } mtx_lock(&mountlist_mtx); TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) { - if (strcmp(mp->mnt_stat.f_mntonname, pathbuf) == 0) + if (strcmp(mp->mnt_stat.f_mntonname, rpathbuf) == 0) break; } mtx_unlock(&mountlist_mtx); + free(rpathbuf, M_TEMP); } free(pathbuf, M_TEMP); if (mp == NULL) {