Merge pull request #34067 from LukeShu/lukeshu/nspawn-fuse
nspawn: enable FUSE in containers
This commit is contained in:
@@ -20,6 +20,10 @@ test_append_files() {
|
||||
# for IPMasquerade=
|
||||
instmods "=net/netfilter"
|
||||
generate_module_dependencies
|
||||
# For unprivileged mountfsd.
|
||||
if command -v openssl >/dev/null 2>&1; then
|
||||
inst_binary openssl
|
||||
fi
|
||||
|
||||
# Create a dummy container "template" with a minimal toolset, which we can
|
||||
# then use as a base for our nspawn/machinectl tests
|
||||
|
||||
@@ -42,6 +42,9 @@ at_exit() {
|
||||
|
||||
mountpoint -q /var/lib/machines && umount --recursive /var/lib/machines
|
||||
rm -f /run/systemd/nspawn/*.nspawn
|
||||
|
||||
rm -fr /var/tmp/TEST-13-NSPAWN.*
|
||||
rm -f /run/verity.d/test-13-nspawn-*.crt
|
||||
}
|
||||
|
||||
trap at_exit EXIT
|
||||
@@ -1031,4 +1034,153 @@ EOF
|
||||
rm -fr "$root"
|
||||
}
|
||||
|
||||
can_do_rootless_nspawn() {
|
||||
# Our create_dummy_ddi() uses squashfs and openssl.
|
||||
command -v mksquashfs &&
|
||||
command -v openssl &&
|
||||
|
||||
# mountfsd must be enabled...
|
||||
[[ -S /run/systemd/io.systemd.MountFileSystem ]] &&
|
||||
# ...and have pidfd support for unprivileged operation.
|
||||
systemd-analyze compare-versions "$(uname -r)" ge 6.5 &&
|
||||
systemd-analyze compare-versions "$(pkcheck --version | awk '{print $3}')" ge 124 &&
|
||||
|
||||
# nsresourced must be enabled...
|
||||
[[ -S /run/systemd/userdb/io.systemd.NamespaceResource ]] &&
|
||||
# ...and must support the UserNamespaceInterface.
|
||||
! (SYSTEMD_LOG_TARGET=console varlinkctl call \
|
||||
/run/systemd/userdb/io.systemd.NamespaceResource \
|
||||
io.systemd.NamespaceResource.AllocateUserRange \
|
||||
'{"name":"test-supported","size":65536,"userNamespaceFileDescriptor":0}' \
|
||||
2>&1 || true) |
|
||||
grep -q "io.systemd.NamespaceResource.UserNamespaceInterfaceNotSupported"
|
||||
}
|
||||
|
||||
create_dummy_ddi() {
|
||||
local outdir="${1:?}"
|
||||
local container_name="${2:?}"
|
||||
|
||||
cat >"$outdir"/openssl.conf <<EOF
|
||||
[ req ]
|
||||
prompt = no
|
||||
distinguished_name = req_distinguished_name
|
||||
|
||||
[ req_distinguished_name ]
|
||||
C = DE
|
||||
ST = Test State
|
||||
L = Test Locality
|
||||
O = Org Name
|
||||
OU = Org Unit Name
|
||||
CN = Common Name
|
||||
emailAddress = test@email.com
|
||||
EOF
|
||||
|
||||
openssl req -config "$outdir"/openssl.conf -subj="/CN=waldo" \
|
||||
-x509 -sha256 -nodes -days 365 -newkey rsa:4096 \
|
||||
-keyout "${outdir}/${container_name}.key" -out "${outdir}/${container_name}.crt"
|
||||
|
||||
mkdir -p /run/verity.d
|
||||
cp "${outdir}/${container_name}.crt" "/run/verity.d/test-13-nspawn-${container_name}.crt"
|
||||
|
||||
SYSTEMD_REPART_OVERRIDE_FSTYPE=squashfs \
|
||||
systemd-repart --make-ddi=portable \
|
||||
--copy-source=/usr/share/TEST-13-NSPAWN-container-template \
|
||||
--certificate="${outdir}/${container_name}.crt" \
|
||||
--private-key="${outdir}/${container_name}.key" \
|
||||
"${outdir}/${container_name}.raw"
|
||||
}
|
||||
|
||||
testcase_unpriv() {
|
||||
if ! can_do_rootless_nspawn; then
|
||||
echo "Skipping rootless test..."
|
||||
return 0
|
||||
fi
|
||||
|
||||
local tmpdir name
|
||||
tmpdir="$(mktemp -d /var/tmp/TEST-13-NSPAWN.unpriv.XXX)"
|
||||
name="unpriv-${tmpdir##*.}"
|
||||
trap 'rm -fr ${tmpdir@Q} || true; rm -f /run/verity.d/test-13-nspawn-${name@Q} || true' RETURN ERR
|
||||
create_dummy_ddi "$tmpdir" "$name"
|
||||
chown --recursive testuser: "$tmpdir"
|
||||
|
||||
systemd-run \
|
||||
--pipe \
|
||||
--uid=testuser \
|
||||
--property=Delegate=yes \
|
||||
-- \
|
||||
systemd-nspawn --pipe --private-network --register=no --keep-unit --image="$tmpdir/$name.raw" echo hello >"$tmpdir/stdout.txt"
|
||||
echo hello | cmp "$tmpdir/stdout.txt" -
|
||||
}
|
||||
|
||||
testcase_fuse() {
|
||||
if [[ "$(cat <>/dev/fuse 2>&1)" != 'cat: -: Operation not permitted' ]]; then
|
||||
echo "FUSE is not supported, skipping the test..."
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Assume that the tests are running on a kernel that is new enough for FUSE
|
||||
# to have user-namespace support; and so we should expect that nspawn
|
||||
# enables FUSE. This test does not validate that the version check
|
||||
# disables FUSE on old kernels.
|
||||
|
||||
local root
|
||||
|
||||
root="$(mktemp -d /var/lib/machines/TEST-13-NSPAWN.fuse.XXX)"
|
||||
create_dummy_container "$root"
|
||||
|
||||
# To avoid adding any complex dependencies to the test, we simply check
|
||||
# that /dev/fuse can be opened for reading and writing (O_RDWR), but that
|
||||
# actually reading from it fails with EPERM. This can be done with a
|
||||
# simple Bash script: run `cat <>/dev/fuse` and if the EPERM error message
|
||||
# comes from "bash" then we know it couldn't be opened, while if it comes
|
||||
# from "cat" then we know that it was opened but not read. If we are able
|
||||
# to read from the file, then this indicates that it's not a real FUSE
|
||||
# device (which requires us to mount a type="fuse" filesystem with the
|
||||
# option string "fd=${num}" for /dev/fuse FD before reading from it will
|
||||
# return anything other than EPERM); if this happens then most likely
|
||||
# nspawn didn't create the file at all and Bash "<>" simply created a new
|
||||
# normal file.
|
||||
#
|
||||
# "cat: -: Operation not permitted" # pass the test; opened but not read
|
||||
# "bash: line 1: /dev/fuse: Operation not permitted" # fail the test; could not open
|
||||
# "" # fail the test; reading worked
|
||||
[[ "$(systemd-nspawn --pipe --directory="$root" \
|
||||
bash -c 'cat <>/dev/fuse' 2>&1)" == 'cat: -: Operation not permitted' ]]
|
||||
|
||||
rm -fr "$root"
|
||||
}
|
||||
|
||||
testcase_unpriv_fuse() {
|
||||
# Same as above, but for unprivileged operation.
|
||||
|
||||
if [[ "$(cat <>/dev/fuse 2>&1)" != 'cat: -: Operation not permitted' ]]; then
|
||||
echo "FUSE is not supported, skipping the test..."
|
||||
return 0
|
||||
fi
|
||||
if ! can_do_rootless_nspawn; then
|
||||
echo "Skipping rootless test..."
|
||||
return 0
|
||||
fi
|
||||
|
||||
local tmpdir name
|
||||
tmpdir="$(mktemp -d /var/tmp/TEST-13-NSPAWN.unpriv-fuse.XXX)"
|
||||
# $name must be such that len("ns-$(id -u testuser)-nspawn-${name}-65535")
|
||||
# <= 31, or nsresourced will reject the request for a namespace.
|
||||
# Therefore; len($name) <= 10 bytes.
|
||||
name="ufuse-${tmpdir##*.}"
|
||||
trap 'rm -fr ${tmpdir@Q} || true; rm -f /run/verity.d/test-13-nspawn-${name@Q} || true' RETURN ERR
|
||||
create_dummy_ddi "$tmpdir" "$name"
|
||||
chown --recursive testuser: "$tmpdir"
|
||||
|
||||
[[ "$(systemd-run \
|
||||
--pipe \
|
||||
--uid=testuser \
|
||||
--property=Delegate=yes \
|
||||
--setenv=SYSTEMD_LOG_LEVEL \
|
||||
--setenv=SYSTEMD_LOG_TARGET \
|
||||
-- \
|
||||
systemd-nspawn --pipe --private-network --register=no --keep-unit --image="$tmpdir/$name.raw" \
|
||||
bash -c 'cat <>/dev/fuse' 2>&1)" == *'cat: -: Operation not permitted' ]]
|
||||
}
|
||||
|
||||
run_testcases
|
||||
|
||||
Reference in New Issue
Block a user