Skip to content

Commit

Permalink
Allow mounting snapshots in .zfs/snapshot as a regular user
Browse files Browse the repository at this point in the history
Rather than doing a terrible credential swapping hack, we just
check that the thing being mounted is a snapshot, and the mountpoint
is the zfsctl directory, then we allow it.

Signed-off-by: Allan Jude <allan@klarasystems.com>
Sponsored-by: Modirum MDPay
Sponsored-by: Klara Inc.
  • Loading branch information
allanjude committed Aug 10, 2022
1 parent b3d0568 commit 53b3d6d
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 14 deletions.
12 changes: 0 additions & 12 deletions module/os/freebsd/spl/spl_vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ mount_snapshot(kthread_t *td, vnode_t **vpp, const char *fstype, char *fspath,
struct vfsconf *vfsp;
struct mount *mp;
vnode_t *vp, *mvp;
struct ucred *pcr, *tcr;
int error;

ASSERT_VOP_ELOCKED(*vpp, "mount_snapshot");
Expand Down Expand Up @@ -195,18 +194,7 @@ mount_snapshot(kthread_t *td, vnode_t **vpp, const char *fstype, char *fspath,
*/
mp->mnt_flag |= MNT_IGNORE;

/*
* XXX: This is evil, but we can't mount a snapshot as a regular user.
* XXX: Is is safe when snapshot is mounted from within a jail?
*/
tcr = td->td_ucred;
pcr = td->td_proc->p_ucred;
td->td_ucred = kcred;
td->td_proc->p_ucred = kcred;
error = VFS_MOUNT(mp);
td->td_ucred = tcr;
td->td_proc->p_ucred = pcr;

if (error != 0) {
/*
* Clear VI_MOUNT and decrement the use count "atomically",
Expand Down
13 changes: 11 additions & 2 deletions module/os/freebsd/zfs/zfs_vfsops.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ int zfs_debug_level;
SYSCTL_INT(_vfs_zfs, OID_AUTO, debug, CTLFLAG_RWTUN, &zfs_debug_level, 0,
"Debug level");

int zfs_jail_mount_snapshot;
SYSCTL_INT(_vfs_zfs, OID_AUTO, jail_mount_snapshot, CTLFLAG_RW,
&zfs_jail_mount_snapshot, 0,
"Allow mounting snapshots in the .zfs directory within jails");

SYSCTL_NODE(_vfs_zfs, OID_AUTO, version, CTLFLAG_RD, 0, "ZFS versions");
static int zfs_version_acl = ZFS_ACL_VERSION;
SYSCTL_INT(_vfs_zfs_version, OID_AUTO, acl, CTLFLAG_RD, &zfs_version_acl, 0,
Expand Down Expand Up @@ -1324,7 +1329,7 @@ zfs_mount(vfs_t *vfsp)
char *osname;
int error = 0;
int canwrite;
bool checkpointrewind;
bool checkpointrewind, isctlsnap = false;

if (vfs_getopt(vfsp->mnt_optnew, "from", (void **)&osname, NULL))
return (SET_ERROR(EINVAL));
Expand All @@ -1339,6 +1344,7 @@ zfs_mount(vfs_t *vfsp)
}

fetch_osname_options(osname, &checkpointrewind);
isctlsnap = (zfsctl_is_node(mvp) && strchr(osname, '@') != NULL);

/*
* Check for mount privilege?
Expand All @@ -1347,7 +1353,9 @@ zfs_mount(vfs_t *vfsp)
* we have local permission to allow it
*/
error = secpolicy_fs_mount(cr, mvp, vfsp);
if (error) {
if (error && isctlsnap) {
secpolicy_fs_mount_clearopts(cr, vfsp);
} else if (error) {
if (dsl_deleg_access(osname, ZFS_DELEG_PERM_MOUNT, cr) != 0)
goto out;

Expand Down Expand Up @@ -1383,6 +1391,7 @@ zfs_mount(vfs_t *vfsp)
* dataset is not visible.
*/
if (!INGLOBALZONE(curproc) &&
(isctlsnap && !zfs_jail_mount_snapshot) &&
(!zone_dataset_visible(osname, &canwrite) || !canwrite)) {
error = SET_ERROR(EPERM);
goto out;
Expand Down

0 comments on commit 53b3d6d

Please sign in to comment.