summaryrefslogtreecommitdiffstats
path: root/content/zygote
diff options
context:
space:
mode:
authorrickyz <rickyz@chromium.org>2015-04-13 14:41:14 -0700
committerCommit bot <commit-bot@chromium.org>2015-04-13 21:41:57 +0000
commit3f16f8e52e917af2f33fc6248f12c0c8e9f9a376 (patch)
treea47201908168a6e10e30157719d86aa754868c0b /content/zygote
parent2936dd47b92f0e1281c181f18ebae2921585fe5c (diff)
downloadchromium_src-3f16f8e52e917af2f33fc6248f12c0c8e9f9a376.zip
chromium_src-3f16f8e52e917af2f33fc6248f12c0c8e9f9a376.tar.gz
chromium_src-3f16f8e52e917af2f33fc6248f12c0c8e9f9a376.tar.bz2
Start all children in their own PID namespace.
This change was split out of https://codereview.chromium.org/868233011/, which was reverted due to a kernel bug. BUG=460972 Review URL: https://codereview.chromium.org/1057403002 Cr-Commit-Position: refs/heads/master@{#324917}
Diffstat (limited to 'content/zygote')
-rw-r--r--content/zygote/zygote_linux.cc44
-rw-r--r--content/zygote/zygote_main_linux.cc16
2 files changed, 55 insertions, 5 deletions
diff --git a/content/zygote/zygote_linux.cc b/content/zygote/zygote_linux.cc
index 5944f87..5a84dec 100644
--- a/content/zygote/zygote_linux.cc
+++ b/content/zygote/zygote_linux.cc
@@ -36,6 +36,8 @@
#include "content/public/common/zygote_fork_delegate_linux.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_switches.h"
+#include "sandbox/linux/services/credentials.h"
+#include "sandbox/linux/services/namespace_sandbox.h"
// See http://code.google.com/p/chromium/wiki/LinuxZygote
@@ -47,6 +49,14 @@ namespace {
void SIGCHLDHandler(int signal) {
}
+// On Linux, when a process is the init process of a PID namespace, it cannot be
+// terminated by signals like SIGTERM or SIGINT, since they are ignored unless
+// we register a handler for them. In the handlers, we exit with this special
+// exit code that GetTerminationStatus understands to mean that we were
+// terminated by an external signal.
+const int kKilledExitCode = 0x80;
+const int kUnexpectedExitCode = 0x81;
+
int LookUpFd(const base::GlobalDescriptors::Mapping& fd_mapping, uint32_t key) {
for (size_t index = 0; index < fd_mapping.size(); ++index) {
if (fd_mapping[index].key == key)
@@ -104,7 +114,7 @@ bool Zygote::ProcessRequests() {
struct sigaction action;
memset(&action, 0, sizeof(action));
action.sa_handler = &SIGCHLDHandler;
- CHECK(sigaction(SIGCHLD, &action, NULL) == 0);
+ PCHECK(sigaction(SIGCHLD, &action, NULL) == 0);
if (UsingSUIDSandbox() || UsingNSSandbox()) {
// Let the ZygoteHost know we are ready to go.
@@ -305,6 +315,11 @@ bool Zygote::GetTerminationStatus(base::ProcessHandle real_pid,
// Time to forget about this process.
process_info_map_.erase(real_pid);
}
+
+ if (WIFEXITED(*exit_code) && WEXITSTATUS(*exit_code) == kKilledExitCode) {
+ *status = base::TERMINATION_STATUS_PROCESS_WAS_KILLED;
+ }
+
return true;
}
@@ -375,12 +390,33 @@ int Zygote::ForkWithRealPid(const std::string& process_type,
CHECK_NE(pid, 0);
} else {
CreatePipe(&read_pipe, &write_pipe);
- // This is roughly equivalent to a fork(). We are using ForkWithFlags mainly
- // to give it some more diverse test coverage.
- pid = base::ForkWithFlags(SIGCHLD, nullptr, nullptr);
+ if (sandbox_flags_ & kSandboxLinuxPIDNS &&
+ sandbox_flags_ & kSandboxLinuxUserNS) {
+ pid = sandbox::NamespaceSandbox::ForkInNewPidNamespace(
+ /*drop_capabilities_in_child=*/true);
+ } else {
+ pid = fork();
+ }
}
if (pid == 0) {
+ // If the process is the init process inside a PID namespace, it must have
+ // explicit signal handlers.
+ if (getpid() == 1) {
+ for (const int sig : {SIGINT, SIGTERM}) {
+ sandbox::NamespaceSandbox::InstallTerminationSignalHandler(
+ sig, kKilledExitCode);
+ }
+
+ static const int kUnexpectedSignals[] = {
+ SIGHUP, SIGQUIT, SIGABRT, SIGPIPE, SIGUSR1, SIGUSR2,
+ };
+ for (const int sig : kUnexpectedSignals) {
+ sandbox::NamespaceSandbox::InstallTerminationSignalHandler(
+ sig, kUnexpectedExitCode);
+ }
+ }
+
// In the child process.
write_pipe.reset();
diff --git a/content/zygote/zygote_main_linux.cc b/content/zygote/zygote_main_linux.cc
index 8a03e4e..ab12e5b 100644
--- a/content/zygote/zygote_main_linux.cc
+++ b/content/zygote/zygote_main_linux.cc
@@ -40,6 +40,7 @@
#include "content/public/common/zygote_fork_delegate_linux.h"
#include "content/zygote/zygote_linux.h"
#include "crypto/nss_util.h"
+#include "sandbox/linux/services/credentials.h"
#include "sandbox/linux/services/init_process_reaper.h"
#include "sandbox/linux/services/libc_urandom_override.h"
#include "sandbox/linux/services/namespace_sandbox.h"
@@ -80,6 +81,11 @@ void CloseFds(const std::vector<int>& fds) {
}
}
+void RunTwoClosures(const base::Closure* first, const base::Closure* second) {
+ first->Run();
+ second->Run();
+}
+
} // namespace
// See http://code.google.com/p/chromium/wiki/LinuxZygote
@@ -407,12 +413,20 @@ static bool EnterSuidSandbox(sandbox::SetuidSandboxClient* setuid_sandbox,
return true;
}
+static void DropAllCapabilities(int proc_fd) {
+ CHECK(sandbox::Credentials::DropAllCapabilities(proc_fd));
+}
+
static void EnterNamespaceSandbox(LinuxSandbox* linux_sandbox,
base::Closure* post_fork_parent_callback) {
linux_sandbox->EngageNamespaceSandbox();
if (getpid() == 1) {
- CHECK(CreateInitProcessReaper(post_fork_parent_callback));
+ base::Closure drop_all_caps_callback =
+ base::Bind(&DropAllCapabilities, linux_sandbox->proc_fd());
+ base::Closure callback = base::Bind(
+ &RunTwoClosures, &drop_all_caps_callback, post_fork_parent_callback);
+ CHECK(CreateInitProcessReaper(&callback));
}
}