summaryrefslogtreecommitdiffhomepage
path: root/test/syscalls/linux/fork.cc
diff options
context:
space:
mode:
authorJamie Liu <jamieliu@google.com>2019-02-19 14:19:07 -0800
committerShentubot <shentubot@google.com>2019-02-19 14:20:05 -0800
commitbb47d8a545f82849f637c480459109e16be336cf (patch)
tree2c47b462d5ae4edb1df6861c753f099b92d97627 /test/syscalls/linux/fork.cc
parent22d8b6eba1487d3f0d87a578e414e451d9aeb26d (diff)
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
Diffstat (limited to 'test/syscalls/linux/fork.cc')
-rw-r--r--test/syscalls/linux/fork.cc31
1 files changed, 31 insertions, 0 deletions
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 <sys/types.h>
#include <unistd.h>
#include <atomic>
+#include <cstdlib>
#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<void*>(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) {