diff --git a/libcontainer/nsenter/nsexec.c b/libcontainer/nsenter/nsexec.c index 74e15b96d5f..565b2ca2030 100644 --- a/libcontainer/nsenter/nsexec.c +++ b/libcontainer/nsenter/nsexec.c @@ -505,6 +505,17 @@ void join_namespaces(char *nslist) if (setns(ns->fd, flag) < 0) bail("failed to setns into %s namespace", ns->type); + /* + * If we change user namespaces, make sure we switch to root in the + * namespace (this matches the logic for unshare(CLONE_NEWUSER)), lots + * of things can break if we aren't the right user. See + * for one example. + */ + if (flag == CLONE_NEWUSER) { + if (setresuid(0, 0, 0) < 0) + bail("failed to become root in user namespace"); + } + close(ns->fd); } diff --git a/tests/integration/userns.bats b/tests/integration/userns.bats index 2094cbf1448..78583ba4d45 100644 --- a/tests/integration/userns.bats +++ b/tests/integration/userns.bats @@ -125,6 +125,26 @@ function teardown() { fi } +# issue: https://github.com/opencontainers/runc/issues/4466 +@test "userns join other container userns[selinux enabled]" { + if ! selinuxenabled; then + skip "requires SELinux enabled and in enforcing mode" + fi + # Create a detached container with the id-mapping we want. + update_config '.process.args = ["sleep", "infinity"]' + runc run -d --console-socket "$CONSOLE_SOCKET" target_userns + [ "$status" -eq 0 ] + + # Configure our container to attach to the first container's userns. + target_pid="$(__runc state target_userns | jq .pid)" + update_config '.linux.namespaces |= map(if .type == "user" then (.path = "/proc/'"$target_pid"'/ns/" + .type) else . end) + | del(.linux.uidMappings) + | del(.linux.gidMappings) + | .linux.mountLabel="system_u:object_r:container_file_t:s0:c344,c805"' + runc run -d --console-socket "$CONSOLE_SOCKET" in_userns + [ "$status" -eq 0 ] +} + @test "userns join other container userns [bind-mounted nsfd]" { requires root