diff --git a/tests/integration/run.bats b/tests/integration/run.bats index e2eda270c..705868eb0 100644 --- a/tests/integration/run.bats +++ b/tests/integration/run.bats @@ -160,3 +160,73 @@ function teardown() { [[ "$output" = *"Hello World"* ]] [[ "$output" = *"runc-dmz: using /proc/self/exe clone"* ]] } + +@test "runc run [joining existing container namespaces]" { + requires timens + + # Create a detached container with the namespaces we want. We notably want + # to include both userns and timens, which require 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 '.linux.namespaces += [{"type": "time"}] + | .linux.timeOffsets = { + "monotonic": { "secs": 7881, "nanosecs": 2718281 }, + "boottime": { "secs": 1337, "nanosecs": 3141519 } + }' + 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 and timens configuration (they cannot be changed). + update_config '.linux |= (del(.uidMappings) | del(.gidMappings) | del(.timeOffsets))' + + 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 + + # ... as well as the timens offsets. + runc exec attached_ctr cat /proc/self/timens_offsets + grep -E '^monotonic\s+7881\s+2718281$' <<<"$output" + grep -E '^boottime\s+1337\s+3141519$' <<<"$output" +}