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"

Reply via email to