From c78f3f2ea0f732a4d95c54b4cfc1c237713dbf4d Mon Sep 17 00:00:00 2001 From: lifubang Date: Thu, 24 Oct 2024 22:17:54 +0800 Subject: [PATCH 1/2] libct/nsenter: become root after joining userns Containerd pre-creates userns and netns before calling runc, which results in the current code not working when SELinux is enabled, resulting in the following error: > runc create failed: unable to start container process: error during container init: error mounting "mqueue" to rootfs at "/dev/mqueue": setxattr /path/to/rootfs/dev/mqueue: operation not permitted The solution is to become root in the user namespace right after we join it. Fixes #4466. Co-authored-by: Wei Fu Co-authored-by: Kir Kolyshkin Co-authored-by: Aleksa Sarai Signed-off-by: lifubang --- libcontainer/nsenter/nsexec.c | 11 +++++++++++ 1 file changed, 11 insertions(+) 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); } From 34a928550f01c6fb2b75baf81fcd6ccfa6d58c9c Mon Sep 17 00:00:00 2001 From: lifubang Date: Fri, 25 Oct 2024 14:01:05 +0800 Subject: [PATCH 2/2] test join other container userns with selinux enabled Signed-off-by: lifubang --- tests/integration/userns.bats | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) 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