Index: sandbox/linux/services/namespace_sandbox.cc |
diff --git a/sandbox/linux/services/namespace_sandbox.cc b/sandbox/linux/services/namespace_sandbox.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..63749cb190aab7bd5b68318d528d162d3126d03c |
--- /dev/null |
+++ b/sandbox/linux/services/namespace_sandbox.cc |
@@ -0,0 +1,116 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "sandbox/linux/services/namespace_sandbox.h" |
+ |
+#include <sched.h> |
+#include <stdlib.h> |
+#include <unistd.h> |
+ |
+#include <string> |
+ |
+#include "base/bind.h" |
+#include "base/environment.h" |
+#include "base/logging.h" |
+#include "base/posix/eintr_wrapper.h" |
+#include "base/strings/stringprintf.h" |
+#include "sandbox/linux/services/namespace_utils.h" |
+ |
+namespace sandbox { |
+ |
+namespace { |
+const char kPipeValue = '\xcc'; |
+ |
+void SetEnvironForNamespaceType(base::EnvironmentMap* environ, |
+ base::NativeEnvironmentString env_var, |
+ bool value) { |
+ // An empty string causes the env var to be unset in the child process. |
+ (*environ)[env_var] = value ? "1" : ""; |
+} |
+ |
+const char kSandboxUSERNSEnvironmentVarName[] = "SBX_USER_NS"; |
+const char kSandboxPIDNSEnvironmentVarName[] = "SBX_PID_NS"; |
+const char kSandboxNETNSEnvironmentVarName[] = "SBX_NET_NS"; |
+ |
+} // namespace |
+ |
+NamespaceSandbox::NamespaceSandbox() { |
+} |
+ |
+NamespaceSandbox::~NamespaceSandbox() { |
+} |
+ |
+void NamespaceSandbox::SetupLaunchOptions( |
+ base::LaunchOptions* options, |
+ base::FileHandleMappingVector* fds_to_remap) { |
+ int clone_flags = 0; |
+ int ns_types[] = {CLONE_NEWUSER, CLONE_NEWPID, CLONE_NEWNET}; |
+ for (const int ns_type : ns_types) { |
+ if (NamespaceUtils::KernelSupportsUnprivilegedNamespace(ns_type)) { |
+ clone_flags |= ns_type; |
+ } |
+ } |
+ |
+ CHECK(clone_flags & CLONE_NEWUSER); |
+ |
+ base::EnvironmentMap* environ = &options->environ; |
jln (very slow on Chromium)
2015/01/28 02:34:39
DCHECK environ?
rickyz (no longer on Chrome)
2015/01/29 00:57:48
Don't think this is needed since environ isn't a p
|
+ SetEnvironForNamespaceType(environ, kSandboxUSERNSEnvironmentVarName, |
jln (very slow on Chromium)
2015/01/28 02:34:39
For loop?
rickyz (no longer on Chrome)
2015/01/29 00:57:48
Done.
|
+ clone_flags & CLONE_NEWUSER); |
+ SetEnvironForNamespaceType(environ, kSandboxPIDNSEnvironmentVarName, |
+ clone_flags & CLONE_NEWPID); |
+ SetEnvironForNamespaceType(environ, kSandboxNETNSEnvironmentVarName, |
+ clone_flags & CLONE_NEWNET); |
+ |
+ int fds[2]; |
+ PCHECK(pipe(fds) == 0); |
+ read_fd_.reset(fds[0]); |
+ write_fd_.reset(fds[1]); |
+ fds_to_remap->push_back(std::make_pair(read_fd_.get(), read_fd_.get())); |
+ read_from_pipe_delegate_.set_fd(read_fd_.get()); |
+ options->pre_exec_delegate = &read_from_pipe_delegate_; |
+ options->clone_flags = clone_flags; |
+} |
+ |
+void NamespaceSandbox::PrepareSandboxedProcess(base::ProcessId pid) { |
+ read_fd_.reset(); |
jln (very slow on Chromium)
2015/01/28 02:34:38
This should destruct the ReadFromPipeDelegate inst
rickyz (no longer on Chrome)
2015/01/29 00:57:48
See the other comment about read_fd_ ownership - t
|
+ |
+ const std::string uid_map_path = base::StringPrintf("/proc/%d/uid_map", pid); |
+ const std::string gid_map_path = base::StringPrintf("/proc/%d/gid_map", pid); |
+ NamespaceUtils::WriteToIdMapFile(uid_map_path.c_str(), getuid()); |
+ NamespaceUtils::WriteToIdMapFile(gid_map_path.c_str(), getgid()); |
+ |
+ PCHECK(HANDLE_EINTR(write(write_fd_.get(), &kPipeValue, 1)) == 1); |
+ write_fd_.reset(); |
+} |
+ |
+bool NamespaceSandbox::InNewUserNamespace() { |
+ return getenv(kSandboxUSERNSEnvironmentVarName) != nullptr; |
+} |
+ |
+bool NamespaceSandbox::InNewPidNamespace() { |
+ return getenv(kSandboxPIDNSEnvironmentVarName) != nullptr; |
+} |
+ |
+bool NamespaceSandbox::InNewNetNamespace() { |
+ return getenv(kSandboxNETNSEnvironmentVarName) != nullptr; |
+} |
+ |
+NamespaceSandbox::ReadFromPipeDelegate::ReadFromPipeDelegate() : fd_(-1) { |
+} |
+ |
+NamespaceSandbox::ReadFromPipeDelegate::~ReadFromPipeDelegate() { |
+} |
+ |
+void NamespaceSandbox::ReadFromPipeDelegate::RunAsyncSafe() { |
+ char c; |
+ RAW_CHECK(HANDLE_EINTR(read(fd_, &c, 1)) == 1); |
+ RAW_CHECK(IGNORE_EINTR(close(fd_)) == 0); |
+ RAW_CHECK(c == kPipeValue); |
+} |
+ |
+void NamespaceSandbox::ReadFromPipeDelegate::set_fd(int fd) { |
+ fd_ = fd; |
+} |
+ |
+} // namespace sandbox |