Home | History | Annotate | Download | only in zygote
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/zygote/zygote_linux.h"
      6 
      7 #include <fcntl.h>
      8 #include <string.h>
      9 #include <sys/socket.h>
     10 #include <sys/types.h>
     11 #include <sys/wait.h>
     12 
     13 #include "base/command_line.h"
     14 #include "base/debug/trace_event.h"
     15 #include "base/file_util.h"
     16 #include "base/linux_util.h"
     17 #include "base/logging.h"
     18 #include "base/macros.h"
     19 #include "base/memory/scoped_vector.h"
     20 #include "base/pickle.h"
     21 #include "base/posix/eintr_wrapper.h"
     22 #include "base/posix/global_descriptors.h"
     23 #include "base/posix/unix_domain_socket_linux.h"
     24 #include "base/process/kill.h"
     25 #include "content/common/child_process_sandbox_support_impl_linux.h"
     26 #include "content/common/sandbox_linux/sandbox_linux.h"
     27 #include "content/common/set_process_title.h"
     28 #include "content/common/zygote_commands_linux.h"
     29 #include "content/public/common/content_descriptors.h"
     30 #include "content/public/common/result_codes.h"
     31 #include "content/public/common/sandbox_linux.h"
     32 #include "content/public/common/zygote_fork_delegate_linux.h"
     33 #include "ipc/ipc_channel.h"
     34 #include "ipc/ipc_switches.h"
     35 
     36 #if defined(ADDRESS_SANITIZER)
     37 #include <sanitizer/asan_interface.h>
     38 #endif
     39 
     40 // See http://code.google.com/p/chromium/wiki/LinuxZygote
     41 
     42 namespace content {
     43 
     44 namespace {
     45 
     46 // NOP function. See below where this handler is installed.
     47 void SIGCHLDHandler(int signal) {
     48 }
     49 
     50 int LookUpFd(const base::GlobalDescriptors::Mapping& fd_mapping, uint32_t key) {
     51   for (size_t index = 0; index < fd_mapping.size(); ++index) {
     52     if (fd_mapping[index].first == key)
     53       return fd_mapping[index].second;
     54   }
     55   return -1;
     56 }
     57 
     58 void CreatePipe(base::ScopedFD* read_pipe, base::ScopedFD* write_pipe) {
     59   int raw_pipe[2];
     60   PCHECK(0 == pipe(raw_pipe));
     61   read_pipe->reset(raw_pipe[0]);
     62   write_pipe->reset(raw_pipe[1]);
     63 }
     64 
     65 void KillAndReap(pid_t pid, ZygoteForkDelegate* helper) {
     66   if (helper) {
     67     // Helper children may be forked in another PID namespace, so |pid| might
     68     // be meaningless to us; or we just might not be able to directly send it
     69     // signals.  So we can't kill it.
     70     // Additionally, we're not its parent, so we can't reap it anyway.
     71     // TODO(mdempsky): Extend the ZygoteForkDelegate API to handle this.
     72     LOG(WARNING) << "Unable to kill or reap helper children";
     73     return;
     74   }
     75 
     76   // Kill the child process in case it's not already dead, so we can safely
     77   // perform a blocking wait.
     78   PCHECK(0 == kill(pid, SIGKILL));
     79   PCHECK(pid == HANDLE_EINTR(waitpid(pid, NULL, 0)));
     80 }
     81 
     82 }  // namespace
     83 
     84 Zygote::Zygote(int sandbox_flags, ScopedVector<ZygoteForkDelegate> helpers,
     85                const std::vector<base::ProcessHandle>& extra_children,
     86                const std::vector<int>& extra_fds)
     87     : sandbox_flags_(sandbox_flags),
     88       helpers_(helpers.Pass()),
     89       initial_uma_index_(0),
     90       extra_children_(extra_children),
     91       extra_fds_(extra_fds) {}
     92 
     93 Zygote::~Zygote() {
     94 }
     95 
     96 bool Zygote::ProcessRequests() {
     97   // A SOCK_SEQPACKET socket is installed in fd 3. We get commands from the
     98   // browser on it.
     99   // A SOCK_DGRAM is installed in fd 5. This is the sandbox IPC channel.
    100   // See http://code.google.com/p/chromium/wiki/LinuxSandboxIPC
    101 
    102   // We need to accept SIGCHLD, even though our handler is a no-op because
    103   // otherwise we cannot wait on children. (According to POSIX 2001.)
    104   struct sigaction action;
    105   memset(&action, 0, sizeof(action));
    106   action.sa_handler = &SIGCHLDHandler;
    107   CHECK(sigaction(SIGCHLD, &action, NULL) == 0);
    108 
    109   if (UsingSUIDSandbox()) {
    110     // Let the ZygoteHost know we are ready to go.
    111     // The receiving code is in content/browser/zygote_host_linux.cc.
    112     bool r = UnixDomainSocket::SendMsg(kZygoteSocketPairFd,
    113                                        kZygoteHelloMessage,
    114                                        sizeof(kZygoteHelloMessage),
    115                                        std::vector<int>());
    116 #if defined(OS_CHROMEOS)
    117     LOG_IF(WARNING, !r) << "Sending zygote magic failed";
    118     // Exit normally on chromeos because session manager may send SIGTERM
    119     // right after the process starts and it may fail to send zygote magic
    120     // number to browser process.
    121     if (!r)
    122       _exit(RESULT_CODE_NORMAL_EXIT);
    123 #else
    124     CHECK(r) << "Sending zygote magic failed";
    125 #endif
    126   }
    127 
    128   for (;;) {
    129     // This function call can return multiple times, once per fork().
    130     if (HandleRequestFromBrowser(kZygoteSocketPairFd))
    131       return true;
    132   }
    133 }
    134 
    135 bool Zygote::GetProcessInfo(base::ProcessHandle pid,
    136                             ZygoteProcessInfo* process_info) {
    137   DCHECK(process_info);
    138   const ZygoteProcessMap::const_iterator it = process_info_map_.find(pid);
    139   if (it == process_info_map_.end()) {
    140     return false;
    141   }
    142   *process_info = it->second;
    143   return true;
    144 }
    145 
    146 bool Zygote::UsingSUIDSandbox() const {
    147   return sandbox_flags_ & kSandboxLinuxSUID;
    148 }
    149 
    150 bool Zygote::HandleRequestFromBrowser(int fd) {
    151   ScopedVector<base::ScopedFD> fds;
    152   char buf[kZygoteMaxMessageLength];
    153   const ssize_t len = UnixDomainSocket::RecvMsg(fd, buf, sizeof(buf), &fds);
    154 
    155   if (len == 0 || (len == -1 && errno == ECONNRESET)) {
    156     // EOF from the browser. We should die.
    157     // TODO(earthdok): call __sanititizer_cov_dump() here to obtain code
    158     // coverage  for the Zygote. Currently it's not possible because of
    159     // confusion over who is responsible for closing the file descriptor.
    160     for (std::vector<int>::iterator it = extra_fds_.begin();
    161          it < extra_fds_.end(); ++it) {
    162       PCHECK(0 == IGNORE_EINTR(close(*it)));
    163     }
    164 #if !defined(ADDRESS_SANITIZER)
    165     // TODO(earthdok): add watchdog thread before using this in non-ASAN builds.
    166     CHECK(extra_children_.empty());
    167 #endif
    168     for (std::vector<base::ProcessHandle>::iterator it =
    169              extra_children_.begin();
    170          it < extra_children_.end(); ++it) {
    171       PCHECK(*it == HANDLE_EINTR(waitpid(*it, NULL, 0)));
    172     }
    173     _exit(0);
    174     return false;
    175   }
    176 
    177   if (len == -1) {
    178     PLOG(ERROR) << "Error reading message from browser";
    179     return false;
    180   }
    181 
    182   Pickle pickle(buf, len);
    183   PickleIterator iter(pickle);
    184 
    185   int kind;
    186   if (pickle.ReadInt(&iter, &kind)) {
    187     switch (kind) {
    188       case kZygoteCommandFork:
    189         // This function call can return multiple times, once per fork().
    190         return HandleForkRequest(fd, pickle, iter, fds.Pass());
    191 
    192       case kZygoteCommandReap:
    193         if (!fds.empty())
    194           break;
    195         HandleReapRequest(fd, pickle, iter);
    196         return false;
    197       case kZygoteCommandGetTerminationStatus:
    198         if (!fds.empty())
    199           break;
    200         HandleGetTerminationStatus(fd, pickle, iter);
    201         return false;
    202       case kZygoteCommandGetSandboxStatus:
    203         HandleGetSandboxStatus(fd, pickle, iter);
    204         return false;
    205       case kZygoteCommandForkRealPID:
    206         // This shouldn't happen in practice, but some failure paths in
    207         // HandleForkRequest (e.g., if ReadArgsAndFork fails during depickling)
    208         // could leave this command pending on the socket.
    209         LOG(ERROR) << "Unexpected real PID message from browser";
    210         NOTREACHED();
    211         return false;
    212       default:
    213         NOTREACHED();
    214         break;
    215     }
    216   }
    217 
    218   LOG(WARNING) << "Error parsing message from browser";
    219   return false;
    220 }
    221 
    222 // TODO(jln): remove callers to this broken API. See crbug.com/274855.
    223 void Zygote::HandleReapRequest(int fd,
    224                                const Pickle& pickle,
    225                                PickleIterator iter) {
    226   base::ProcessId child;
    227 
    228   if (!pickle.ReadInt(&iter, &child)) {
    229     LOG(WARNING) << "Error parsing reap request from browser";
    230     return;
    231   }
    232 
    233   ZygoteProcessInfo child_info;
    234   if (!GetProcessInfo(child, &child_info)) {
    235     LOG(ERROR) << "Child not found!";
    236     NOTREACHED();
    237     return;
    238   }
    239 
    240   if (!child_info.started_from_helper) {
    241     // Do not call base::EnsureProcessTerminated() under ThreadSanitizer, as it
    242     // spawns a separate thread which may live until the call to fork() in the
    243     // zygote. As a result, ThreadSanitizer will report an error and almost
    244     // disable race detection in the child process.
    245     // Not calling EnsureProcessTerminated() may result in zombie processes
    246     // sticking around. This will only happen during testing, so we can live
    247     // with this for now.
    248 #if !defined(THREAD_SANITIZER)
    249     // TODO(jln): this old code is completely broken. See crbug.com/274855.
    250     base::EnsureProcessTerminated(child_info.internal_pid);
    251 #else
    252     LOG(WARNING) << "Zygote process omitting a call to "
    253         << "base::EnsureProcessTerminated() for child pid " << child
    254         << " under ThreadSanitizer. See http://crbug.com/274855.";
    255 #endif
    256   } else {
    257     // For processes from the helper, send a GetTerminationStatus request
    258     // with known_dead set to true.
    259     // This is not perfect, as the process may be killed instantly, but is
    260     // better than ignoring the request.
    261     base::TerminationStatus status;
    262     int exit_code;
    263     bool got_termination_status =
    264         GetTerminationStatus(child, true /* known_dead */, &status, &exit_code);
    265     DCHECK(got_termination_status);
    266   }
    267   process_info_map_.erase(child);
    268 }
    269 
    270 bool Zygote::GetTerminationStatus(base::ProcessHandle real_pid,
    271                                   bool known_dead,
    272                                   base::TerminationStatus* status,
    273                                   int* exit_code) {
    274 
    275   ZygoteProcessInfo child_info;
    276   if (!GetProcessInfo(real_pid, &child_info)) {
    277     LOG(ERROR) << "Zygote::GetTerminationStatus for unknown PID "
    278                << real_pid;
    279     NOTREACHED();
    280     return false;
    281   }
    282   // We know about |real_pid|.
    283   const base::ProcessHandle child = child_info.internal_pid;
    284   if (child_info.started_from_helper) {
    285     if (!child_info.started_from_helper->GetTerminationStatus(
    286             child, known_dead, status, exit_code)) {
    287       return false;
    288     }
    289   } else {
    290     // Handle the request directly.
    291     if (known_dead) {
    292       *status = base::GetKnownDeadTerminationStatus(child, exit_code);
    293     } else {
    294       // We don't know if the process is dying, so get its status but don't
    295       // wait.
    296       *status = base::GetTerminationStatus(child, exit_code);
    297     }
    298   }
    299   // Successfully got a status for |real_pid|.
    300   if (*status != base::TERMINATION_STATUS_STILL_RUNNING) {
    301     // Time to forget about this process.
    302     process_info_map_.erase(real_pid);
    303   }
    304   return true;
    305 }
    306 
    307 void Zygote::HandleGetTerminationStatus(int fd,
    308                                         const Pickle& pickle,
    309                                         PickleIterator iter) {
    310   bool known_dead;
    311   base::ProcessHandle child_requested;
    312 
    313   if (!pickle.ReadBool(&iter, &known_dead) ||
    314       !pickle.ReadInt(&iter, &child_requested)) {
    315     LOG(WARNING) << "Error parsing GetTerminationStatus request "
    316                  << "from browser";
    317     return;
    318   }
    319 
    320   base::TerminationStatus status;
    321   int exit_code;
    322 
    323   bool got_termination_status =
    324       GetTerminationStatus(child_requested, known_dead, &status, &exit_code);
    325   if (!got_termination_status) {
    326     // Assume that if we can't find the child in the sandbox, then
    327     // it terminated normally.
    328     NOTREACHED();
    329     status = base::TERMINATION_STATUS_NORMAL_TERMINATION;
    330     exit_code = RESULT_CODE_NORMAL_EXIT;
    331   }
    332 
    333   Pickle write_pickle;
    334   write_pickle.WriteInt(static_cast<int>(status));
    335   write_pickle.WriteInt(exit_code);
    336   ssize_t written =
    337       HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size()));
    338   if (written != static_cast<ssize_t>(write_pickle.size()))
    339     PLOG(ERROR) << "write";
    340 }
    341 
    342 int Zygote::ForkWithRealPid(const std::string& process_type,
    343                             const base::GlobalDescriptors::Mapping& fd_mapping,
    344                             const std::string& channel_id,
    345                             base::ScopedFD pid_oracle,
    346                             std::string* uma_name,
    347                             int* uma_sample,
    348                             int* uma_boundary_value) {
    349   ZygoteForkDelegate* helper = NULL;
    350   for (ScopedVector<ZygoteForkDelegate>::iterator i = helpers_.begin();
    351        i != helpers_.end();
    352        ++i) {
    353     if ((*i)->CanHelp(process_type, uma_name, uma_sample, uma_boundary_value)) {
    354       helper = *i;
    355       break;
    356     }
    357   }
    358 
    359   base::ScopedFD read_pipe, write_pipe;
    360   base::ProcessId pid = 0;
    361   if (helper) {
    362     int ipc_channel_fd = LookUpFd(fd_mapping, kPrimaryIPCChannel);
    363     if (ipc_channel_fd < 0) {
    364       DLOG(ERROR) << "Failed to find kPrimaryIPCChannel in FD mapping";
    365       return -1;
    366     }
    367     std::vector<int> fds;
    368     fds.push_back(ipc_channel_fd);  // kBrowserFDIndex
    369     fds.push_back(pid_oracle.get());  // kPIDOracleFDIndex
    370     pid = helper->Fork(process_type, fds, channel_id);
    371 
    372     // Helpers should never return in the child process.
    373     CHECK_NE(pid, 0);
    374   } else {
    375     CreatePipe(&read_pipe, &write_pipe);
    376     pid = fork();
    377   }
    378 
    379   if (pid == 0) {
    380     // In the child process.
    381     write_pipe.reset();
    382 
    383     // Ping the PID oracle socket so the browser can find our PID.
    384     CHECK(SendZygoteChildPing(pid_oracle.get()));
    385 
    386     // Now read back our real PID from the zygote.
    387     base::ProcessId real_pid;
    388     if (!base::ReadFromFD(read_pipe.get(),
    389                           reinterpret_cast<char*>(&real_pid),
    390                           sizeof(real_pid))) {
    391       LOG(FATAL) << "Failed to synchronise with parent zygote process";
    392     }
    393     if (real_pid <= 0) {
    394       LOG(FATAL) << "Invalid pid from parent zygote";
    395     }
    396 #if defined(OS_LINUX)
    397     // Sandboxed processes need to send the global, non-namespaced PID when
    398     // setting up an IPC channel to their parent.
    399     IPC::Channel::SetGlobalPid(real_pid);
    400     // Force the real PID so chrome event data have a PID that corresponds
    401     // to system trace event data.
    402     base::debug::TraceLog::GetInstance()->SetProcessID(
    403         static_cast<int>(real_pid));
    404 #endif
    405     return 0;
    406   }
    407 
    408   // In the parent process.
    409   read_pipe.reset();
    410   pid_oracle.reset();
    411 
    412   // Always receive a real PID from the zygote host, though it might
    413   // be invalid (see below).
    414   base::ProcessId real_pid;
    415   {
    416     ScopedVector<base::ScopedFD> recv_fds;
    417     char buf[kZygoteMaxMessageLength];
    418     const ssize_t len = UnixDomainSocket::RecvMsg(
    419         kZygoteSocketPairFd, buf, sizeof(buf), &recv_fds);
    420     CHECK_GT(len, 0);
    421     CHECK(recv_fds.empty());
    422 
    423     Pickle pickle(buf, len);
    424     PickleIterator iter(pickle);
    425 
    426     int kind;
    427     CHECK(pickle.ReadInt(&iter, &kind));
    428     CHECK(kind == kZygoteCommandForkRealPID);
    429     CHECK(pickle.ReadInt(&iter, &real_pid));
    430   }
    431 
    432   // Fork failed.
    433   if (pid < 0) {
    434     return -1;
    435   }
    436 
    437   // If we successfully forked a child, but it crashed without sending
    438   // a message to the browser, the browser won't have found its PID.
    439   if (real_pid < 0) {
    440     KillAndReap(pid, helper);
    441     return -1;
    442   }
    443 
    444   // If we're not using a helper, send the PID back to the child process.
    445   if (!helper) {
    446     ssize_t written =
    447         HANDLE_EINTR(write(write_pipe.get(), &real_pid, sizeof(real_pid)));
    448     if (written != sizeof(real_pid)) {
    449       KillAndReap(pid, helper);
    450       return -1;
    451     }
    452   }
    453 
    454   // Now set-up this process to be tracked by the Zygote.
    455   if (process_info_map_.find(real_pid) != process_info_map_.end()) {
    456     LOG(ERROR) << "Already tracking PID " << real_pid;
    457     NOTREACHED();
    458   }
    459   process_info_map_[real_pid].internal_pid = pid;
    460   process_info_map_[real_pid].started_from_helper = helper;
    461 
    462   return real_pid;
    463 }
    464 
    465 base::ProcessId Zygote::ReadArgsAndFork(const Pickle& pickle,
    466                                         PickleIterator iter,
    467                                         ScopedVector<base::ScopedFD> fds,
    468                                         std::string* uma_name,
    469                                         int* uma_sample,
    470                                         int* uma_boundary_value) {
    471   std::vector<std::string> args;
    472   int argc = 0;
    473   int numfds = 0;
    474   base::GlobalDescriptors::Mapping mapping;
    475   std::string process_type;
    476   std::string channel_id;
    477   const std::string channel_id_prefix = std::string("--")
    478       + switches::kProcessChannelID + std::string("=");
    479 
    480   if (!pickle.ReadString(&iter, &process_type))
    481     return -1;
    482   if (!pickle.ReadInt(&iter, &argc))
    483     return -1;
    484 
    485   for (int i = 0; i < argc; ++i) {
    486     std::string arg;
    487     if (!pickle.ReadString(&iter, &arg))
    488       return -1;
    489     args.push_back(arg);
    490     if (arg.compare(0, channel_id_prefix.length(), channel_id_prefix) == 0)
    491       channel_id = arg.substr(channel_id_prefix.length());
    492   }
    493 
    494   if (!pickle.ReadInt(&iter, &numfds))
    495     return -1;
    496   if (numfds != static_cast<int>(fds.size()))
    497     return -1;
    498 
    499   // First FD is the PID oracle socket.
    500   if (fds.size() < 1)
    501     return -1;
    502   base::ScopedFD pid_oracle(fds[0]->Pass());
    503 
    504   // Remaining FDs are for the global descriptor mapping.
    505   for (int i = 1; i < numfds; ++i) {
    506     base::GlobalDescriptors::Key key;
    507     if (!pickle.ReadUInt32(&iter, &key))
    508       return -1;
    509     mapping.push_back(std::make_pair(key, fds[i]->get()));
    510   }
    511 
    512   mapping.push_back(std::make_pair(
    513       static_cast<uint32_t>(kSandboxIPCChannel), GetSandboxFD()));
    514 
    515   // Returns twice, once per process.
    516   base::ProcessId child_pid = ForkWithRealPid(process_type,
    517                                               mapping,
    518                                               channel_id,
    519                                               pid_oracle.Pass(),
    520                                               uma_name,
    521                                               uma_sample,
    522                                               uma_boundary_value);
    523   if (!child_pid) {
    524     // This is the child process.
    525 
    526     // Our socket from the browser.
    527     PCHECK(0 == IGNORE_EINTR(close(kZygoteSocketPairFd)));
    528 
    529     // Pass ownership of file descriptors from fds to GlobalDescriptors.
    530     for (ScopedVector<base::ScopedFD>::iterator i = fds.begin(); i != fds.end();
    531          ++i)
    532       ignore_result((*i)->release());
    533     base::GlobalDescriptors::GetInstance()->Reset(mapping);
    534 
    535     // Reset the process-wide command line to our new command line.
    536     CommandLine::Reset();
    537     CommandLine::Init(0, NULL);
    538     CommandLine::ForCurrentProcess()->InitFromArgv(args);
    539 
    540     // Update the process title. The argv was already cached by the call to
    541     // SetProcessTitleFromCommandLine in ChromeMain, so we can pass NULL here
    542     // (we don't have the original argv at this point).
    543     SetProcessTitleFromCommandLine(NULL);
    544   } else if (child_pid < 0) {
    545     LOG(ERROR) << "Zygote could not fork: process_type " << process_type
    546         << " numfds " << numfds << " child_pid " << child_pid;
    547   }
    548   return child_pid;
    549 }
    550 
    551 bool Zygote::HandleForkRequest(int fd,
    552                                const Pickle& pickle,
    553                                PickleIterator iter,
    554                                ScopedVector<base::ScopedFD> fds) {
    555   std::string uma_name;
    556   int uma_sample;
    557   int uma_boundary_value;
    558   base::ProcessId child_pid = ReadArgsAndFork(
    559       pickle, iter, fds.Pass(), &uma_name, &uma_sample, &uma_boundary_value);
    560   if (child_pid == 0)
    561     return true;
    562   // If there's no UMA report for this particular fork, then check if any
    563   // helpers have an initial UMA report for us to send instead.
    564   while (uma_name.empty() && initial_uma_index_ < helpers_.size()) {
    565     helpers_[initial_uma_index_++]->InitialUMA(
    566         &uma_name, &uma_sample, &uma_boundary_value);
    567   }
    568   // Must always send reply, as ZygoteHost blocks while waiting for it.
    569   Pickle reply_pickle;
    570   reply_pickle.WriteInt(child_pid);
    571   reply_pickle.WriteString(uma_name);
    572   if (!uma_name.empty()) {
    573     reply_pickle.WriteInt(uma_sample);
    574     reply_pickle.WriteInt(uma_boundary_value);
    575   }
    576   if (HANDLE_EINTR(write(fd, reply_pickle.data(), reply_pickle.size())) !=
    577       static_cast<ssize_t> (reply_pickle.size()))
    578     PLOG(ERROR) << "write";
    579   return false;
    580 }
    581 
    582 bool Zygote::HandleGetSandboxStatus(int fd,
    583                                     const Pickle& pickle,
    584                                     PickleIterator iter) {
    585   if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) !=
    586                    sizeof(sandbox_flags_)) {
    587     PLOG(ERROR) << "write";
    588   }
    589 
    590   return false;
    591 }
    592 
    593 }  // namespace content
    594