mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 18:40:43 +03:00
Add Linux namespace delegation support
This allows ZFS datasets to be delegated to a user/mount namespace Within that namespace, only the delegated datasets are visible Works very similarly to Zones/Jailes on other ZFS OSes As a user: ``` $ unshare -Um $ zfs list no datasets available $ echo $$ 1234 ``` As root: ``` # zfs list NAME ZONED MOUNTPOINT containers off /containers containers/host off /containers/host containers/host/child off /containers/host/child containers/host/child/gchild off /containers/host/child/gchild containers/unpriv on /unpriv containers/unpriv/child on /unpriv/child containers/unpriv/child/gchild on /unpriv/child/gchild # zfs zone /proc/1234/ns/user containers/unpriv ``` Back to the user namespace: ``` $ zfs list NAME USED AVAIL REFER MOUNTPOINT containers 129M 47.8G 24K /containers containers/unpriv 128M 47.8G 24K /unpriv containers/unpriv/child 128M 47.8G 128M /unpriv/child ``` Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Will Andrews <will.andrews@klarasystems.com> Signed-off-by: Allan Jude <allan@klarasystems.com> Signed-off-by: Mateusz Piotrowski <mateusz.piotrowski@klarasystems.com> Co-authored-by: Allan Jude <allan@klarasystems.com> Co-authored-by: Mateusz Piotrowski <mateusz.piotrowski@klarasystems.com> Sponsored-by: Buddy <https://buddy.works> Closes #12263
This commit is contained in:
committed by
Brian Behlendorf
parent
a1aa8f14c8
commit
4ed5e25074
@@ -177,7 +177,8 @@ tests = ['upgrade_projectquota_001_pos']
|
||||
tags = ['functional', 'upgrade']
|
||||
|
||||
[tests/functional/user_namespace:Linux]
|
||||
tests = ['user_namespace_001']
|
||||
tests = ['user_namespace_001', 'user_namespace_002', 'user_namespace_003',
|
||||
'user_namespace_004']
|
||||
tags = ['functional', 'user_namespace']
|
||||
|
||||
[tests/functional/userquota:Linux]
|
||||
|
||||
@@ -146,11 +146,13 @@ export SYSTEM_FILES_LINUX='attr
|
||||
mkswap
|
||||
modprobe
|
||||
mpstat
|
||||
nsenter
|
||||
parted
|
||||
perf
|
||||
setfattr
|
||||
sha256sum
|
||||
udevadm
|
||||
unshare
|
||||
useradd
|
||||
userdel
|
||||
usermod
|
||||
|
||||
@@ -1895,6 +1895,9 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
|
||||
functional/user_namespace/cleanup.ksh \
|
||||
functional/user_namespace/setup.ksh \
|
||||
functional/user_namespace/user_namespace_001.ksh \
|
||||
functional/user_namespace/user_namespace_002.ksh \
|
||||
functional/user_namespace/user_namespace_003.ksh \
|
||||
functional/user_namespace/user_namespace_004.ksh \
|
||||
functional/userquota/cleanup.ksh \
|
||||
functional/userquota/groupspace_001_pos.ksh \
|
||||
functional/userquota/groupspace_002_pos.ksh \
|
||||
|
||||
@@ -47,6 +47,11 @@ function cleanup
|
||||
done
|
||||
}
|
||||
|
||||
unshare -Urm echo test
|
||||
if [ "$?" -ne "0" ]; then
|
||||
log_unsupported "Failed to create user namespace"
|
||||
fi
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
log_assert "Check root in user namespaces"
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or http://www.opensolaris.org/os/licensing.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/user_namespace/user_namespace_common.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Regression test for delegation of datasets to user namespaces.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Delegate a dataset to a user namespace.
|
||||
# 2. Check that 'zfs list' is only able to see inside the delegation.
|
||||
# 3. Check that 'zfs create' is able to create only inside the delegation.
|
||||
# 4. Check that the filesystems can be mounted inside the delegation,
|
||||
# and that file permissions are appropriate.
|
||||
# 5. Check that 'zfs destroy' is able to destroy only inside the delegation.
|
||||
# 6. Check that 'zfs unzone' has a desirable effect.
|
||||
#
|
||||
|
||||
verify_runnable "both"
|
||||
|
||||
user_ns_cleanup() {
|
||||
if [ -n "$proc_ns_added" ]; then
|
||||
log_must zfs unzone $proc_ns_added $TESTPOOL/userns
|
||||
fi
|
||||
if [ -n "$unshared_pid" ]; then
|
||||
kill -9 $unshared_pid
|
||||
# Give it a sec to make the global cleanup more reliable.
|
||||
sleep 1
|
||||
fi
|
||||
log_must zfs destroy -r $TESTPOOL/userns
|
||||
}
|
||||
|
||||
log_onexit user_ns_cleanup
|
||||
|
||||
log_assert "Check zfs/zpool command delegation in user namespaces"
|
||||
|
||||
# Create the baseline datasets.
|
||||
log_must zfs create -o zoned=on $TESTPOOL/userns
|
||||
log_must zfs create -o zoned=on $TESTPOOL/userns/testds
|
||||
# Partial match should be denied; hence we also set this to be 'zoned'.
|
||||
log_must zfs create -o zoned=on $TESTPOOL/user
|
||||
|
||||
# 1. Create a user namespace with a cloned mount namespace, then delegate.
|
||||
unshare -Urm echo test
|
||||
if [ "$?" -ne "0" ]; then
|
||||
log_unsupported "Failed to create user namespace"
|
||||
fi
|
||||
unshare -Urm /usr/bin/sleep 1h &
|
||||
unshared_pid=$!
|
||||
if [ "$?" -ne "0" ]; then
|
||||
log_unsupported "Failed to create user namespace"
|
||||
fi
|
||||
proc_ns=/proc/$unshared_pid/ns/user
|
||||
sleep 2 # Wait for unshare to acquire user namespace
|
||||
log_note "unshare: child=${unshared_pid} proc_ns=${proc_ns}"
|
||||
|
||||
NSENTER="nsenter -t $unshared_pid --all"
|
||||
|
||||
$NSENTER echo test
|
||||
if [ "$?" -ne "0" ]; then
|
||||
log_unsupported "Failed to enter user namespace"
|
||||
fi
|
||||
|
||||
# 1b. Pre-test by checking that 'zone' does something new.
|
||||
list="$($NSENTER zfs list -r -H -o name | tr '\n' ' ')"
|
||||
log_must test -z "$list"
|
||||
log_must zfs zone $proc_ns $TESTPOOL/userns
|
||||
proc_ns_added="$ns"
|
||||
|
||||
# 2. 'zfs list'
|
||||
list="$($NSENTER zfs list -r -H -o name $TESTPOOL | tr '\n' ' ')"
|
||||
log_must test "$list" = "$TESTPOOL $TESTPOOL/userns $TESTPOOL/userns/testds "
|
||||
|
||||
# 3. 'zfs create'
|
||||
log_must $NSENTER zfs create $TESTPOOL/userns/created
|
||||
log_mustnot $NSENTER zfs create $TESTPOOL/user/created
|
||||
|
||||
# 4. Check file permissions (create mounts the filesystem). The 'permissions'
|
||||
# check is simply, does it get mapped to user namespace's root/root?
|
||||
log_must $NSENTER df -h /$TESTPOOL/userns/created
|
||||
log_must $NSENTER mkfile 8192 /$TESTPOOL/userns/created/testfile
|
||||
uidgid=$($NSENTER stat -c '%u %g' /$TESTPOOL/userns/created/testfile)
|
||||
log_must test "${uidgid}" = "0 0"
|
||||
|
||||
# 5. 'zfs destroy'
|
||||
log_must $NSENTER zfs destroy $TESTPOOL/userns/created
|
||||
log_mustnot $NSENTER zfs destroy $TESTPOOL/user
|
||||
|
||||
# 6. 'zfs unzone' should have an effect
|
||||
log_must zfs unzone $proc_ns $TESTPOOL/userns
|
||||
proc_ns_added=""
|
||||
list="$($NSENTER zfs list -r -H -o name | tr '\n' ' ')"
|
||||
log_must test -z "$list"
|
||||
|
||||
log_pass "Check zfs/zpool command delegation in user namespaces"
|
||||
@@ -0,0 +1,97 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or http://www.opensolaris.org/os/licensing.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/user_namespace/user_namespace_common.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Regression test for delegation of datasets to user namespaces.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Delegate two datasets with distinctive names to a user namespace.
|
||||
# 2. Check that 'zfs list' is not able to see datasets outside of the
|
||||
# delegation, which have a prefix matching one of the delegated sets.
|
||||
# Also, check that all the delegated sets are visible.
|
||||
#
|
||||
|
||||
verify_runnable "both"
|
||||
|
||||
user_ns_cleanup() {
|
||||
if [ -n "$proc_ns_added" ]; then
|
||||
log_must zfs unzone $proc_ns_added $TESTPOOL/userns
|
||||
log_must zfs unzone $proc_ns_added $TESTPOOL/otheruserns
|
||||
fi
|
||||
if [ -n "$unshared_pid" ]; then
|
||||
kill -9 $unshared_pid
|
||||
# Give it a sec to make the global cleanup more reliable.
|
||||
sleep 1
|
||||
fi
|
||||
log_must zfs destroy -r $TESTPOOL/userns
|
||||
log_must zfs destroy -r $TESTPOOL/usernsisitnot
|
||||
log_must zfs destroy -r $TESTPOOL/otheruserns
|
||||
}
|
||||
|
||||
log_onexit user_ns_cleanup
|
||||
|
||||
log_assert "Check zfs list command handling of dataset visibility in user namespaces"
|
||||
|
||||
# Create the baseline dataset.
|
||||
log_must zfs create -o zoned=on $TESTPOOL/userns
|
||||
# Datasets with a prefix matching the delegated dataset should not be
|
||||
# automatically considered visible.
|
||||
log_must zfs create -o zoned=on $TESTPOOL/usernsisitnot
|
||||
# All delegated datasets should be visible.
|
||||
log_must zfs create -o zoned=on $TESTPOOL/otheruserns
|
||||
|
||||
# 1. Create a user namespace with a cloned mount namespace, then delegate.
|
||||
unshare -Urm echo test
|
||||
if [ "$?" -ne "0" ]; then
|
||||
log_unsupported "Failed to create user namespace"
|
||||
fi
|
||||
unshare -Urm /usr/bin/sleep 1h &
|
||||
unshared_pid=$!
|
||||
if [ "$?" -ne "0" ]; then
|
||||
log_unsupported "Failed to create user namespace"
|
||||
fi
|
||||
proc_ns=/proc/$unshared_pid/ns/user
|
||||
sleep 2 # Wait for unshare to acquire user namespace
|
||||
log_note "unshare: child=${unshared_pid} proc_ns=${proc_ns}"
|
||||
|
||||
NSENTER="nsenter -t $unshared_pid --all"
|
||||
|
||||
$NSENTER echo test
|
||||
if [ "$?" -ne "0" ]; then
|
||||
log_unsupported "Failed to enter user namespace"
|
||||
fi
|
||||
|
||||
# 1b. Pre-test by checking that 'zone' does something new.
|
||||
list="$($NSENTER zfs list -r -H -o name | tr '\n' ' ')"
|
||||
log_must test -z "$list"
|
||||
log_must zfs zone $proc_ns $TESTPOOL/userns
|
||||
log_must zfs zone $proc_ns $TESTPOOL/otheruserns
|
||||
proc_ns_added="$ns"
|
||||
|
||||
# 2. 'zfs list'
|
||||
list="$($NSENTER zfs list -r -H -o name $TESTPOOL | tr '\n' ' ')"
|
||||
log_must test "$list" = "$TESTPOOL $TESTPOOL/otheruserns $TESTPOOL/userns "
|
||||
|
||||
log_pass "Check zfs list command handling of dataset visibility in user namespaces"
|
||||
@@ -0,0 +1,67 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or http://www.opensolaris.org/os/licensing.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/user_namespace/user_namespace_common.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Regression test for safeguards around the delegation of datasets to
|
||||
# user namespaces.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Check that 'zfs zone' correctly handles the case of the first
|
||||
# argument being a non-namespace file.
|
||||
# 2. Check that 'zfs zone' correctly handles the case of the first
|
||||
# argument being a non-namespace and non-existent file.
|
||||
#
|
||||
|
||||
verify_runnable "both"
|
||||
|
||||
user_ns_cleanup() {
|
||||
if [ -n "$temp_file" ]; then
|
||||
log_must rm -f "$temp_file"
|
||||
fi
|
||||
|
||||
log_must zfs destroy -r "$TESTPOOL/userns"
|
||||
}
|
||||
|
||||
log_onexit user_ns_cleanup
|
||||
|
||||
log_assert "Check zfs zone command handling of non-namespace files"
|
||||
|
||||
# Pass if user namespaces are not supported.
|
||||
unshare -Urm echo test
|
||||
if [ "$?" -ne "0" ]; then
|
||||
log_unsupported "Failed to create user namespace"
|
||||
fi
|
||||
|
||||
# Create the baseline datasets.
|
||||
log_must zfs create -o zoned=on "$TESTPOOL/userns"
|
||||
|
||||
# 1. Try to pass a non-namespace file to zfs zone.
|
||||
temp_file="$(TMPDIR=$TEST_BASE_DIR mktemp)"
|
||||
log_mustnot zfs zone "$temp_file" "$TESTPOOL/userns"
|
||||
|
||||
# 2. Try to pass a non-namespace and non-existent file to zfs zone.
|
||||
log_mustnot zfs zone "$TEMP_BASE_DIR/nonexistent" "$TESTPOOL/userns"
|
||||
|
||||
log_pass "Check zfs zone command handling of non-namespace files"
|
||||
Reference in New Issue
Block a user