| Index: content/zygote/zygote_main_linux.cc
|
| diff --git a/content/zygote/zygote_main_linux.cc b/content/zygote/zygote_main_linux.cc
|
| index 7a79ab3f2c76f4940be1aff5133046fbace668c0..93ab269b3a6fff8a60a40a9d7d0a7b4e2a66fccd 100644
|
| --- a/content/zygote/zygote_main_linux.cc
|
| +++ b/content/zygote/zygote_main_linux.cc
|
| @@ -15,6 +15,8 @@
|
| #include <unistd.h>
|
|
|
| #include "base/basictypes.h"
|
| +#include "base/bind.h"
|
| +#include "base/callback.h"
|
| #include "base/command_line.h"
|
| #include "base/linux_util.h"
|
| #include "base/native_library.h"
|
| @@ -308,80 +310,8 @@ static void PreSandboxInit() {
|
| new FontConfigIPC(GetSandboxFD()))->unref();
|
| }
|
|
|
| -// Do nothing here
|
| -static void SIGCHLDHandler(int signal) {
|
| -}
|
| -
|
| -// The current process will become a process reaper like init.
|
| -// We fork a child that will continue normally, when it dies, we can safely
|
| -// exit.
|
| -// We need to be careful we close the magic kZygoteIdFd properly in the parent
|
| -// before this function returns.
|
| -static bool CreateInitProcessReaper() {
|
| - int sync_fds[2];
|
| - // We want to use send, so we can't use a pipe
|
| - if (socketpair(AF_UNIX, SOCK_STREAM, 0, sync_fds)) {
|
| - LOG(ERROR) << "Failed to create socketpair";
|
| - return false;
|
| - }
|
| -
|
| - // We use normal fork, not the ForkDelegate in this case since we are not a
|
| - // true Zygote yet.
|
| - pid_t child_pid = fork();
|
| - if (child_pid == -1) {
|
| - (void) HANDLE_EINTR(close(sync_fds[0]));
|
| - (void) HANDLE_EINTR(close(sync_fds[1]));
|
| - return false;
|
| - }
|
| - if (child_pid) {
|
| - // We are the parent, assuming the role of an init process.
|
| - // The disposition for SIGCHLD cannot be SIG_IGN or wait() will only return
|
| - // once all of our childs are dead. Since we're init we need to reap childs
|
| - // as they come.
|
| - struct sigaction action;
|
| - memset(&action, 0, sizeof(action));
|
| - action.sa_handler = &SIGCHLDHandler;
|
| - CHECK(sigaction(SIGCHLD, &action, NULL) == 0);
|
| -
|
| - (void) HANDLE_EINTR(close(sync_fds[0]));
|
| - shutdown(sync_fds[1], SHUT_RD);
|
| - // This "magic" socket must only appear in one process.
|
| - (void) HANDLE_EINTR(close(kZygoteIdFd));
|
| - // Tell the child to continue
|
| - CHECK(HANDLE_EINTR(send(sync_fds[1], "C", 1, MSG_NOSIGNAL)) == 1);
|
| - (void) HANDLE_EINTR(close(sync_fds[1]));
|
| -
|
| - for (;;) {
|
| - // Loop until we have reaped our one natural child
|
| - siginfo_t reaped_child_info;
|
| - int wait_ret =
|
| - HANDLE_EINTR(waitid(P_ALL, 0, &reaped_child_info, WEXITED));
|
| - if (wait_ret)
|
| - _exit(1);
|
| - if (reaped_child_info.si_pid == child_pid) {
|
| - int exit_code = 0;
|
| - // We're done waiting
|
| - if (reaped_child_info.si_code == CLD_EXITED) {
|
| - exit_code = reaped_child_info.si_status;
|
| - }
|
| - // Exit with the same exit code as our parent. This is most likely
|
| - // useless. _exit with 0 if we got signaled.
|
| - _exit(exit_code);
|
| - }
|
| - }
|
| - } else {
|
| - // The child needs to wait for the parent to close kZygoteIdFd to avoid a
|
| - // race condition
|
| - (void) HANDLE_EINTR(close(sync_fds[1]));
|
| - shutdown(sync_fds[0], SHUT_WR);
|
| - char should_continue;
|
| - int read_ret = HANDLE_EINTR(read(sync_fds[0], &should_continue, 1));
|
| - (void) HANDLE_EINTR(close(sync_fds[0]));
|
| - if (read_ret == 1)
|
| - return true;
|
| - else
|
| - return false;
|
| - }
|
| +static void CloseFdAndHandleEintr(int fd) {
|
| + (void) HANDLE_EINTR(close(fd));
|
| }
|
|
|
| // This will set the *using_suid_sandbox variable to true if the SUID sandbox
|
| @@ -421,7 +351,13 @@ static bool EnterSuidSandbox(LinuxSandbox* linux_sandbox,
|
| if (getpid() == 1) {
|
| // The setuid sandbox has created a new PID namespace and we need
|
| // to assume the role of init.
|
| - if (!CreateInitProcessReaper()) {
|
| + // This "magic" socket must only appear in one process, so make sure
|
| + // it gets closed in the parent after fork().
|
| + base::Closure zygoteid_fd_closer =
|
| + base::Bind(CloseFdAndHandleEintr, kZygoteIdFd);
|
| + const bool init_created =
|
| + setuid_sandbox->CreateInitProcessReaper(&zygoteid_fd_closer);
|
| + if (!init_created) {
|
| LOG(ERROR) << "Error creating an init process to reap zombies";
|
| return false;
|
| }
|
|
|