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; |
} |