| 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.
|
|
|