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