Home | History | Annotate | Download | only in app
      1 // Copyright 2013 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 // For linux_syscall_support.h. This makes it safe to call embedded system
      6 // calls when in seccomp mode.
      7 
      8 #include "components/breakpad/app/breakpad_linux.h"
      9 
     10 #include <fcntl.h>
     11 #include <poll.h>
     12 #include <signal.h>
     13 #include <stdlib.h>
     14 #include <sys/socket.h>
     15 #include <sys/time.h>
     16 #include <sys/types.h>
     17 #include <sys/uio.h>
     18 #include <sys/wait.h>
     19 #include <time.h>
     20 #include <unistd.h>
     21 
     22 #include <algorithm>
     23 #include <string>
     24 
     25 #include "base/base_switches.h"
     26 #include "base/command_line.h"
     27 #include "base/debug/crash_logging.h"
     28 #include "base/files/file_path.h"
     29 #include "base/linux_util.h"
     30 #include "base/path_service.h"
     31 #include "base/platform_file.h"
     32 #include "base/posix/eintr_wrapper.h"
     33 #include "base/posix/global_descriptors.h"
     34 #include "base/process/memory.h"
     35 #include "base/strings/string_util.h"
     36 #include "breakpad/src/client/linux/handler/exception_handler.h"
     37 #include "breakpad/src/client/linux/minidump_writer/directory_reader.h"
     38 #include "breakpad/src/common/linux/linux_libc_support.h"
     39 #include "breakpad/src/common/memory.h"
     40 #include "components/breakpad/app/breakpad_client.h"
     41 #include "components/breakpad/app/breakpad_linux_impl.h"
     42 #include "content/public/common/content_descriptors.h"
     43 
     44 #if defined(OS_ANDROID)
     45 #include <android/log.h>
     46 #include <sys/stat.h>
     47 
     48 #include "base/android/build_info.h"
     49 #include "base/android/path_utils.h"
     50 #endif
     51 #include "third_party/lss/linux_syscall_support.h"
     52 
     53 #if defined(ADDRESS_SANITIZER)
     54 #include <ucontext.h>  // for getcontext().
     55 #endif
     56 
     57 #if defined(OS_ANDROID)
     58 #define STAT_STRUCT struct stat
     59 #define FSTAT_FUNC fstat
     60 #else
     61 #define STAT_STRUCT struct kernel_stat
     62 #define FSTAT_FUNC sys_fstat
     63 #endif
     64 
     65 // Some versions of gcc are prone to warn about unused return values. In cases
     66 // where we either a) know the call cannot fail, or b) there is nothing we
     67 // can do when a call fails, we mark the return code as ignored. This avoids
     68 // spurious compiler warnings.
     69 #define IGNORE_RET(x) do { if (x); } while (0)
     70 
     71 using google_breakpad::ExceptionHandler;
     72 using google_breakpad::MinidumpDescriptor;
     73 
     74 namespace breakpad {
     75 
     76 namespace {
     77 
     78 #if !defined(OS_CHROMEOS)
     79 const char kUploadURL[] = "https://clients2.google.com/cr/report";
     80 #endif
     81 
     82 bool g_is_crash_reporter_enabled = false;
     83 uint64_t g_process_start_time = 0;
     84 pid_t g_pid = 0;
     85 char* g_crash_log_path = NULL;
     86 ExceptionHandler* g_breakpad = NULL;
     87 
     88 #if defined(ADDRESS_SANITIZER)
     89 const char* g_asan_report_str = NULL;
     90 #endif
     91 #if defined(OS_ANDROID)
     92 char* g_process_type = NULL;
     93 #endif
     94 
     95 CrashKeyStorage* g_crash_keys = NULL;
     96 
     97 // Writes the value |v| as 16 hex characters to the memory pointed at by
     98 // |output|.
     99 void write_uint64_hex(char* output, uint64_t v) {
    100   static const char hextable[] = "0123456789abcdef";
    101 
    102   for (int i = 15; i >= 0; --i) {
    103     output[i] = hextable[v & 15];
    104     v >>= 4;
    105   }
    106 }
    107 
    108 // The following helper functions are for calculating uptime.
    109 
    110 // Converts a struct timeval to milliseconds.
    111 uint64_t timeval_to_ms(struct timeval *tv) {
    112   uint64_t ret = tv->tv_sec;  // Avoid overflow by explicitly using a uint64_t.
    113   ret *= 1000;
    114   ret += tv->tv_usec / 1000;
    115   return ret;
    116 }
    117 
    118 // Converts a struct timeval to milliseconds.
    119 uint64_t kernel_timeval_to_ms(struct kernel_timeval *tv) {
    120   uint64_t ret = tv->tv_sec;  // Avoid overflow by explicitly using a uint64_t.
    121   ret *= 1000;
    122   ret += tv->tv_usec / 1000;
    123   return ret;
    124 }
    125 
    126 // String buffer size to use to convert a uint64_t to string.
    127 const size_t kUint64StringSize = 21;
    128 
    129 void SetProcessStartTime() {
    130   // Set the base process start time value.
    131   struct timeval tv;
    132   if (!gettimeofday(&tv, NULL))
    133     g_process_start_time = timeval_to_ms(&tv);
    134   else
    135     g_process_start_time = 0;
    136 }
    137 
    138 // uint64_t version of my_int_len() from
    139 // breakpad/src/common/linux/linux_libc_support.h. Return the length of the
    140 // given, non-negative integer when expressed in base 10.
    141 unsigned my_uint64_len(uint64_t i) {
    142   if (!i)
    143     return 1;
    144 
    145   unsigned len = 0;
    146   while (i) {
    147     len++;
    148     i /= 10;
    149   }
    150 
    151   return len;
    152 }
    153 
    154 // uint64_t version of my_uitos() from
    155 // breakpad/src/common/linux/linux_libc_support.h. Convert a non-negative
    156 // integer to a string (not null-terminated).
    157 void my_uint64tos(char* output, uint64_t i, unsigned i_len) {
    158   for (unsigned index = i_len; index; --index, i /= 10)
    159     output[index - 1] = '0' + (i % 10);
    160 }
    161 
    162 #if defined(OS_ANDROID)
    163 char* my_strncpy(char* dst, const char* src, size_t len) {
    164   int i = len;
    165   char* p = dst;
    166   if (!dst || !src)
    167     return dst;
    168   while (i != 0 && *src != '\0') {
    169     *p++ = *src++;
    170     i--;
    171   }
    172   while (i != 0) {
    173     *p++ = '\0';
    174     i--;
    175   }
    176   return dst;
    177 }
    178 
    179 char* my_strncat(char *dest, const char* src, size_t len) {
    180   char* ret = dest;
    181   while (*dest)
    182       dest++;
    183   while (len--)
    184     if (!(*dest++ = *src++))
    185       return ret;
    186   *dest = 0;
    187   return ret;
    188 }
    189 #endif
    190 
    191 size_t LengthWithoutTrailingSpaces(const char* str, size_t len) {
    192   while (len > 0 && str[len - 1] == ' ') {
    193     len--;
    194   }
    195   return len;
    196 }
    197 
    198 // Populates the passed in allocated string and its size with the distro of
    199 // the crashing process.
    200 // The passed string is expected to be at least kDistroSize bytes long.
    201 void PopulateDistro(char* distro, size_t* distro_len_param) {
    202   size_t distro_len = std::min(my_strlen(base::g_linux_distro), kDistroSize);
    203   memcpy(distro, base::g_linux_distro, distro_len);
    204   if (distro_len_param)
    205     *distro_len_param = distro_len;
    206 }
    207 
    208 void SetClientIdFromCommandLine(const CommandLine& command_line) {
    209   // Get the guid and linux distro from the command line switch.
    210   std::string switch_value =
    211       command_line.GetSwitchValueASCII(switches::kEnableCrashReporter);
    212   size_t separator = switch_value.find(",");
    213   if (separator != std::string::npos) {
    214     GetBreakpadClient()->SetClientID(switch_value.substr(0, separator));
    215     base::SetLinuxDistro(switch_value.substr(separator + 1));
    216   } else {
    217     GetBreakpadClient()->SetClientID(switch_value);
    218   }
    219 }
    220 
    221 // MIME substrings.
    222 #if defined(OS_CHROMEOS)
    223 const char g_sep[] = ":";
    224 #endif
    225 const char g_rn[] = "\r\n";
    226 const char g_form_data_msg[] = "Content-Disposition: form-data; name=\"";
    227 const char g_quote_msg[] = "\"";
    228 const char g_dashdash_msg[] = "--";
    229 const char g_dump_msg[] = "upload_file_minidump\"; filename=\"dump\"";
    230 #if defined(ADDRESS_SANITIZER)
    231 const char g_log_msg[] = "upload_file_log\"; filename=\"log\"";
    232 #endif
    233 const char g_content_type_msg[] = "Content-Type: application/octet-stream";
    234 
    235 // MimeWriter manages an iovec for writing MIMEs to a file.
    236 class MimeWriter {
    237  public:
    238   static const int kIovCapacity = 30;
    239   static const size_t kMaxCrashChunkSize = 64;
    240 
    241   MimeWriter(int fd, const char* const mime_boundary);
    242   ~MimeWriter();
    243 
    244   // Append boundary.
    245   virtual void AddBoundary();
    246 
    247   // Append end of file boundary.
    248   virtual void AddEnd();
    249 
    250   // Append key/value pair with specified sizes.
    251   virtual void AddPairData(const char* msg_type,
    252                            size_t msg_type_size,
    253                            const char* msg_data,
    254                            size_t msg_data_size);
    255 
    256   // Append key/value pair.
    257   void AddPairString(const char* msg_type,
    258                      const char* msg_data) {
    259     AddPairData(msg_type, my_strlen(msg_type), msg_data, my_strlen(msg_data));
    260   }
    261 
    262   // Append key/value pair, splitting value into chunks no larger than
    263   // |chunk_size|. |chunk_size| cannot be greater than |kMaxCrashChunkSize|.
    264   // The msg_type string will have a counter suffix to distinguish each chunk.
    265   virtual void AddPairDataInChunks(const char* msg_type,
    266                                    size_t msg_type_size,
    267                                    const char* msg_data,
    268                                    size_t msg_data_size,
    269                                    size_t chunk_size,
    270                                    bool strip_trailing_spaces);
    271 
    272   // Add binary file contents to be uploaded with the specified filename.
    273   virtual void AddFileContents(const char* filename_msg,
    274                                uint8_t* file_data,
    275                                size_t file_size);
    276 
    277   // Flush any pending iovecs to the output file.
    278   void Flush() {
    279     IGNORE_RET(sys_writev(fd_, iov_, iov_index_));
    280     iov_index_ = 0;
    281   }
    282 
    283  protected:
    284   void AddItem(const void* base, size_t size);
    285   // Minor performance trade-off for easier-to-maintain code.
    286   void AddString(const char* str) {
    287     AddItem(str, my_strlen(str));
    288   }
    289   void AddItemWithoutTrailingSpaces(const void* base, size_t size);
    290 
    291   struct kernel_iovec iov_[kIovCapacity];
    292   int iov_index_;
    293 
    294   // Output file descriptor.
    295   int fd_;
    296 
    297   const char* const mime_boundary_;
    298 
    299   DISALLOW_COPY_AND_ASSIGN(MimeWriter);
    300 };
    301 
    302 MimeWriter::MimeWriter(int fd, const char* const mime_boundary)
    303     : iov_index_(0),
    304       fd_(fd),
    305       mime_boundary_(mime_boundary) {
    306 }
    307 
    308 MimeWriter::~MimeWriter() {
    309 }
    310 
    311 void MimeWriter::AddBoundary() {
    312   AddString(mime_boundary_);
    313   AddString(g_rn);
    314 }
    315 
    316 void MimeWriter::AddEnd() {
    317   AddString(mime_boundary_);
    318   AddString(g_dashdash_msg);
    319   AddString(g_rn);
    320 }
    321 
    322 void MimeWriter::AddPairData(const char* msg_type,
    323                              size_t msg_type_size,
    324                              const char* msg_data,
    325                              size_t msg_data_size) {
    326   AddString(g_form_data_msg);
    327   AddItem(msg_type, msg_type_size);
    328   AddString(g_quote_msg);
    329   AddString(g_rn);
    330   AddString(g_rn);
    331   AddItem(msg_data, msg_data_size);
    332   AddString(g_rn);
    333 }
    334 
    335 void MimeWriter::AddPairDataInChunks(const char* msg_type,
    336                                      size_t msg_type_size,
    337                                      const char* msg_data,
    338                                      size_t msg_data_size,
    339                                      size_t chunk_size,
    340                                      bool strip_trailing_spaces) {
    341   if (chunk_size > kMaxCrashChunkSize)
    342     return;
    343 
    344   unsigned i = 0;
    345   size_t done = 0, msg_length = msg_data_size;
    346 
    347   while (msg_length) {
    348     char num[kUint64StringSize];
    349     const unsigned num_len = my_uint_len(++i);
    350     my_uitos(num, i, num_len);
    351 
    352     size_t chunk_len = std::min(chunk_size, msg_length);
    353 
    354     AddString(g_form_data_msg);
    355     AddItem(msg_type, msg_type_size);
    356     AddItem(num, num_len);
    357     AddString(g_quote_msg);
    358     AddString(g_rn);
    359     AddString(g_rn);
    360     if (strip_trailing_spaces) {
    361       AddItemWithoutTrailingSpaces(msg_data + done, chunk_len);
    362     } else {
    363       AddItem(msg_data + done, chunk_len);
    364     }
    365     AddString(g_rn);
    366     AddBoundary();
    367     Flush();
    368 
    369     done += chunk_len;
    370     msg_length -= chunk_len;
    371   }
    372 }
    373 
    374 void MimeWriter::AddFileContents(const char* filename_msg, uint8_t* file_data,
    375                                  size_t file_size) {
    376   AddString(g_form_data_msg);
    377   AddString(filename_msg);
    378   AddString(g_rn);
    379   AddString(g_content_type_msg);
    380   AddString(g_rn);
    381   AddString(g_rn);
    382   AddItem(file_data, file_size);
    383   AddString(g_rn);
    384 }
    385 
    386 void MimeWriter::AddItem(const void* base, size_t size) {
    387   // Check if the iovec is full and needs to be flushed to output file.
    388   if (iov_index_ == kIovCapacity) {
    389     Flush();
    390   }
    391   iov_[iov_index_].iov_base = const_cast<void*>(base);
    392   iov_[iov_index_].iov_len = size;
    393   ++iov_index_;
    394 }
    395 
    396 void MimeWriter::AddItemWithoutTrailingSpaces(const void* base, size_t size) {
    397   AddItem(base, LengthWithoutTrailingSpaces(static_cast<const char*>(base),
    398                                             size));
    399 }
    400 
    401 #if defined(OS_CHROMEOS)
    402 // This subclass is used on Chromium OS to report crashes in a format easy for
    403 // the central crash reporting facility to understand.
    404 // Format is <name>:<data length in decimal>:<data>
    405 class CrashReporterWriter : public MimeWriter
    406 {
    407  public:
    408   explicit CrashReporterWriter(int fd);
    409 
    410   virtual void AddBoundary() OVERRIDE;
    411 
    412   virtual void AddEnd() OVERRIDE;
    413 
    414   virtual void AddPairData(const char* msg_type,
    415                            size_t msg_type_size,
    416                           const char* msg_data,
    417                            size_t msg_data_size) OVERRIDE;
    418 
    419   virtual void AddPairDataInChunks(const char* msg_type,
    420                                    size_t msg_type_size,
    421                                    const char* msg_data,
    422                                    size_t msg_data_size,
    423                                    size_t chunk_size,
    424                                    bool strip_trailing_spaces) OVERRIDE;
    425 
    426   virtual void AddFileContents(const char* filename_msg,
    427                                uint8_t* file_data,
    428                                size_t file_size) OVERRIDE;
    429 
    430  private:
    431   DISALLOW_COPY_AND_ASSIGN(CrashReporterWriter);
    432 };
    433 
    434 
    435 CrashReporterWriter::CrashReporterWriter(int fd) : MimeWriter(fd, "") {}
    436 
    437 // No-ops.
    438 void CrashReporterWriter::AddBoundary() {}
    439 void CrashReporterWriter::AddEnd() {}
    440 
    441 void CrashReporterWriter::AddPairData(const char* msg_type,
    442                                       size_t msg_type_size,
    443                                       const char* msg_data,
    444                                       size_t msg_data_size) {
    445   char data[kUint64StringSize];
    446   const unsigned data_len = my_uint_len(msg_data_size);
    447   my_uitos(data, msg_data_size, data_len);
    448 
    449   AddItem(msg_type, msg_type_size);
    450   AddString(g_sep);
    451   AddItem(data, data_len);
    452   AddString(g_sep);
    453   AddItem(msg_data, msg_data_size);
    454   Flush();
    455 }
    456 
    457 void CrashReporterWriter::AddPairDataInChunks(const char* msg_type,
    458                                               size_t msg_type_size,
    459                                               const char* msg_data,
    460                                               size_t msg_data_size,
    461                                               size_t chunk_size,
    462                                               bool strip_trailing_spaces) {
    463   if (chunk_size > kMaxCrashChunkSize)
    464     return;
    465 
    466   unsigned i = 0;
    467   size_t done = 0;
    468   size_t msg_length = msg_data_size;
    469 
    470   while (msg_length) {
    471     char num[kUint64StringSize];
    472     const unsigned num_len = my_uint_len(++i);
    473     my_uitos(num, i, num_len);
    474 
    475     size_t chunk_len = std::min(chunk_size, msg_length);
    476 
    477     size_t write_len = chunk_len;
    478     if (strip_trailing_spaces) {
    479       // Take care of this here because we need to know the exact length of
    480       // what is going to be written.
    481       write_len = LengthWithoutTrailingSpaces(msg_data + done, write_len);
    482     }
    483 
    484     char data[kUint64StringSize];
    485     const unsigned data_len = my_uint_len(write_len);
    486     my_uitos(data, write_len, data_len);
    487 
    488     AddItem(msg_type, msg_type_size);
    489     AddItem(num, num_len);
    490     AddString(g_sep);
    491     AddItem(data, data_len);
    492     AddString(g_sep);
    493     AddItem(msg_data + done, write_len);
    494     Flush();
    495 
    496     done += chunk_len;
    497     msg_length -= chunk_len;
    498   }
    499 }
    500 
    501 void CrashReporterWriter::AddFileContents(const char* filename_msg,
    502                                           uint8_t* file_data,
    503                                           size_t file_size) {
    504   char data[kUint64StringSize];
    505   const unsigned data_len = my_uint_len(file_size);
    506   my_uitos(data, file_size, data_len);
    507 
    508   AddString(filename_msg);
    509   AddString(g_sep);
    510   AddItem(data, data_len);
    511   AddString(g_sep);
    512   AddItem(file_data, file_size);
    513   Flush();
    514 }
    515 #endif
    516 
    517 void DumpProcess() {
    518   if (g_breakpad)
    519     g_breakpad->WriteMinidump();
    520 }
    521 
    522 #if defined(OS_ANDROID)
    523 const char kGoogleBreakpad[] = "google-breakpad";
    524 #endif
    525 
    526 size_t WriteLog(const char* buf, size_t nbytes) {
    527 #if defined(OS_ANDROID)
    528   return __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad, buf);
    529 #else
    530   return sys_write(2, buf, nbytes);
    531 #endif
    532 }
    533 
    534 #if defined(OS_ANDROID)
    535 // Android's native crash handler outputs a diagnostic tombstone to the device
    536 // log. By returning false from the HandlerCallbacks, breakpad will reinstall
    537 // the previous (i.e. native) signal handlers before returning from its own
    538 // handler. A Chrome build fingerprint is written to the log, so that the
    539 // specific build of Chrome and the location of the archived Chrome symbols can
    540 // be determined directly from it.
    541 bool FinalizeCrashDoneAndroid() {
    542   base::android::BuildInfo* android_build_info =
    543       base::android::BuildInfo::GetInstance();
    544 
    545   __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad,
    546                       "### ### ### ### ### ### ### ### ### ### ### ### ###");
    547   __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad,
    548                       "Chrome build fingerprint:");
    549   __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad,
    550                       android_build_info->package_version_name());
    551   __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad,
    552                       android_build_info->package_version_code());
    553   __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad,
    554                       CHROME_BUILD_ID);
    555   __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad,
    556                       "### ### ### ### ### ### ### ### ### ### ### ### ###");
    557   return false;
    558 }
    559 #endif
    560 
    561 bool CrashDone(const MinidumpDescriptor& minidump,
    562                const bool upload,
    563                const bool succeeded) {
    564   // WARNING: this code runs in a compromised context. It may not call into
    565   // libc nor allocate memory normally.
    566   if (!succeeded) {
    567     const char msg[] = "Failed to generate minidump.";
    568     WriteLog(msg, sizeof(msg) - 1);
    569     return false;
    570   }
    571 
    572   DCHECK(!minidump.IsFD());
    573 
    574   BreakpadInfo info = {0};
    575   info.filename = minidump.path();
    576   info.fd = minidump.fd();
    577 #if defined(ADDRESS_SANITIZER)
    578   google_breakpad::PageAllocator allocator;
    579   const size_t log_path_len = my_strlen(minidump.path());
    580   char* log_path = reinterpret_cast<char*>(allocator.Alloc(log_path_len + 1));
    581   my_memcpy(log_path, minidump.path(), log_path_len);
    582   my_memcpy(log_path + log_path_len - 4, ".log", 4);
    583   log_path[log_path_len] = '\0';
    584   info.log_filename = log_path;
    585 #endif
    586   info.process_type = "browser";
    587   info.process_type_length = 7;
    588   info.distro = base::g_linux_distro;
    589   info.distro_length = my_strlen(base::g_linux_distro);
    590   info.upload = upload;
    591   info.process_start_time = g_process_start_time;
    592   info.oom_size = base::g_oom_size;
    593   info.pid = g_pid;
    594   info.crash_keys = g_crash_keys;
    595   HandleCrashDump(info);
    596 #if defined(OS_ANDROID)
    597   return FinalizeCrashDoneAndroid();
    598 #else
    599   return true;
    600 #endif
    601 }
    602 
    603 // Wrapper function, do not add more code here.
    604 bool CrashDoneNoUpload(const MinidumpDescriptor& minidump,
    605                        void* context,
    606                        bool succeeded) {
    607   return CrashDone(minidump, false, succeeded);
    608 }
    609 
    610 #if !defined(OS_ANDROID)
    611 // Wrapper function, do not add more code here.
    612 bool CrashDoneUpload(const MinidumpDescriptor& minidump,
    613                      void* context,
    614                      bool succeeded) {
    615   return CrashDone(minidump, true, succeeded);
    616 }
    617 #endif
    618 
    619 #if defined(ADDRESS_SANITIZER)
    620 extern "C"
    621 void __asan_set_error_report_callback(void (*cb)(const char*));
    622 
    623 extern "C"
    624 void AsanLinuxBreakpadCallback(const char* report) {
    625   g_asan_report_str = report;
    626   // Send minidump here.
    627   g_breakpad->SimulateSignalDelivery(SIGKILL);
    628 }
    629 #endif
    630 
    631 void EnableCrashDumping(bool unattended) {
    632   g_is_crash_reporter_enabled = true;
    633 
    634   base::FilePath tmp_path("/tmp");
    635   PathService::Get(base::DIR_TEMP, &tmp_path);
    636 
    637   base::FilePath dumps_path(tmp_path);
    638   if (GetBreakpadClient()->GetCrashDumpLocation(&dumps_path)) {
    639     base::FilePath logfile =
    640         dumps_path.Append(GetBreakpadClient()->GetReporterLogFilename());
    641     std::string logfile_str = logfile.value();
    642     const size_t crash_log_path_len = logfile_str.size() + 1;
    643     g_crash_log_path = new char[crash_log_path_len];
    644     strncpy(g_crash_log_path, logfile_str.c_str(), crash_log_path_len);
    645   }
    646   DCHECK(!g_breakpad);
    647   MinidumpDescriptor minidump_descriptor(dumps_path.value());
    648   minidump_descriptor.set_size_limit(kMaxMinidumpFileSize);
    649 #if defined(OS_ANDROID)
    650   unattended = true;  // Android never uploads directly.
    651 #endif
    652   if (unattended) {
    653     g_breakpad = new ExceptionHandler(
    654         minidump_descriptor,
    655         NULL,
    656         CrashDoneNoUpload,
    657         NULL,
    658         true,  // Install handlers.
    659         -1);   // Server file descriptor. -1 for in-process.
    660     return;
    661   }
    662 
    663 #if !defined(OS_ANDROID)
    664   // Attended mode
    665   g_breakpad = new ExceptionHandler(
    666       minidump_descriptor,
    667       NULL,
    668       CrashDoneUpload,
    669       NULL,
    670       true,  // Install handlers.
    671       -1);   // Server file descriptor. -1 for in-process.
    672 #endif
    673 }
    674 
    675 #if defined(OS_ANDROID)
    676 bool CrashDoneInProcessNoUpload(
    677     const google_breakpad::MinidumpDescriptor& descriptor,
    678     void* context,
    679     const bool succeeded) {
    680   // WARNING: this code runs in a compromised context. It may not call into
    681   // libc nor allocate memory normally.
    682   if (!succeeded) {
    683     static const char msg[] = "Crash dump generation failed.\n";
    684     WriteLog(msg, sizeof(msg) - 1);
    685     return false;
    686   }
    687 
    688   // Start constructing the message to send to the browser.
    689   char distro[kDistroSize + 1] = {0};
    690   size_t distro_length = 0;
    691   PopulateDistro(distro, &distro_length);
    692   BreakpadInfo info = {0};
    693   info.filename = NULL;
    694   info.fd = descriptor.fd();
    695   info.process_type = g_process_type;
    696   info.process_type_length = my_strlen(g_process_type);
    697   info.distro = distro;
    698   info.distro_length = distro_length;
    699   info.upload = false;
    700   info.process_start_time = g_process_start_time;
    701   info.pid = g_pid;
    702   info.crash_keys = g_crash_keys;
    703   HandleCrashDump(info);
    704   return FinalizeCrashDoneAndroid();
    705 }
    706 
    707 void EnableNonBrowserCrashDumping(const std::string& process_type,
    708                                   int minidump_fd) {
    709   // This will guarantee that the BuildInfo has been initialized and subsequent
    710   // calls will not require memory allocation.
    711   base::android::BuildInfo::GetInstance();
    712   SetClientIdFromCommandLine(*CommandLine::ForCurrentProcess());
    713 
    714   // On Android, the current sandboxing uses process isolation, in which the
    715   // child process runs with a different UID. That breaks the normal crash
    716   // reporting where the browser process generates the minidump by inspecting
    717   // the child process. This is because the browser process now does not have
    718   // the permission to access the states of the child process (as it has a
    719   // different UID).
    720   // TODO(jcivelli): http://b/issue?id=6776356 we should use a watchdog
    721   // process forked from the renderer process that generates the minidump.
    722   if (minidump_fd == -1) {
    723     LOG(ERROR) << "Minidump file descriptor not found, crash reporting will "
    724         " not work.";
    725     return;
    726   }
    727   SetProcessStartTime();
    728   g_pid = getpid();
    729 
    730   g_is_crash_reporter_enabled = true;
    731   // Save the process type (it is leaked).
    732   const size_t process_type_len = process_type.size() + 1;
    733   g_process_type = new char[process_type_len];
    734   strncpy(g_process_type, process_type.c_str(), process_type_len);
    735   new google_breakpad::ExceptionHandler(MinidumpDescriptor(minidump_fd),
    736       NULL, CrashDoneInProcessNoUpload, NULL, true, -1);
    737 }
    738 #else
    739 // Non-Browser = Extension, Gpu, Plugins, Ppapi and Renderer
    740 bool NonBrowserCrashHandler(const void* crash_context,
    741                             size_t crash_context_size,
    742                             void* context) {
    743   const int fd = reinterpret_cast<intptr_t>(context);
    744   int fds[2] = { -1, -1 };
    745   if (sys_socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
    746     static const char msg[] = "Failed to create socket for crash dumping.\n";
    747     WriteLog(msg, sizeof(msg) - 1);
    748     return false;
    749   }
    750 
    751   // Start constructing the message to send to the browser.
    752   char distro[kDistroSize + 1] = {0};
    753   PopulateDistro(distro, NULL);
    754 
    755   char b;  // Dummy variable for sys_read below.
    756   const char* b_addr = &b;  // Get the address of |b| so we can create the
    757                             // expected /proc/[pid]/syscall content in the
    758                             // browser to convert namespace tids.
    759 
    760   // The length of the control message:
    761   static const unsigned kControlMsgSize = sizeof(fds);
    762   static const unsigned kControlMsgSpaceSize = CMSG_SPACE(kControlMsgSize);
    763   static const unsigned kControlMsgLenSize = CMSG_LEN(kControlMsgSize);
    764 
    765   struct kernel_msghdr msg;
    766   my_memset(&msg, 0, sizeof(struct kernel_msghdr));
    767   struct kernel_iovec iov[kCrashIovSize];
    768   iov[0].iov_base = const_cast<void*>(crash_context);
    769   iov[0].iov_len = crash_context_size;
    770   iov[1].iov_base = distro;
    771   iov[1].iov_len = kDistroSize + 1;
    772   iov[2].iov_base = &b_addr;
    773   iov[2].iov_len = sizeof(b_addr);
    774   iov[3].iov_base = &fds[0];
    775   iov[3].iov_len = sizeof(fds[0]);
    776   iov[4].iov_base = &g_process_start_time;
    777   iov[4].iov_len = sizeof(g_process_start_time);
    778   iov[5].iov_base = &base::g_oom_size;
    779   iov[5].iov_len = sizeof(base::g_oom_size);
    780   google_breakpad::SerializedNonAllocatingMap* serialized_map;
    781   iov[6].iov_len = g_crash_keys->Serialize(
    782       const_cast<const google_breakpad::SerializedNonAllocatingMap**>(
    783           &serialized_map));
    784   iov[6].iov_base = serialized_map;
    785 #if defined(ADDRESS_SANITIZER)
    786   iov[7].iov_base = const_cast<char*>(g_asan_report_str);
    787   iov[7].iov_len = kMaxAsanReportSize + 1;
    788 #endif
    789 
    790   msg.msg_iov = iov;
    791   msg.msg_iovlen = kCrashIovSize;
    792   char cmsg[kControlMsgSpaceSize];
    793   my_memset(cmsg, 0, kControlMsgSpaceSize);
    794   msg.msg_control = cmsg;
    795   msg.msg_controllen = sizeof(cmsg);
    796 
    797   struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg);
    798   hdr->cmsg_level = SOL_SOCKET;
    799   hdr->cmsg_type = SCM_RIGHTS;
    800   hdr->cmsg_len = kControlMsgLenSize;
    801   ((int*) CMSG_DATA(hdr))[0] = fds[0];
    802   ((int*) CMSG_DATA(hdr))[1] = fds[1];
    803 
    804   if (HANDLE_EINTR(sys_sendmsg(fd, &msg, 0)) < 0) {
    805     static const char errmsg[] = "Failed to tell parent about crash.\n";
    806     WriteLog(errmsg, sizeof(errmsg) - 1);
    807     IGNORE_RET(sys_close(fds[1]));
    808     return false;
    809   }
    810   IGNORE_RET(sys_close(fds[1]));
    811 
    812   if (HANDLE_EINTR(sys_read(fds[0], &b, 1)) != 1) {
    813     static const char errmsg[] = "Parent failed to complete crash dump.\n";
    814     WriteLog(errmsg, sizeof(errmsg) - 1);
    815   }
    816 
    817   return true;
    818 }
    819 
    820 void EnableNonBrowserCrashDumping() {
    821   const int fd = base::GlobalDescriptors::GetInstance()->Get(kCrashDumpSignal);
    822   g_is_crash_reporter_enabled = true;
    823   // We deliberately leak this object.
    824   DCHECK(!g_breakpad);
    825 
    826   g_breakpad = new ExceptionHandler(
    827       MinidumpDescriptor("/tmp"),  // Unused but needed or Breakpad will assert.
    828       NULL,
    829       NULL,
    830       reinterpret_cast<void*>(fd),  // Param passed to the crash handler.
    831       true,
    832       -1);
    833   g_breakpad->set_crash_handler(NonBrowserCrashHandler);
    834 }
    835 #endif  // defined(OS_ANDROID)
    836 
    837 void SetCrashKeyValue(const base::StringPiece& key,
    838                       const base::StringPiece& value) {
    839   g_crash_keys->SetKeyValue(key.data(), value.data());
    840 }
    841 
    842 void ClearCrashKey(const base::StringPiece& key) {
    843   g_crash_keys->RemoveKey(key.data());
    844 }
    845 
    846 }  // namespace
    847 
    848 void LoadDataFromFD(google_breakpad::PageAllocator& allocator,
    849                     int fd, bool close_fd, uint8_t** file_data, size_t* size) {
    850   STAT_STRUCT st;
    851   if (FSTAT_FUNC(fd, &st) != 0) {
    852     static const char msg[] = "Cannot upload crash dump: stat failed\n";
    853     WriteLog(msg, sizeof(msg) - 1);
    854     if (close_fd)
    855       IGNORE_RET(sys_close(fd));
    856     return;
    857   }
    858 
    859   *file_data = reinterpret_cast<uint8_t*>(allocator.Alloc(st.st_size));
    860   if (!(*file_data)) {
    861     static const char msg[] = "Cannot upload crash dump: cannot alloc\n";
    862     WriteLog(msg, sizeof(msg) - 1);
    863     if (close_fd)
    864       IGNORE_RET(sys_close(fd));
    865     return;
    866   }
    867   my_memset(*file_data, 0xf, st.st_size);
    868 
    869   *size = st.st_size;
    870   int byte_read = sys_read(fd, *file_data, *size);
    871   if (byte_read == -1) {
    872     static const char msg[] = "Cannot upload crash dump: read failed\n";
    873     WriteLog(msg, sizeof(msg) - 1);
    874     if (close_fd)
    875       IGNORE_RET(sys_close(fd));
    876     return;
    877   }
    878 
    879   if (close_fd)
    880     IGNORE_RET(sys_close(fd));
    881 }
    882 
    883 void LoadDataFromFile(google_breakpad::PageAllocator& allocator,
    884                       const char* filename,
    885                       int* fd, uint8_t** file_data, size_t* size) {
    886   // WARNING: this code runs in a compromised context. It may not call into
    887   // libc nor allocate memory normally.
    888   *fd = sys_open(filename, O_RDONLY, 0);
    889   *size = 0;
    890 
    891   if (*fd < 0) {
    892     static const char msg[] = "Cannot upload crash dump: failed to open\n";
    893     WriteLog(msg, sizeof(msg) - 1);
    894     return;
    895   }
    896 
    897   LoadDataFromFD(allocator, *fd, true, file_data, size);
    898 }
    899 
    900 // Spawn the appropriate upload process for the current OS:
    901 // - generic Linux invokes wget.
    902 // - ChromeOS invokes crash_reporter.
    903 // |dumpfile| is the path to the dump data file.
    904 // |mime_boundary| is only used on Linux.
    905 // |exe_buf| is only used on CrOS and is the crashing process' name.
    906 void ExecUploadProcessOrTerminate(const BreakpadInfo& info,
    907                                   const char* dumpfile,
    908                                   const char* mime_boundary,
    909                                   const char* exe_buf,
    910                                   google_breakpad::PageAllocator* allocator) {
    911 #if defined(OS_CHROMEOS)
    912   // CrOS uses crash_reporter instead of wget to report crashes,
    913   // it needs to know where the crash dump lives and the pid and uid of the
    914   // crashing process.
    915   static const char kCrashReporterBinary[] = "/sbin/crash_reporter";
    916 
    917   char pid_buf[kUint64StringSize];
    918   uint64_t pid_str_length = my_uint64_len(info.pid);
    919   my_uint64tos(pid_buf, info.pid, pid_str_length);
    920   pid_buf[pid_str_length] = '\0';
    921 
    922   char uid_buf[kUint64StringSize];
    923   uid_t uid = geteuid();
    924   uint64_t uid_str_length = my_uint64_len(uid);
    925   my_uint64tos(uid_buf, uid, uid_str_length);
    926   uid_buf[uid_str_length] = '\0';
    927   const char* args[] = {
    928     kCrashReporterBinary,
    929     "--chrome",
    930     dumpfile,
    931     "--pid",
    932     pid_buf,
    933     "--uid",
    934     uid_buf,
    935     "--exe",
    936     exe_buf,
    937     NULL,
    938   };
    939   static const char msg[] = "Cannot upload crash dump: cannot exec "
    940                             "/sbin/crash_reporter\n";
    941 #else
    942   // The --header argument to wget looks like:
    943   //   --header=Content-Type: multipart/form-data; boundary=XYZ
    944   // where the boundary has two fewer leading '-' chars
    945   static const char header_msg[] =
    946       "--header=Content-Type: multipart/form-data; boundary=";
    947   char* const header = reinterpret_cast<char*>(allocator->Alloc(
    948       sizeof(header_msg) - 1 + strlen(mime_boundary) - 2 + 1));
    949   memcpy(header, header_msg, sizeof(header_msg) - 1);
    950   memcpy(header + sizeof(header_msg) - 1, mime_boundary + 2,
    951          strlen(mime_boundary) - 2);
    952   // We grab the NUL byte from the end of |mime_boundary|.
    953 
    954   // The --post-file argument to wget looks like:
    955   //   --post-file=/tmp/...
    956   static const char post_file_msg[] = "--post-file=";
    957   char* const post_file = reinterpret_cast<char*>(allocator->Alloc(
    958        sizeof(post_file_msg) - 1 + strlen(dumpfile) + 1));
    959   memcpy(post_file, post_file_msg, sizeof(post_file_msg) - 1);
    960   memcpy(post_file + sizeof(post_file_msg) - 1, dumpfile, strlen(dumpfile));
    961 
    962   static const char kWgetBinary[] = "/usr/bin/wget";
    963   const char* args[] = {
    964     kWgetBinary,
    965     header,
    966     post_file,
    967     kUploadURL,
    968     "--timeout=10",  // Set a timeout so we don't hang forever.
    969     "--tries=1",     // Don't retry if the upload fails.
    970     "-O",  // output reply to fd 3
    971     "/dev/fd/3",
    972     NULL,
    973   };
    974   static const char msg[] = "Cannot upload crash dump: cannot exec "
    975                             "/usr/bin/wget\n";
    976 #endif
    977   execve(args[0], const_cast<char**>(args), environ);
    978   WriteLog(msg, sizeof(msg) - 1);
    979   sys__exit(1);
    980 }
    981 
    982 #if defined(OS_CHROMEOS)
    983 const char* GetCrashingProcessName(const BreakpadInfo& info,
    984                                    google_breakpad::PageAllocator* allocator) {
    985   // Symlink to process binary is at /proc/###/exe.
    986   char linkpath[kUint64StringSize + sizeof("/proc/") + sizeof("/exe")] =
    987     "/proc/";
    988   uint64_t pid_value_len = my_uint64_len(info.pid);
    989   my_uint64tos(linkpath + sizeof("/proc/") - 1, info.pid, pid_value_len);
    990   linkpath[sizeof("/proc/") - 1 + pid_value_len] = '\0';
    991   my_strlcat(linkpath, "/exe", sizeof(linkpath));
    992 
    993   const int kMaxSize = 4096;
    994   char* link = reinterpret_cast<char*>(allocator->Alloc(kMaxSize));
    995   if (link) {
    996     ssize_t size = readlink(linkpath, link, kMaxSize);
    997     if (size < kMaxSize && size > 0) {
    998       // readlink(2) doesn't add a terminating NUL, so do it now.
    999       link[size] = '\0';
   1000 
   1001       const char* name = my_strrchr(link, '/');
   1002       if (name)
   1003         return name + 1;
   1004       return link;
   1005     }
   1006   }
   1007   // Either way too long, or a read error.
   1008   return "chrome-crash-unknown-process";
   1009 }
   1010 #endif
   1011 
   1012 void HandleCrashDump(const BreakpadInfo& info) {
   1013   int dumpfd;
   1014   bool keep_fd = false;
   1015   size_t dump_size;
   1016   uint8_t* dump_data;
   1017   google_breakpad::PageAllocator allocator;
   1018   const char* exe_buf = NULL;
   1019 
   1020 #if defined(OS_CHROMEOS)
   1021   // Grab the crashing process' name now, when it should still be available.
   1022   // If we try to do this later in our grandchild the crashing process has
   1023   // already terminated.
   1024   exe_buf = GetCrashingProcessName(info, &allocator);
   1025 #endif
   1026 
   1027   if (info.fd != -1) {
   1028     // Dump is provided with an open FD.
   1029     keep_fd = true;
   1030     dumpfd = info.fd;
   1031 
   1032     // The FD is pointing to the end of the file.
   1033     // Rewind, we'll read the data next.
   1034     if (lseek(dumpfd, 0, SEEK_SET) == -1) {
   1035       static const char msg[] = "Cannot upload crash dump: failed to "
   1036           "reposition minidump FD\n";
   1037       WriteLog(msg, sizeof(msg) - 1);
   1038       IGNORE_RET(sys_close(dumpfd));
   1039       return;
   1040     }
   1041     LoadDataFromFD(allocator, info.fd, false, &dump_data, &dump_size);
   1042   } else {
   1043     // Dump is provided with a path.
   1044     keep_fd = false;
   1045     LoadDataFromFile(allocator, info.filename, &dumpfd, &dump_data, &dump_size);
   1046   }
   1047 
   1048   // TODO(jcivelli): make log work when using FDs.
   1049 #if defined(ADDRESS_SANITIZER)
   1050   int logfd;
   1051   size_t log_size;
   1052   uint8_t* log_data;
   1053   // Load the AddressSanitizer log into log_data.
   1054   LoadDataFromFile(allocator, info.log_filename, &logfd, &log_data, &log_size);
   1055 #endif
   1056 
   1057   // We need to build a MIME block for uploading to the server. Since we are
   1058   // going to fork and run wget, it needs to be written to a temp file.
   1059   const int ufd = sys_open("/dev/urandom", O_RDONLY, 0);
   1060   if (ufd < 0) {
   1061     static const char msg[] = "Cannot upload crash dump because /dev/urandom"
   1062                               " is missing\n";
   1063     WriteLog(msg, sizeof(msg) - 1);
   1064     return;
   1065   }
   1066 
   1067   static const char temp_file_template[] =
   1068       "/tmp/chromium-upload-XXXXXXXXXXXXXXXX";
   1069   char temp_file[sizeof(temp_file_template)];
   1070   int temp_file_fd = -1;
   1071   if (keep_fd) {
   1072     temp_file_fd = dumpfd;
   1073     // Rewind the destination, we are going to overwrite it.
   1074     if (lseek(dumpfd, 0, SEEK_SET) == -1) {
   1075       static const char msg[] = "Cannot upload crash dump: failed to "
   1076           "reposition minidump FD (2)\n";
   1077       WriteLog(msg, sizeof(msg) - 1);
   1078       IGNORE_RET(sys_close(dumpfd));
   1079       return;
   1080     }
   1081   } else {
   1082     if (info.upload) {
   1083       memcpy(temp_file, temp_file_template, sizeof(temp_file_template));
   1084 
   1085       for (unsigned i = 0; i < 10; ++i) {
   1086         uint64_t t;
   1087         sys_read(ufd, &t, sizeof(t));
   1088         write_uint64_hex(temp_file + sizeof(temp_file) - (16 + 1), t);
   1089 
   1090         temp_file_fd = sys_open(temp_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
   1091         if (temp_file_fd >= 0)
   1092           break;
   1093       }
   1094 
   1095       if (temp_file_fd < 0) {
   1096         static const char msg[] = "Failed to create temporary file in /tmp: "
   1097             "cannot upload crash dump\n";
   1098         WriteLog(msg, sizeof(msg) - 1);
   1099         IGNORE_RET(sys_close(ufd));
   1100         return;
   1101       }
   1102     } else {
   1103       temp_file_fd = sys_open(info.filename, O_WRONLY, 0600);
   1104       if (temp_file_fd < 0) {
   1105         static const char msg[] = "Failed to save crash dump: failed to open\n";
   1106         WriteLog(msg, sizeof(msg) - 1);
   1107         IGNORE_RET(sys_close(ufd));
   1108         return;
   1109       }
   1110     }
   1111   }
   1112 
   1113   // The MIME boundary is 28 hyphens, followed by a 64-bit nonce and a NUL.
   1114   char mime_boundary[28 + 16 + 1];
   1115   my_memset(mime_boundary, '-', 28);
   1116   uint64_t boundary_rand;
   1117   sys_read(ufd, &boundary_rand, sizeof(boundary_rand));
   1118   write_uint64_hex(mime_boundary + 28, boundary_rand);
   1119   mime_boundary[28 + 16] = 0;
   1120   IGNORE_RET(sys_close(ufd));
   1121 
   1122   // The MIME block looks like this:
   1123   //   BOUNDARY \r\n
   1124   //   Content-Disposition: form-data; name="prod" \r\n \r\n
   1125   //   Chrome_Linux \r\n
   1126   //   BOUNDARY \r\n
   1127   //   Content-Disposition: form-data; name="ver" \r\n \r\n
   1128   //   1.2.3.4 \r\n
   1129   //   BOUNDARY \r\n
   1130   //
   1131   //   zero or one:
   1132   //   Content-Disposition: form-data; name="ptime" \r\n \r\n
   1133   //   abcdef \r\n
   1134   //   BOUNDARY \r\n
   1135   //
   1136   //   zero or one:
   1137   //   Content-Disposition: form-data; name="ptype" \r\n \r\n
   1138   //   abcdef \r\n
   1139   //   BOUNDARY \r\n
   1140   //
   1141   //   zero or one:
   1142   //   Content-Disposition: form-data; name="lsb-release" \r\n \r\n
   1143   //   abcdef \r\n
   1144   //   BOUNDARY \r\n
   1145   //
   1146   //   zero or one:
   1147   //   Content-Disposition: form-data; name="oom-size" \r\n \r\n
   1148   //   1234567890 \r\n
   1149   //   BOUNDARY \r\n
   1150   //
   1151   //   zero or more (up to CrashKeyStorage::num_entries = 64):
   1152   //   Content-Disposition: form-data; name=crash-key-name \r\n
   1153   //   crash-key-value \r\n
   1154   //   BOUNDARY \r\n
   1155   //
   1156   //   Content-Disposition: form-data; name="dump"; filename="dump" \r\n
   1157   //   Content-Type: application/octet-stream \r\n \r\n
   1158   //   <dump contents>
   1159   //   \r\n BOUNDARY -- \r\n
   1160 
   1161 #if defined(OS_CHROMEOS)
   1162   CrashReporterWriter writer(temp_file_fd);
   1163 #else
   1164   MimeWriter writer(temp_file_fd, mime_boundary);
   1165 #endif
   1166   {
   1167     std::string product_name;
   1168     std::string version;
   1169 
   1170     GetBreakpadClient()->GetProductNameAndVersion(&product_name, &version);
   1171 
   1172     writer.AddBoundary();
   1173     writer.AddPairString("prod", product_name.c_str());
   1174     writer.AddBoundary();
   1175     writer.AddPairString("ver", version.c_str());
   1176     writer.AddBoundary();
   1177     if (info.pid > 0) {
   1178       char pid_value_buf[kUint64StringSize];
   1179       uint64_t pid_value_len = my_uint64_len(info.pid);
   1180       my_uint64tos(pid_value_buf, info.pid, pid_value_len);
   1181       static const char pid_key_name[] = "pid";
   1182       writer.AddPairData(pid_key_name, sizeof(pid_key_name) - 1,
   1183                          pid_value_buf, pid_value_len);
   1184       writer.AddBoundary();
   1185     }
   1186 #if defined(OS_ANDROID)
   1187     // Addtional MIME blocks are added for logging on Android devices.
   1188     static const char android_build_id[] = "android_build_id";
   1189     static const char android_build_fp[] = "android_build_fp";
   1190     static const char device[] = "device";
   1191     static const char model[] = "model";
   1192     static const char brand[] = "brand";
   1193     static const char exception_info[] = "exception_info";
   1194 
   1195     base::android::BuildInfo* android_build_info =
   1196         base::android::BuildInfo::GetInstance();
   1197     writer.AddPairString(
   1198         android_build_id, android_build_info->android_build_id());
   1199     writer.AddBoundary();
   1200     writer.AddPairString(
   1201         android_build_fp, android_build_info->android_build_fp());
   1202     writer.AddBoundary();
   1203     writer.AddPairString(device, android_build_info->device());
   1204     writer.AddBoundary();
   1205     writer.AddPairString(model, android_build_info->model());
   1206     writer.AddBoundary();
   1207     writer.AddPairString(brand, android_build_info->brand());
   1208     writer.AddBoundary();
   1209     if (android_build_info->java_exception_info() != NULL) {
   1210       writer.AddPairString(exception_info,
   1211                            android_build_info->java_exception_info());
   1212       writer.AddBoundary();
   1213     }
   1214 #endif
   1215     writer.Flush();
   1216   }
   1217 
   1218   if (info.process_start_time > 0) {
   1219     struct kernel_timeval tv;
   1220     if (!sys_gettimeofday(&tv, NULL)) {
   1221       uint64_t time = kernel_timeval_to_ms(&tv);
   1222       if (time > info.process_start_time) {
   1223         time -= info.process_start_time;
   1224         char time_str[kUint64StringSize];
   1225         const unsigned time_len = my_uint64_len(time);
   1226         my_uint64tos(time_str, time, time_len);
   1227 
   1228         static const char process_time_msg[] = "ptime";
   1229         writer.AddPairData(process_time_msg, sizeof(process_time_msg) - 1,
   1230                            time_str, time_len);
   1231         writer.AddBoundary();
   1232         writer.Flush();
   1233       }
   1234     }
   1235   }
   1236 
   1237   if (info.process_type_length) {
   1238     writer.AddPairString("ptype", info.process_type);
   1239     writer.AddBoundary();
   1240     writer.Flush();
   1241   }
   1242 
   1243   if (info.distro_length) {
   1244     static const char distro_msg[] = "lsb-release";
   1245     writer.AddPairString(distro_msg, info.distro);
   1246     writer.AddBoundary();
   1247     writer.Flush();
   1248   }
   1249 
   1250   if (info.oom_size) {
   1251     char oom_size_str[kUint64StringSize];
   1252     const unsigned oom_size_len = my_uint64_len(info.oom_size);
   1253     my_uint64tos(oom_size_str, info.oom_size, oom_size_len);
   1254     static const char oom_size_msg[] = "oom-size";
   1255     writer.AddPairData(oom_size_msg, sizeof(oom_size_msg) - 1,
   1256                        oom_size_str, oom_size_len);
   1257     writer.AddBoundary();
   1258     writer.Flush();
   1259   }
   1260 
   1261   if (info.crash_keys) {
   1262     CrashKeyStorage::Iterator crash_key_iterator(*info.crash_keys);
   1263     const CrashKeyStorage::Entry* entry;
   1264     while ((entry = crash_key_iterator.Next())) {
   1265       writer.AddPairString(entry->key, entry->value);
   1266       writer.AddBoundary();
   1267       writer.Flush();
   1268     }
   1269   }
   1270 
   1271   writer.AddFileContents(g_dump_msg, dump_data, dump_size);
   1272 #if defined(ADDRESS_SANITIZER)
   1273   // Append a multipart boundary and the contents of the AddressSanitizer log.
   1274   writer.AddBoundary();
   1275   writer.AddFileContents(g_log_msg, log_data, log_size);
   1276 #endif
   1277   writer.AddEnd();
   1278   writer.Flush();
   1279 
   1280   IGNORE_RET(sys_close(temp_file_fd));
   1281 
   1282 #if defined(OS_ANDROID)
   1283   if (info.filename) {
   1284     int filename_length = my_strlen(info.filename);
   1285 
   1286     // If this was a file, we need to copy it to the right place and use the
   1287     // right file name so it gets uploaded by the browser.
   1288     const char msg[] = "Output crash dump file:";
   1289     WriteLog(msg, sizeof(msg) - 1);
   1290     WriteLog(info.filename, filename_length - 1);
   1291 
   1292     char pid_buf[kUint64StringSize];
   1293     uint64_t pid_str_length = my_uint64_len(info.pid);
   1294     my_uint64tos(pid_buf, info.pid, pid_str_length);
   1295 
   1296     // -1 because we won't need the null terminator on the original filename.
   1297     unsigned done_filename_len = filename_length - 1 + pid_str_length;
   1298     char* done_filename = reinterpret_cast<char*>(
   1299         allocator.Alloc(done_filename_len));
   1300     // Rename the file such that the pid is the suffix in order signal to other
   1301     // processes that the minidump is complete. The advantage of using the pid
   1302     // as the suffix is that it is trivial to associate the minidump with the
   1303     // crashed process.
   1304     // Finally, note strncpy prevents null terminators from
   1305     // being copied. Pad the rest with 0's.
   1306     my_strncpy(done_filename, info.filename, done_filename_len);
   1307     // Append the suffix a null terminator should be added.
   1308     my_strncat(done_filename, pid_buf, pid_str_length);
   1309     // Rename the minidump file to signal that it is complete.
   1310     if (rename(info.filename, done_filename)) {
   1311       const char failed_msg[] = "Failed to rename:";
   1312       WriteLog(failed_msg, sizeof(failed_msg) - 1);
   1313       WriteLog(info.filename, filename_length - 1);
   1314       const char to_msg[] = "to";
   1315       WriteLog(to_msg, sizeof(to_msg) - 1);
   1316       WriteLog(done_filename, done_filename_len - 1);
   1317     }
   1318   }
   1319 #endif
   1320 
   1321   if (!info.upload)
   1322     return;
   1323 
   1324   const pid_t child = sys_fork();
   1325   if (!child) {
   1326     // Spawned helper process.
   1327     //
   1328     // This code is called both when a browser is crashing (in which case,
   1329     // nothing really matters any more) and when a renderer/plugin crashes, in
   1330     // which case we need to continue.
   1331     //
   1332     // Since we are a multithreaded app, if we were just to fork(), we might
   1333     // grab file descriptors which have just been created in another thread and
   1334     // hold them open for too long.
   1335     //
   1336     // Thus, we have to loop and try and close everything.
   1337     const int fd = sys_open("/proc/self/fd", O_DIRECTORY | O_RDONLY, 0);
   1338     if (fd < 0) {
   1339       for (unsigned i = 3; i < 8192; ++i)
   1340         IGNORE_RET(sys_close(i));
   1341     } else {
   1342       google_breakpad::DirectoryReader reader(fd);
   1343       const char* name;
   1344       while (reader.GetNextEntry(&name)) {
   1345         int i;
   1346         if (my_strtoui(&i, name) && i > 2 && i != fd)
   1347           IGNORE_RET(sys_close(i));
   1348         reader.PopEntry();
   1349       }
   1350 
   1351       IGNORE_RET(sys_close(fd));
   1352     }
   1353 
   1354     IGNORE_RET(sys_setsid());
   1355 
   1356     // Leave one end of a pipe in the upload process and watch for it getting
   1357     // closed by the upload process exiting.
   1358     int fds[2];
   1359     if (sys_pipe(fds) >= 0) {
   1360       const pid_t upload_child = sys_fork();
   1361       if (!upload_child) {
   1362         // Upload process.
   1363         IGNORE_RET(sys_close(fds[0]));
   1364         IGNORE_RET(sys_dup2(fds[1], 3));
   1365         ExecUploadProcessOrTerminate(info, temp_file, mime_boundary, exe_buf,
   1366                                      &allocator);
   1367       }
   1368 
   1369       // Helper process.
   1370       if (upload_child > 0) {
   1371         IGNORE_RET(sys_close(fds[1]));
   1372         char id_buf[17];  // Crash report IDs are expected to be 16 chars.
   1373         ssize_t len = -1;
   1374         // Upload should finish in about 10 seconds. Add a few more 500 ms
   1375         // internals to account for process startup time.
   1376         for (size_t wait_count = 0; wait_count < 24; ++wait_count) {
   1377           struct kernel_pollfd poll_fd;
   1378           poll_fd.fd = fds[0];
   1379           poll_fd.events = POLLIN | POLLPRI | POLLERR;
   1380           int ret = sys_poll(&poll_fd, 1, 500);
   1381           if (ret < 0) {
   1382             // Error
   1383             break;
   1384           } else if (ret > 0) {
   1385             // There is data to read.
   1386             len = HANDLE_EINTR(sys_read(fds[0], id_buf, sizeof(id_buf) - 1));
   1387             break;
   1388           }
   1389           // ret == 0 -> timed out, continue waiting.
   1390         }
   1391         if (len > 0) {
   1392           // Write crash dump id to stderr.
   1393           id_buf[len] = 0;
   1394           static const char msg[] = "\nCrash dump id: ";
   1395           WriteLog(msg, sizeof(msg) - 1);
   1396           WriteLog(id_buf, my_strlen(id_buf));
   1397           WriteLog("\n", 1);
   1398 
   1399           // Write crash dump id to crash log as: seconds_since_epoch,crash_id
   1400           struct kernel_timeval tv;
   1401           if (g_crash_log_path && !sys_gettimeofday(&tv, NULL)) {
   1402             uint64_t time = kernel_timeval_to_ms(&tv) / 1000;
   1403             char time_str[kUint64StringSize];
   1404             const unsigned time_len = my_uint64_len(time);
   1405             my_uint64tos(time_str, time, time_len);
   1406 
   1407             int log_fd = sys_open(g_crash_log_path,
   1408                                   O_CREAT | O_WRONLY | O_APPEND,
   1409                                   0600);
   1410             if (log_fd > 0) {
   1411               sys_write(log_fd, time_str, time_len);
   1412               sys_write(log_fd, ",", 1);
   1413               sys_write(log_fd, id_buf, my_strlen(id_buf));
   1414               sys_write(log_fd, "\n", 1);
   1415               IGNORE_RET(sys_close(log_fd));
   1416             }
   1417           }
   1418         }
   1419         if (sys_waitpid(upload_child, NULL, WNOHANG) == 0) {
   1420           // Upload process is still around, kill it.
   1421           sys_kill(upload_child, SIGKILL);
   1422         }
   1423       }
   1424     }
   1425 
   1426     // Helper process.
   1427     IGNORE_RET(sys_unlink(info.filename));
   1428 #if defined(ADDRESS_SANITIZER)
   1429     IGNORE_RET(sys_unlink(info.log_filename));
   1430 #endif
   1431     IGNORE_RET(sys_unlink(temp_file));
   1432     sys__exit(0);
   1433   }
   1434 
   1435   // Main browser process.
   1436   if (child <= 0)
   1437     return;
   1438   (void) HANDLE_EINTR(sys_waitpid(child, NULL, 0));
   1439 }
   1440 
   1441 void InitCrashReporter(const std::string& process_type) {
   1442 #if defined(OS_ANDROID)
   1443   // This will guarantee that the BuildInfo has been initialized and subsequent
   1444   // calls will not require memory allocation.
   1445   base::android::BuildInfo::GetInstance();
   1446 #endif
   1447   // Determine the process type and take appropriate action.
   1448   const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
   1449   if (parsed_command_line.HasSwitch(switches::kDisableBreakpad))
   1450     return;
   1451 
   1452   if (process_type.empty()) {
   1453     bool enable_breakpad = GetBreakpadClient()->GetCollectStatsConsent() ||
   1454                            GetBreakpadClient()->IsRunningUnattended();
   1455     enable_breakpad &=
   1456         !parsed_command_line.HasSwitch(switches::kDisableBreakpad);
   1457     if (!enable_breakpad) {
   1458       enable_breakpad = parsed_command_line.HasSwitch(
   1459           switches::kEnableCrashReporterForTesting);
   1460     }
   1461     if (!enable_breakpad) {
   1462       VLOG(1) << "Breakpad disabled";
   1463       return;
   1464     }
   1465 
   1466     EnableCrashDumping(GetBreakpadClient()->IsRunningUnattended());
   1467   } else if (GetBreakpadClient()->EnableBreakpadForProcess(process_type)) {
   1468 #if defined(OS_ANDROID)
   1469     NOTREACHED() << "Breakpad initialized with InitCrashReporter() instead of "
   1470       "InitNonBrowserCrashReporter in " << process_type << " process.";
   1471     return;
   1472 #else
   1473     // We might be chrooted in a zygote or renderer process so we cannot call
   1474     // GetCollectStatsConsent because that needs access the the user's home
   1475     // dir. Instead, we set a command line flag for these processes.
   1476     // Even though plugins are not chrooted, we share the same code path for
   1477     // simplicity.
   1478     if (!parsed_command_line.HasSwitch(switches::kEnableCrashReporter))
   1479       return;
   1480     SetClientIdFromCommandLine(parsed_command_line);
   1481     EnableNonBrowserCrashDumping();
   1482     VLOG(1) << "Non Browser crash dumping enabled for: " << process_type;
   1483 #endif  // #if defined(OS_ANDROID)
   1484   }
   1485 
   1486   SetProcessStartTime();
   1487   g_pid = getpid();
   1488 
   1489   GetBreakpadClient()->SetDumpWithoutCrashingFunction(&DumpProcess);
   1490 #if defined(ADDRESS_SANITIZER)
   1491   // Register the callback for AddressSanitizer error reporting.
   1492   __asan_set_error_report_callback(AsanLinuxBreakpadCallback);
   1493 #endif
   1494 
   1495   g_crash_keys = new CrashKeyStorage;
   1496   GetBreakpadClient()->RegisterCrashKeys();
   1497   base::debug::SetCrashKeyReportingFunctions(
   1498       &SetCrashKeyValue, &ClearCrashKey);
   1499 }
   1500 
   1501 #if defined(OS_ANDROID)
   1502 void InitNonBrowserCrashReporterForAndroid(const std::string& process_type) {
   1503   const CommandLine* command_line = CommandLine::ForCurrentProcess();
   1504   if (command_line->HasSwitch(switches::kEnableCrashReporter)) {
   1505     // On Android we need to provide a FD to the file where the minidump is
   1506     // generated as the renderer and browser run with different UIDs
   1507     // (preventing the browser from inspecting the renderer process).
   1508     int minidump_fd = base::GlobalDescriptors::GetInstance()->MaybeGet(
   1509         GetBreakpadClient()->GetAndroidMinidumpDescriptor());
   1510     if (minidump_fd == base::kInvalidPlatformFileValue) {
   1511       NOTREACHED() << "Could not find minidump FD, crash reporting disabled.";
   1512     } else {
   1513       EnableNonBrowserCrashDumping(process_type, minidump_fd);
   1514     }
   1515   }
   1516 }
   1517 #endif  // OS_ANDROID
   1518 
   1519 bool IsCrashReporterEnabled() {
   1520   return g_is_crash_reporter_enabled;
   1521 }
   1522 
   1523 }  // namespace breakpad
   1524