diff options
author | rickyz <rickyz@chromium.org> | 2015-04-13 14:41:14 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-13 21:41:57 +0000 |
commit | 3f16f8e52e917af2f33fc6248f12c0c8e9f9a376 (patch) | |
tree | a47201908168a6e10e30157719d86aa754868c0b /content/zygote | |
parent | 2936dd47b92f0e1281c181f18ebae2921585fe5c (diff) | |
download | chromium_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.cc | 44 | ||||
-rw-r--r-- | content/zygote/zygote_main_linux.cc | 16 |
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)); } } |