| Index: content/zygote/zygote_linux.cc
|
| diff --git a/content/zygote/zygote_linux.cc b/content/zygote/zygote_linux.cc
|
| index 8ac4a61d64e714920e501f28bf21736f625b6ced..e0dbbf7fa8f21629a08baa4b42397795d4d1770f 100644
|
| --- a/content/zygote/zygote_linux.cc
|
| +++ b/content/zygote/zygote_linux.cc
|
| @@ -36,6 +36,7 @@
|
| #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"
|
|
|
| #if defined(ADDRESS_SANITIZER)
|
| #include <sanitizer/asan_interface.h>
|
| @@ -51,6 +52,20 @@ 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;
|
| +
|
| +void TerminationSignalHandler(int signal) {
|
| + // Return a special exit code so that the process is detected as terminated by
|
| + // a signal. We cannot terminate ourself with a signal since we may be the
|
| + // init process in a PID namespace.
|
| + _exit(kKilledExitCode);
|
| +}
|
| +
|
| 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)
|
| @@ -274,12 +289,10 @@ bool Zygote::GetTerminationStatus(base::ProcessHandle real_pid,
|
| bool known_dead,
|
| base::TerminationStatus* status,
|
| int* exit_code) {
|
| -
|
| ZygoteProcessInfo child_info;
|
| if (!GetProcessInfo(real_pid, &child_info)) {
|
| - LOG(ERROR) << "Zygote::GetTerminationStatus for unknown PID "
|
| + LOG(FATAL) << "Zygote::GetTerminationStatus for unknown PID "
|
| << real_pid;
|
| - NOTREACHED();
|
| return false;
|
| }
|
| // We know about |real_pid|.
|
| @@ -304,6 +317,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;
|
| }
|
|
|
| @@ -374,12 +392,27 @@ 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);
|
| + int clone_flags = SIGCHLD;
|
| + if (sandbox_flags_ & kSandboxLinuxPIDNS &&
|
| + sandbox_flags_ & kSandboxLinuxUserNS) {
|
| + clone_flags |= CLONE_NEWPID;
|
| + }
|
| + pid = base::ForkWithFlags(clone_flags, nullptr, nullptr);
|
| }
|
|
|
| if (pid == 0) {
|
| + CHECK(sandbox::Credentials::DropAllCapabilities());
|
| +
|
| + // If the process is the init process inside a PID namespace, it must have
|
| + // explicit SIGTERM and SIGINT handlers.
|
| + if (getpid() == 1) {
|
| + struct sigaction action;
|
| + memset(&action, 0, sizeof(action));
|
| + action.sa_handler = &TerminationSignalHandler;
|
| + PCHECK(sigaction(SIGINT, &action, nullptr) == 0);
|
| + PCHECK(sigaction(SIGTERM, &action, nullptr) == 0);
|
| + }
|
| +
|
| // In the child process.
|
| write_pipe.reset();
|
|
|
|
|