1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
|
summary: userns restrictions work for strict mode snaps
details: |
This test checks that a snap which plugs the userns interface is able to use
unprivileged user namespaces only when the userns interface is connected on
systems that support restrictions on unprivileged user namespaces.
# This test is not executed on a core system simply because of the hassle of
# building the support C program.
# ubuntu-14.04: the test sets up a user session, which requires more recent systemd
systems: [-ubuntu-core-*, -ubuntu-14.04-*]
environment:
# This is used to abbreviate some of the paths below.
P: /var/snap/test-snapd-userns/common
prepare: |
echo "Install a helper snap (for confinement testing)"
"$TESTSTOOLS"/snaps-state install-local test-snapd-userns
echo "Compile and prepare the support program"
# Because we use the snap data directory we don't need to clean it up
# manually as all snaps and their data are reset after each test.
# Build the test binary statically, as it will be running inside a base with
# potentially older glibc.
gcc -Wall -Wextra -Werror ./unshare.c -o "$P/unshare" -static
tests.session -u test prepare
restore: |
tests.session -u test restore
execute: |
# ensure that the system supports unprivileged userns and it is enabled
if ! sysctl kernel.unprivileged_userns_clone; then
echo "Skipping testing of unprivileged userns since it is not supported by the kernel"
exit 0
fi
echo "Enable the use of unprivileged user namespaces by default"
orig_userns_clone=$(sysctl -n kernel.unprivileged_userns_clone)
sysctl -w kernel.unprivileged_userns_clone=1
tests.cleanup defer sysctl -w kernel.unprivileged_userns_clone="$orig_userns_clone"
echo "The userns interface is disconnected by default"
snap connections test-snapd-userns | MATCH 'userns +test-snapd-userns:userns +- +-'
# running unshare -U to create a new user namespace should be denied as an
# unprivileged user by seccomp
echo "When the userns interface is disconnected creating a new user namespace is denied"
tests.session -u test exec sh -c "snap run test-snapd-userns.with-userns-plug -c '\\$P/unshare -U id'" 2>&1 | MATCH 'unshare: unshare: Operation not permitted'
echo "Connect the userns interface"
snap connect test-snapd-userns:userns
snap connections test-snapd-userns | MATCH 'userns +test-snapd-userns:userns +:userns +manual'
# running unshare -U to create a new user namespace should be allowed
echo "When the userns interface is connected creating a new user namespace is allowed"
nobody_group=nogroup
# on arch the group is called nobody
if os.query is-arch-linux; then
nobody_group=nobody
fi
tests.session -u test exec sh -c "snap run test-snapd-userns.with-userns-plug -c '\\$P/unshare -U id'" 2>&1 | MATCH 'uid=65534\(nobody\) gid=65534\('"$nobody_group"'\) groups=65534\('"$nobody_group"'\)'
# check the userns feature is supported by snapd itself - this should always
# be the case when using the vendored apparmor
if snap debug sandbox-features --required apparmor:parser:snapd-internal; then
if ! snap debug sandbox-features --required apparmor:parser:userns; then
echo "The internal vendored apparmor within snapd does not support userns restrictions"
exit 1
fi
else
if ! snap debug sandbox-features --required apparmor:parser:userns; then
# apparmor in ubuntu since kinetic should support userns
if os.query is-ubuntu-ge 22.10; then
echo "Ubuntu host system AppArmor does not support userns but it should"
exit 1
fi
echo "Host system AppArmor does not support userns, skipping remainder of test"
exit 0
fi
fi
# now check the kernel AppArmor userns enforcement as well as seccomp
# enforcement above
if [ ! -e /proc/sys/kernel/apparmor_restrict_unprivileged_userns ]; then
echo "Skipping testing of AppArmor enforcement since it is not supported by the kernel"
exit 0
fi
# enable AppArmor enforcement
echo "Enable AppArmor enforcement of unprivileged user namespace restrictions"
orig_apparmor_userns=$(sysctl -n kernel.apparmor_restrict_unprivileged_userns)
sysctl -w kernel.apparmor_restrict_unprivileged_userns=1
tests.cleanup defer sysctl -w kernel.apparmor_restrict_unprivileged_userns="$orig_apparmor_userns"
# and remove the AppArmor permission from the snap's AppArmor profile
sed -i 's/userns,/##spread##userns,/' /var/lib/snapd/apparmor/profiles/snap.test-snapd-userns.with-userns-plug
# then reload the profile, ensuring the right apparmor_parser is used -
# always use the policy features of the kernel to ensure that the parser
# does not silently downgrade the profile
APPARMOR_PARSER="apparmor_parser --policy-features=<kernel>"
if snap debug sandbox-features --required apparmor:parser:snapd-internal; then
APPARMOR_PARSER="/snap/snapd/current/usr/lib/snapd/apparmor_parser --config-file /snap/snapd/current/usr/lib/snapd/apparmor/parser.conf -b /snap/snapd/current/usr/lib/snapd/apparmor.d --policy-features=<kernel>"
fi
$APPARMOR_PARSER -r /var/lib/snapd/apparmor/profiles/snap.test-snapd-userns.with-userns-plug
# running unshare -U as an unprivileged user to create a new user namespace
# should be denied
echo "When the userns AppArmor permission is removed creating a new user namespace as an unprivileged user is denied"
tests.session -u test exec sh -c "snap run test-snapd-userns.with-userns-plug -c '\$SNAP_COMMON/unshare -U id'" 2>&1 | MATCH 'unshare: unshare: Permission denied'
# it should also be denied for root as well as per
# https://gitlab.com/apparmor/apparmor/-/wikis/unprivileged_userns_restriction#allowing-user-namespaces-creation-in-policy
echo "When the userns AppArmor permission is removed creating a new user namespace as root is denied"
snap run test-snapd-userns.with-userns-plug -c "\$SNAP_COMMON/unshare -U id" 2>&1 | MATCH 'unshare: unshare: Permission denied'
|