From bb47d8a545f82849f637c480459109e16be336cf Mon Sep 17 00:00:00 2001 From: Jamie Liu Date: Tue, 19 Feb 2019 14:19:07 -0800 Subject: Fix clone(CLONE_NEWUSER). - Use new user namespace for namespace creation checks. - Ensure userns is never nil since it's used by other namespaces. PiperOrigin-RevId: 234673175 Change-Id: I4b9d9d1e63ce4e24362089793961a996f7540cd9 --- test/syscalls/linux/BUILD | 2 ++ test/syscalls/linux/fork.cc | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) (limited to 'test/syscalls') diff --git a/test/syscalls/linux/BUILD b/test/syscalls/linux/BUILD index 3c61c48ef..e7f5ea998 100644 --- a/test/syscalls/linux/BUILD +++ b/test/syscalls/linux/BUILD @@ -732,7 +732,9 @@ cc_binary( srcs = ["fork.cc"], linkstatic = 1, deps = [ + "//test/util:capability_util", "//test/util:logging", + "//test/util:memory_util", "//test/util:test_main", "//test/util:test_util", "//test/util:thread_util", diff --git a/test/syscalls/linux/fork.cc b/test/syscalls/linux/fork.cc index 1bff5e50f..73ac885b5 100644 --- a/test/syscalls/linux/fork.cc +++ b/test/syscalls/linux/fork.cc @@ -21,11 +21,14 @@ #include #include #include +#include #include "gtest/gtest.h" #include "absl/time/clock.h" #include "absl/time/time.h" +#include "test/util/capability_util.h" #include "test/util/logging.h" +#include "test/util/memory_util.h" #include "test/util/test_util.h" #include "test/util/thread_util.h" @@ -393,6 +396,34 @@ TEST_F(ForkTest, Affinity) { EXPECT_THAT(Wait(child), SyscallSucceedsWithValue(0)); } +TEST(CloneTest, NewUserNamespacePermitsAllOtherNamespaces) { + // "If CLONE_NEWUSER is specified along with other CLONE_NEW* flags in a + // single clone(2) or unshare(2) call, the user namespace is guaranteed to be + // created first, giving the child (clone(2)) or caller (unshare(2)) + // privileges over the remaining namespaces created by the call. Thus, it is + // possible for an unprivileged caller to specify this combination of flags." + // - user_namespaces(7) + SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(CanCreateUserNamespace())); + Mapping child_stack = ASSERT_NO_ERRNO_AND_VALUE( + MmapAnon(kPageSize, PROT_READ | PROT_WRITE, MAP_PRIVATE)); + int child_pid; + // We only test with CLONE_NEWIPC, CLONE_NEWNET, and CLONE_NEWUTS since these + // namespaces were implemented in Linux before user namespaces. + ASSERT_THAT( + child_pid = clone( + +[](void*) { return 0; }, + reinterpret_cast(child_stack.addr() + kPageSize), + CLONE_NEWUSER | CLONE_NEWIPC | CLONE_NEWNET | CLONE_NEWUTS | SIGCHLD, + /* arg = */ nullptr), + SyscallSucceeds()); + + int status; + ASSERT_THAT(waitpid(child_pid, &status, 0), + SyscallSucceedsWithValue(child_pid)); + EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0) + << "status = " << status; +} + #ifdef __x86_64__ // Clone with CLONE_SETTLS and a non-canonical TLS address is rejected. TEST(CloneTest, NonCanonicalTLS) { -- cgit v1.2.3