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