Index: content/zygote/zygote_linux.cc |
diff --git a/content/zygote/zygote_linux.cc b/content/zygote/zygote_linux.cc |
index 63c472fa7e7167340fafbc21a1ce135e605f2162..62b16b011299624e92c7a17235affb97281a1fcc 100644 |
--- a/content/zygote/zygote_linux.cc |
+++ b/content/zygote/zygote_linux.cc |
@@ -83,10 +83,10 @@ bool Zygote::ProcessRequests() { |
if (UsingSUIDSandbox()) { |
// Let the ZygoteHost know we are ready to go. |
// The receiving code is in content/browser/zygote_host_linux.cc. |
- std::vector<int> empty; |
bool r = UnixDomainSocket::SendMsg(kZygoteSocketPairFd, |
kZygoteHelloMessage, |
- sizeof(kZygoteHelloMessage), empty); |
+ sizeof(kZygoteHelloMessage), |
+ std::vector<int>()); |
#if defined(OS_CHROMEOS) |
LOG_IF(WARNING, !r) << "Sending zygote magic failed"; |
// Exit normally on chromeos because session manager may send SIGTERM |
@@ -304,56 +304,42 @@ int Zygote::ForkWithRealPid(const std::string& process_type, |
uma_name, |
uma_sample, |
uma_boundary_value)); |
- int dummy_fd; |
- ino_t dummy_inode; |
- int pipe_fds[2] = { -1, -1 }; |
- base::ProcessId pid = 0; |
- |
- dummy_fd = socket(PF_UNIX, SOCK_DGRAM, 0); |
- if (dummy_fd < 0) { |
- LOG(ERROR) << "Failed to create dummy FD"; |
- goto error; |
- } |
- if (!base::FileDescriptorGetInode(&dummy_inode, dummy_fd)) { |
- LOG(ERROR) << "Failed to get inode for dummy FD"; |
- goto error; |
- } |
+ |
+ int pipe_fds[2] = {-1, -1}; |
if (pipe(pipe_fds) != 0) { |
LOG(ERROR) << "Failed to create pipe"; |
- goto error; |
+ return -1; |
} |
+ base::ScopedFD read_pipe(pipe_fds[0]); |
+ base::ScopedFD write_pipe(pipe_fds[1]); |
+ base::ProcessId pid = -1; |
if (use_helper) { |
std::vector<int> fds; |
int ipc_channel_fd = LookUpFd(fd_mapping, kPrimaryIPCChannel); |
if (ipc_channel_fd < 0) { |
DLOG(ERROR) << "Failed to find kPrimaryIPCChannel in FD mapping"; |
- goto error; |
+ return -1; |
} |
fds.push_back(ipc_channel_fd); // kBrowserFDIndex |
- fds.push_back(dummy_fd); // kDummyFDIndex |
- fds.push_back(pipe_fds[0]); // kParentFDIndex |
+ fds.push_back(write_pipe.get()); // kParentFDIndex |
pid = helper_->Fork(process_type, fds, channel_id); |
} else { |
pid = fork(); |
} |
if (pid < 0) { |
- goto error; |
- } else if (pid == 0) { |
+ return -1; |
+ } |
+ if (pid == 0) { |
// In the child process. |
- close(pipe_fds[1]); |
+ read_pipe.reset(); |
+ |
base::ProcessId real_pid; |
- // Wait until the parent process has discovered our PID. We |
- // should not fork any child processes (which the seccomp |
- // sandbox does) until then, because that can interfere with the |
- // parent's discovery of our PID. |
- if (!base::ReadFromFD(pipe_fds[0], reinterpret_cast<char*>(&real_pid), |
- sizeof(real_pid))) { |
- LOG(FATAL) << "Failed to synchronise with parent zygote process"; |
- } |
- if (real_pid <= 0) { |
- LOG(FATAL) << "Invalid pid from parent zygote"; |
+ if (!SendRealPidToZygote(write_pipe.get(), &real_pid)) { |
+ LOG(FATAL) << "Failed to synchronise with parent process"; |
} |
+ write_pipe.reset(); |
+ |
#if defined(OS_LINUX) |
// Sandboxed processes need to send the global, non-namespaced PID when |
// setting up an IPC channel to their parent. |
@@ -363,78 +349,33 @@ int Zygote::ForkWithRealPid(const std::string& process_type, |
base::debug::TraceLog::GetInstance()->SetProcessID( |
static_cast<int>(real_pid)); |
#endif |
- close(pipe_fds[0]); |
- close(dummy_fd); |
return 0; |
- } else { |
- // In the parent process. |
- close(dummy_fd); |
- dummy_fd = -1; |
- close(pipe_fds[0]); |
- pipe_fds[0] = -1; |
- base::ProcessId real_pid; |
- if (UsingSUIDSandbox()) { |
- uint8_t reply_buf[512]; |
- Pickle request; |
- request.WriteInt(LinuxSandbox::METHOD_GET_CHILD_WITH_INODE); |
- request.WriteUInt64(dummy_inode); |
- |
- const ssize_t r = UnixDomainSocket::SendRecvMsg( |
- GetSandboxFD(), reply_buf, sizeof(reply_buf), NULL, |
- request); |
- if (r == -1) { |
- LOG(ERROR) << "Failed to get child process's real PID"; |
- goto error; |
- } |
- |
- Pickle reply(reinterpret_cast<char*>(reply_buf), r); |
- PickleIterator iter(reply); |
- if (!reply.ReadInt(&iter, &real_pid)) |
- goto error; |
- if (real_pid <= 0) { |
- // METHOD_GET_CHILD_WITH_INODE failed. Did the child die already? |
- LOG(ERROR) << "METHOD_GET_CHILD_WITH_INODE failed"; |
- goto error; |
- } |
- } else { |
- // If no SUID sandbox is involved then no pid translation is |
- // necessary. |
- real_pid = pid; |
- } |
- |
- // Now set-up this process to be tracked by the Zygote. |
- if (process_info_map_.find(real_pid) != process_info_map_.end()) { |
- LOG(ERROR) << "Already tracking PID " << real_pid; |
- NOTREACHED(); |
- } |
- process_info_map_[real_pid].internal_pid = pid; |
- process_info_map_[real_pid].started_from_helper = use_helper; |
- |
- // If we're using a helper, we still need to let the child process know |
- // we've discovered its real PID, but we don't actually reveal the PID. |
- const base::ProcessId pid_for_child = use_helper ? 0 : real_pid; |
- ssize_t written = |
- HANDLE_EINTR(write(pipe_fds[1], &pid_for_child, sizeof(pid_for_child))); |
- if (written != sizeof(pid_for_child)) { |
- LOG(ERROR) << "Failed to synchronise with child process"; |
- goto error; |
- } |
- close(pipe_fds[1]); |
- return real_pid; |
} |
- error: |
- if (pid > 0) { |
+ // In the parent process. |
+ write_pipe.reset(); |
+ |
+ base::ProcessId real_pid; |
+ if (!base::ReadFromFD(read_pipe.get(), |
+ reinterpret_cast<char*>(&real_pid), |
+ sizeof(real_pid))) { |
+ LOG(ERROR) << "Failed to synchronise with child process"; |
+ // TODO(mdempsky): Dispatch to helper |
if (waitpid(pid, NULL, WNOHANG) == -1) |
LOG(ERROR) << "Failed to wait for process"; |
+ return -1; |
} |
- if (dummy_fd >= 0) |
- close(dummy_fd); |
- if (pipe_fds[0] >= 0) |
- close(pipe_fds[0]); |
- if (pipe_fds[1] >= 0) |
- close(pipe_fds[1]); |
- return -1; |
+ read_pipe.reset(); |
+ |
+ // Now set-up this process to be tracked by the Zygote. |
+ if (process_info_map_.find(real_pid) != process_info_map_.end()) { |
+ LOG(ERROR) << "Already tracking PID " << real_pid; |
+ NOTREACHED(); |
+ } |
+ process_info_map_[real_pid].internal_pid = pid; |
+ process_info_map_[real_pid].started_from_helper = use_helper; |
+ |
+ return real_pid; |
} |
base::ProcessId Zygote::ReadArgsAndFork(const Pickle& pickle, |
@@ -489,8 +430,6 @@ base::ProcessId Zygote::ReadArgsAndFork(const Pickle& pickle, |
// This is the child process. |
close(kZygoteSocketPairFd); // Our socket from the browser. |
- if (UsingSUIDSandbox()) |
- close(kZygoteIdFd); // Another socket from the browser. |
base::GlobalDescriptors::GetInstance()->Reset(mapping); |
// Reset the process-wide command line to our new command line. |