Skip to content

Commit

Permalink
integration: add mega-test for joining namespaces
Browse files Browse the repository at this point in the history
(This is a cherry-pick of 6fa8d06.)

Given we've had several bugs in this behaviour that have now been fixed,
add an integration test that makes sure that you can start a container
that joins all of the namespaces of a second container.

The only namespace we do not join is the mount namespace, because
joining a namespace that has been pivot_root'd leads to a bunch of
errors. In principle, removing everything from config.json that requires
a mount _should_ work, but the root.path configuration is mandatory and
we cannot just ignore setting up the rootfs in the namespace joining
scenario (if the user has configured a different rootfs, we need to use
it or error out, and there's no reasonable way of checking if if the
rootfs paths are the same that doesn't result in spaghetti logic).

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
  • Loading branch information
cyphar committed Dec 14, 2023
1 parent 8f8cb45 commit 2dd8368
Showing 1 changed file with 57 additions and 0 deletions.
57 changes: 57 additions & 0 deletions tests/integration/run.bats
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,60 @@ function teardown() {
[ "$status" -eq 0 ]
[ "$output" = "410" ]
}

@test "runc run [joining existing container namespaces]" {
# Create a detached container with the namespaces we want. We notably want
# to include userns, which requires config-related configuration.
if [ $EUID -eq 0 ]; then
update_config '.linux.namespaces += [{"type": "user"}]
| .linux.uidMappings += [{"containerID": 0, "hostID": 100000, "size": 100}]
| .linux.gidMappings += [{"containerID": 0, "hostID": 200000, "size": 200}]'
mkdir -p rootfs/{proc,sys,tmp}
fi
update_config '.process.args = ["sleep", "infinity"]'

runc run -d --console-socket "$CONSOLE_SOCKET" target_ctr
[ "$status" -eq 0 ]

# Modify our container's configuration such that it is just going to
# inherit all of the namespaces of the target container.
#
# NOTE: We cannot join the mount namespace of another container because of
# some quirks of the runtime-spec. In particular, we MUST pivot_root into
# root.path and root.path MUST be set in the config, so runc cannot just
# ignore root.path when joining namespaces (and root.path doesn't exist
# inside root.path, for obvious reasons).
#
# We could hack around this (create a copy of the rootfs inside the rootfs,
# or use a simpler mount namespace target), but those wouldn't be similar
# tests to the other namespace joining tests.
target_pid="$(__runc state target_ctr | jq .pid)"
update_config '.linux.namespaces |= map_values(.path = if .type == "mount" then "" else "/proc/'"$target_pid"'/ns/" + ({"network": "net", "mount": "mnt"}[.type] // .type) end)'
# Remove the userns configuration (it cannot be changed).
update_config '.linux |= (del(.uidMappings) | del(.gidMappings))'

runc run -d --console-socket "$CONSOLE_SOCKET" attached_ctr
[ "$status" -eq 0 ]

# Make sure there are two sleep processes in our container.
runc exec attached_ctr ps aux
[ "$status" -eq 0 ]
run -0 grep "sleep infinity" <<<"$output"
[ "${#lines[@]}" -eq 2 ]

# ... that the userns mappings are the same...
runc exec attached_ctr cat /proc/self/uid_map
[ "$status" -eq 0 ]
if [ $EUID -eq 0 ]; then
grep -E '^\s+0\s+100000\s+100$' <<<"$output"
else
grep -E '^\s+0\s+'$EUID'\s+1$' <<<"$output"
fi
runc exec attached_ctr cat /proc/self/gid_map
[ "$status" -eq 0 ]
if [ $EUID -eq 0 ]; then
grep -E '^\s+0\s+200000\s+200$' <<<"$output"
else
grep -E '^\s+0\s+'$EUID'\s+1$' <<<"$output"
fi
}

0 comments on commit 2dd8368

Please sign in to comment.