After implementing a suggestion from pjd@, a new version of the patch is attached, now using a more universal solution - vn_fullpath_global() in the mount part.
Dňa 28. 7. 2011 16:59, Martin Matuska wrote / napísal(a): > Please review my attached patch. > > The patch fixes f_mntonname with mount/unmount inside a jail with allow.mount > enabled. > Filesystems mountable in a jail require the VFCF_JAIL flag (currently only > ZFS). > > With this patch, mount and unmount works both with enforce_statfs = 0 and > enforce_statfs = 1. > I suggest disabling mount/unmount for jails with enforce_statfs = 2, as this > is contradictory and does not play well with or without this patch. > > I have successfully tested this patch with ZFS, nullfs and tmpfs. > > To enable nullfs for a jail, you have to modify tmpfs/tmpfs_vfsops.c and > recompile the tmpfs module: > -VFS_SET(tmpfs_vfsops, tmpfs, 0); > +VFS_SET(tmpfs_vfsops, tmpfs, VFCF_JAIL); > > To enable tmpfs for a jail, you have to modify nullfs/null_vfsops.c and > recompile the nullfs module: > -VFS_SET(null_vfsops, nullfs, VFCF_LOOPBACK); > +VFS_SET(null_vfsops, nullfs, VFCF_LOOPBACK | VFCF_JAIL); > > The filesystems can be successfully mounted/unmounted inside a jail and also > unmounted from the parent host without problems. > > The mount inside jail, a jail needs allow.mount=1 and enforce.statfs=0 or > enforce.statfs=1, for more information see jail(8) > I assume other filesystem not dealing with devices may work correctly with > this patch, too (e.g. nfs). > > With jailed nullfs we can run tinderbox in a jail ;) > > Please review, comment and/or test my attached patch. > > Cheers, > mm -- Martin Matuska FreeBSD committer http://blog.vx.sk
Index: sys/kern/kern_jail.c =================================================================== --- sys/kern/kern_jail.c (revision 224471) +++ 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 224471) +++ 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,23 @@ 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 && strlen(fspath) >= MNAMELEN) + error = ENAMETOOLONG; + if (error != 0) { + vput(vp); + if (fbuf != NULL) + free(fbuf, M_TEMP); + return(error); + } + /* * If the user is not root, ensure that they own the directory * onto which we are attempting to mount. @@ -781,12 +792,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,7 +1083,7 @@ NDFREE(&nd, NDF_ONLY_PNBUF); vp = nd.ni_vp; if ((fsflags & MNT_UPDATE) == 0) { - error = vfs_domount_first(td, vfsp, fspath, vp, fsflags, + error = vfs_domount_first(td, vfsp, vp, fsflags, optlist); } else { error = vfs_domount_update(td, vp, fsflags, optlist); @@ -1105,7 +1118,7 @@ } */ *uap; { struct mount *mp; - char *pathbuf; + char *pathbuf, *rpathbuf; int error, id0, id1; AUDIT_ARG_VALUE(uap->flags); @@ -1140,12 +1153,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) {
_______________________________________________ freebsd-current@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-current To unsubscribe, send any mail to "freebsd-current-unsubscr...@freebsd.org"