mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
tests: add test for 'weird' external namespace joining
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
This commit is contained in:
@@ -29,7 +29,7 @@ function teardown() {
|
||||
if [ -v to_umount_list ]; then
|
||||
while read -r mount_path; do
|
||||
umount -l "$mount_path" || :
|
||||
rm -f "$mount_path"
|
||||
rm -rf "$mount_path"
|
||||
done <"$to_umount_list"
|
||||
rm -f "$to_umount_list"
|
||||
unset to_umount_list
|
||||
@@ -184,3 +184,65 @@ function teardown() {
|
||||
grep -E '^\s+0\s+'$EUID'\s+1$' <<<"$output"
|
||||
fi
|
||||
}
|
||||
|
||||
# <https://github.com/opencontainers/runc/issues/4390>
|
||||
@test "userns join external namespaces [wrong userns owner]" {
|
||||
requires root
|
||||
|
||||
# Create an external user namespace for us to join. It seems on some
|
||||
# operating systems (AlmaLinux in particular) "unshare -U" will
|
||||
# automatically use an identity mapping (which breaks this test) so we need
|
||||
# to use runc to create the userns.
|
||||
update_config '.process.args = ["sleep", "infinity"]'
|
||||
runc run -d --console-socket "$CONSOLE_SOCKET" target_userns
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
# Bind-mount the first containers userns nsfd to a different path, to
|
||||
# exercise the non-fast-path (where runc has to join the userns to get the
|
||||
# mappings).
|
||||
userns_pid="$(__runc state target_userns | jq .pid)"
|
||||
userns_path="$(mktemp "$BATS_RUN_TMPDIR/userns.XXXXXX")"
|
||||
mount --bind "/proc/$userns_pid/ns/user" "$userns_path"
|
||||
echo "$userns_path" >>"$to_umount_list"
|
||||
|
||||
# Kill the container -- we have the userns bind-mounted.
|
||||
runc delete -f target_userns
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
# Configure our container to attach to the external userns.
|
||||
update_config '.linux.namespaces |= map(if .type == "user" then (.path = "'"$userns_path"'") else . end)
|
||||
| del(.linux.uidMappings)
|
||||
| del(.linux.gidMappings)'
|
||||
|
||||
# Also create a network namespace that *is not owned* by the above userns.
|
||||
# NOTE: Having no permissions in a namespaces makes it necessary to modify
|
||||
# the config so that we don't get mount errors (for reference: no netns
|
||||
# permissions == no sysfs mounts, no pidns permissoins == no procfs mounts,
|
||||
# no utsns permissions == no sethostname(2), no ipc permissions == no
|
||||
# mqueue mounts, etc).
|
||||
netns_path="$(mktemp "$BATS_RUN_TMPDIR/netns.XXXXXX")"
|
||||
unshare -i -- mount --bind "/proc/self/ns/net" "$netns_path"
|
||||
echo "$netns_path" >>"$to_umount_list"
|
||||
# Configure our container to attach to the external netns.
|
||||
update_config '.linux.namespaces |= map(if .type == "network" then (.path = "'"$netns_path"'") else . end)'
|
||||
|
||||
# Convert sysfs mounts to a bind-mount from the host, to avoid permission
|
||||
# issues due to the netns setup we have.
|
||||
update_config '.mounts |= map((select(.type == "sysfs") | { "source": "/sys", "destination": .destination, "type": "bind", "options": ["rbind"] }) // .)'
|
||||
|
||||
# Create a detached container to verify the namespaces are correct.
|
||||
update_config '.process.args = ["sleep", "infinity"]'
|
||||
runc --debug run -d --console-socket "$CONSOLE_SOCKET" ctr
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
userns_id="user:[$(stat -c "%i" "$userns_path")]"
|
||||
netns_id="net:[$(stat -c "%i" "$netns_path")]"
|
||||
|
||||
runc exec ctr readlink /proc/self/ns/user
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == "$userns_id" ]]
|
||||
|
||||
runc exec ctr readlink /proc/self/ns/net
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == "$netns_id" ]]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user