Home | History | Annotate | Download | only in app
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // For linux_syscall_support.h. This makes it safe to call embedded system
      6 // calls when in seccomp mode.
      7 
      8 #include "components/breakpad/app/breakpad_linux.h"
      9 
     10 #include <fcntl.h>
     11 #include <poll.h>
     12 #include <signal.h>
     13 #include <stdlib.h>
     14 #include <sys/socket.h>
     15 #include <sys/time.h>
     16 #include <sys/types.h>
     17 #include <sys/uio.h>
     18 #include <sys/wait.h>
     19 #include <time.h>
     20 #include <unistd.h>
     21 
     22 #include <algorithm>
     23 #include <string>
     24 
     25 #include "base/base_switches.h"
     26 #include "base/command_line.h"
     27 #include "base/debug/crash_logging.h"
     28 #include "base/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/platform_file.h"
     33 #include "base/posix/eintr_wrapper.h"
     34 #include "base/posix/global_descriptors.h"
     35 #include "base/process/memory.h"
     36 #include "base/strings/string_util.h"
     37 #include "breakpad/src/client/linux/crash_generation/crash_generation_client.h"
     38 #include "breakpad/src/client/linux/handler/exception_handler.h"
     39 #include "breakpad/src/client/linux/minidump_writer/directory_reader.h"
     40 #include "breakpad/src/common/linux/linux_libc_support.h"
     41 #include "breakpad/src/common/memory.h"
     42 #include "components/breakpad/app/breakpad_client.h"
     43 #include "components/breakpad/app/breakpad_linux_impl.h"
     44 #include "content/public/common/content_descriptors.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 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   GetBreakpadClient()->SetClientID(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 (GetBreakpadClient()->GetCrashDumpLocation(&dumps_path)) {
    635     base::FilePath logfile =
    636         dumps_path.Append(GetBreakpadClient()->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 // GetBreakpadClient() cannot call any Set methods until after InitCrashKeys().
    872 void InitCrashKeys() {
    873   g_crash_keys = new CrashKeyStorage;
    874   GetBreakpadClient()->RegisterCrashKeys();
    875   base::debug::SetCrashKeyReportingFunctions(&SetCrashKeyValue, &ClearCrashKey);
    876 }
    877 
    878 // Miscellaneous initialization functions to call after Breakpad has been
    879 // enabled.
    880 void PostEnableBreakpadInitialization() {
    881   SetProcessStartTime();
    882   g_pid = getpid();
    883 
    884   base::debug::SetDumpWithoutCrashingFunction(&DumpProcess);
    885 #if defined(ADDRESS_SANITIZER)
    886   // Register the callback for AddressSanitizer error reporting.
    887   __asan_set_error_report_callback(AsanLinuxBreakpadCallback);
    888 #endif
    889 }
    890 
    891 }  // namespace
    892 
    893 void LoadDataFromFD(google_breakpad::PageAllocator& allocator,
    894                     int fd, bool close_fd, uint8_t** file_data, size_t* size) {
    895   STAT_STRUCT st;
    896   if (FSTAT_FUNC(fd, &st) != 0) {
    897     static const char msg[] = "Cannot upload crash dump: stat failed\n";
    898     WriteLog(msg, sizeof(msg) - 1);
    899     if (close_fd)
    900       IGNORE_RET(sys_close(fd));
    901     return;
    902   }
    903 
    904   *file_data = reinterpret_cast<uint8_t*>(allocator.Alloc(st.st_size));
    905   if (!(*file_data)) {
    906     static const char msg[] = "Cannot upload crash dump: cannot alloc\n";
    907     WriteLog(msg, sizeof(msg) - 1);
    908     if (close_fd)
    909       IGNORE_RET(sys_close(fd));
    910     return;
    911   }
    912   my_memset(*file_data, 0xf, st.st_size);
    913 
    914   *size = st.st_size;
    915   int byte_read = sys_read(fd, *file_data, *size);
    916   if (byte_read == -1) {
    917     static const char msg[] = "Cannot upload crash dump: read failed\n";
    918     WriteLog(msg, sizeof(msg) - 1);
    919     if (close_fd)
    920       IGNORE_RET(sys_close(fd));
    921     return;
    922   }
    923 
    924   if (close_fd)
    925     IGNORE_RET(sys_close(fd));
    926 }
    927 
    928 void LoadDataFromFile(google_breakpad::PageAllocator& allocator,
    929                       const char* filename,
    930                       int* fd, uint8_t** file_data, size_t* size) {
    931   // WARNING: this code runs in a compromised context. It may not call into
    932   // libc nor allocate memory normally.
    933   *fd = sys_open(filename, O_RDONLY, 0);
    934   *size = 0;
    935 
    936   if (*fd < 0) {
    937     static const char msg[] = "Cannot upload crash dump: failed to open\n";
    938     WriteLog(msg, sizeof(msg) - 1);
    939     return;
    940   }
    941 
    942   LoadDataFromFD(allocator, *fd, true, file_data, size);
    943 }
    944 
    945 // Spawn the appropriate upload process for the current OS:
    946 // - generic Linux invokes wget.
    947 // - ChromeOS invokes crash_reporter.
    948 // |dumpfile| is the path to the dump data file.
    949 // |mime_boundary| is only used on Linux.
    950 // |exe_buf| is only used on CrOS and is the crashing process' name.
    951 void ExecUploadProcessOrTerminate(const BreakpadInfo& info,
    952                                   const char* dumpfile,
    953                                   const char* mime_boundary,
    954                                   const char* exe_buf,
    955                                   google_breakpad::PageAllocator* allocator) {
    956 #if defined(OS_CHROMEOS)
    957   // CrOS uses crash_reporter instead of wget to report crashes,
    958   // it needs to know where the crash dump lives and the pid and uid of the
    959   // crashing process.
    960   static const char kCrashReporterBinary[] = "/sbin/crash_reporter";
    961 
    962   char pid_buf[kUint64StringSize];
    963   uint64_t pid_str_length = my_uint64_len(info.pid);
    964   my_uint64tos(pid_buf, info.pid, pid_str_length);
    965   pid_buf[pid_str_length] = '\0';
    966 
    967   char uid_buf[kUint64StringSize];
    968   uid_t uid = geteuid();
    969   uint64_t uid_str_length = my_uint64_len(uid);
    970   my_uint64tos(uid_buf, uid, uid_str_length);
    971   uid_buf[uid_str_length] = '\0';
    972   const char* args[] = {
    973     kCrashReporterBinary,
    974     "--chrome",
    975     dumpfile,
    976     "--pid",
    977     pid_buf,
    978     "--uid",
    979     uid_buf,
    980     "--exe",
    981     exe_buf,
    982     NULL,
    983   };
    984   static const char msg[] = "Cannot upload crash dump: cannot exec "
    985                             "/sbin/crash_reporter\n";
    986 #else
    987   // The --header argument to wget looks like:
    988   //   --header=Content-Type: multipart/form-data; boundary=XYZ
    989   // where the boundary has two fewer leading '-' chars
    990   static const char header_msg[] =
    991       "--header=Content-Type: multipart/form-data; boundary=";
    992   char* const header = reinterpret_cast<char*>(allocator->Alloc(
    993       sizeof(header_msg) - 1 + strlen(mime_boundary) - 2 + 1));
    994   memcpy(header, header_msg, sizeof(header_msg) - 1);
    995   memcpy(header + sizeof(header_msg) - 1, mime_boundary + 2,
    996          strlen(mime_boundary) - 2);
    997   // We grab the NUL byte from the end of |mime_boundary|.
    998 
    999   // The --post-file argument to wget looks like:
   1000   //   --post-file=/tmp/...
   1001   static const char post_file_msg[] = "--post-file=";
   1002   char* const post_file = reinterpret_cast<char*>(allocator->Alloc(
   1003        sizeof(post_file_msg) - 1 + strlen(dumpfile) + 1));
   1004   memcpy(post_file, post_file_msg, sizeof(post_file_msg) - 1);
   1005   memcpy(post_file + sizeof(post_file_msg) - 1, dumpfile, strlen(dumpfile));
   1006 
   1007   static const char kWgetBinary[] = "/usr/bin/wget";
   1008   const char* args[] = {
   1009     kWgetBinary,
   1010     header,
   1011     post_file,
   1012     kUploadURL,
   1013     "--timeout=10",  // Set a timeout so we don't hang forever.
   1014     "--tries=1",     // Don't retry if the upload fails.
   1015     "-O",  // output reply to fd 3
   1016     "/dev/fd/3",
   1017     NULL,
   1018   };
   1019   static const char msg[] = "Cannot upload crash dump: cannot exec "
   1020                             "/usr/bin/wget\n";
   1021 #endif
   1022   execve(args[0], const_cast<char**>(args), environ);
   1023   WriteLog(msg, sizeof(msg) - 1);
   1024   sys__exit(1);
   1025 }
   1026 
   1027 // Runs in the helper process to wait for the upload process running
   1028 // ExecUploadProcessOrTerminate() to finish. Returns the number of bytes written
   1029 // to |fd| and save the written contents to |buf|.
   1030 // |buf| needs to be big enough to hold |bytes_to_read| + 1 characters.
   1031 size_t WaitForCrashReportUploadProcess(int fd, size_t bytes_to_read,
   1032                                        char* buf) {
   1033   size_t bytes_read = 0;
   1034 
   1035   // Upload should finish in about 10 seconds. Add a few more 500 ms
   1036   // internals to account for process startup time.
   1037   for (size_t wait_count = 0; wait_count < 24; ++wait_count) {
   1038     struct kernel_pollfd poll_fd;
   1039     poll_fd.fd = fd;
   1040     poll_fd.events = POLLIN | POLLPRI | POLLERR;
   1041     int ret = sys_poll(&poll_fd, 1, 500);
   1042     if (ret < 0) {
   1043       // Error
   1044       break;
   1045     } else if (ret > 0) {
   1046       // There is data to read.
   1047       ssize_t len = HANDLE_EINTR(
   1048           sys_read(fd, buf + bytes_read, bytes_to_read - bytes_read));
   1049       if (len < 0)
   1050         break;
   1051       bytes_read += len;
   1052       if (bytes_read == bytes_to_read)
   1053         break;
   1054     }
   1055     // |ret| == 0 -> timed out, continue waiting.
   1056     // or |bytes_read| < |bytes_to_read| still, keep reading.
   1057   }
   1058   buf[bytes_to_read] = 0;  // Always NUL terminate the buffer.
   1059   return bytes_read;
   1060 }
   1061 
   1062 // |buf| should be |expected_len| + 1 characters in size and NULL terminated.
   1063 bool IsValidCrashReportId(const char* buf, size_t bytes_read,
   1064                           size_t expected_len) {
   1065   if (bytes_read != expected_len)
   1066     return false;
   1067 #if defined(OS_CHROMEOS)
   1068   return my_strcmp(buf, "_sys_cr_finished") == 0;
   1069 #else
   1070   for (size_t i = 0; i < bytes_read; ++i) {
   1071     if (!my_isxdigit(buf[i]))
   1072       return false;
   1073   }
   1074   return true;
   1075 #endif
   1076 }
   1077 
   1078 // |buf| should be |expected_len| + 1 characters in size and NULL terminated.
   1079 void HandleCrashReportId(const char* buf, size_t bytes_read,
   1080                          size_t expected_len) {
   1081   WriteNewline();
   1082   if (!IsValidCrashReportId(buf, bytes_read, expected_len)) {
   1083 #if defined(OS_CHROMEOS)
   1084     static const char msg[] = "Crash_reporter failed to process crash report";
   1085 #else
   1086     static const char msg[] = "Failed to get crash dump id.";
   1087 #endif
   1088     WriteLog(msg, sizeof(msg) - 1);
   1089     WriteNewline();
   1090     return;
   1091   }
   1092 
   1093 #if defined(OS_CHROMEOS)
   1094   static const char msg[] = "Crash dump received by crash_reporter\n";
   1095   WriteLog(msg, sizeof(msg) - 1);
   1096 #else
   1097   // Write crash dump id to stderr.
   1098   static const char msg[] = "Crash dump id: ";
   1099   WriteLog(msg, sizeof(msg) - 1);
   1100   WriteLog(buf, my_strlen(buf));
   1101   WriteNewline();
   1102 
   1103   // Write crash dump id to crash log as: seconds_since_epoch,crash_id
   1104   struct kernel_timeval tv;
   1105   if (g_crash_log_path && !sys_gettimeofday(&tv, NULL)) {
   1106     uint64_t time = kernel_timeval_to_ms(&tv) / 1000;
   1107     char time_str[kUint64StringSize];
   1108     const unsigned time_len = my_uint64_len(time);
   1109     my_uint64tos(time_str, time, time_len);
   1110 
   1111     const int kLogOpenFlags = O_CREAT | O_WRONLY | O_APPEND | O_CLOEXEC;
   1112     int log_fd = sys_open(g_crash_log_path, kLogOpenFlags, 0600);
   1113     if (log_fd > 0) {
   1114       sys_write(log_fd, time_str, time_len);
   1115       sys_write(log_fd, ",", 1);
   1116       sys_write(log_fd, buf, my_strlen(buf));
   1117       sys_write(log_fd, "\n", 1);
   1118       IGNORE_RET(sys_close(log_fd));
   1119     }
   1120   }
   1121 #endif
   1122 }
   1123 
   1124 #if defined(OS_CHROMEOS)
   1125 const char* GetCrashingProcessName(const BreakpadInfo& info,
   1126                                    google_breakpad::PageAllocator* allocator) {
   1127   // Symlink to process binary is at /proc/###/exe.
   1128   char linkpath[kUint64StringSize + sizeof("/proc/") + sizeof("/exe")] =
   1129     "/proc/";
   1130   uint64_t pid_value_len = my_uint64_len(info.pid);
   1131   my_uint64tos(linkpath + sizeof("/proc/") - 1, info.pid, pid_value_len);
   1132   linkpath[sizeof("/proc/") - 1 + pid_value_len] = '\0';
   1133   my_strlcat(linkpath, "/exe", sizeof(linkpath));
   1134 
   1135   const int kMaxSize = 4096;
   1136   char* link = reinterpret_cast<char*>(allocator->Alloc(kMaxSize));
   1137   if (link) {
   1138     ssize_t size = readlink(linkpath, link, kMaxSize);
   1139     if (size < kMaxSize && size > 0) {
   1140       // readlink(2) doesn't add a terminating NUL, so do it now.
   1141       link[size] = '\0';
   1142 
   1143       const char* name = my_strrchr(link, '/');
   1144       if (name)
   1145         return name + 1;
   1146       return link;
   1147     }
   1148   }
   1149   // Either way too long, or a read error.
   1150   return "chrome-crash-unknown-process";
   1151 }
   1152 #endif
   1153 
   1154 void HandleCrashDump(const BreakpadInfo& info) {
   1155   int dumpfd;
   1156   bool keep_fd = false;
   1157   size_t dump_size;
   1158   uint8_t* dump_data;
   1159   google_breakpad::PageAllocator allocator;
   1160   const char* exe_buf = NULL;
   1161 
   1162 #if defined(OS_CHROMEOS)
   1163   // Grab the crashing process' name now, when it should still be available.
   1164   // If we try to do this later in our grandchild the crashing process has
   1165   // already terminated.
   1166   exe_buf = GetCrashingProcessName(info, &allocator);
   1167 #endif
   1168 
   1169   if (info.fd != -1) {
   1170     // Dump is provided with an open FD.
   1171     keep_fd = true;
   1172     dumpfd = info.fd;
   1173 
   1174     // The FD is pointing to the end of the file.
   1175     // Rewind, we'll read the data next.
   1176     if (lseek(dumpfd, 0, SEEK_SET) == -1) {
   1177       static const char msg[] = "Cannot upload crash dump: failed to "
   1178           "reposition minidump FD\n";
   1179       WriteLog(msg, sizeof(msg) - 1);
   1180       IGNORE_RET(sys_close(dumpfd));
   1181       return;
   1182     }
   1183     LoadDataFromFD(allocator, info.fd, false, &dump_data, &dump_size);
   1184   } else {
   1185     // Dump is provided with a path.
   1186     keep_fd = false;
   1187     LoadDataFromFile(allocator, info.filename, &dumpfd, &dump_data, &dump_size);
   1188   }
   1189 
   1190   // TODO(jcivelli): make log work when using FDs.
   1191 #if defined(ADDRESS_SANITIZER)
   1192   int logfd;
   1193   size_t log_size;
   1194   uint8_t* log_data;
   1195   // Load the AddressSanitizer log into log_data.
   1196   LoadDataFromFile(allocator, info.log_filename, &logfd, &log_data, &log_size);
   1197 #endif
   1198 
   1199   // We need to build a MIME block for uploading to the server. Since we are
   1200   // going to fork and run wget, it needs to be written to a temp file.
   1201   const int ufd = sys_open("/dev/urandom", O_RDONLY, 0);
   1202   if (ufd < 0) {
   1203     static const char msg[] = "Cannot upload crash dump because /dev/urandom"
   1204                               " is missing\n";
   1205     WriteLog(msg, sizeof(msg) - 1);
   1206     return;
   1207   }
   1208 
   1209   static const char temp_file_template[] =
   1210       "/tmp/chromium-upload-XXXXXXXXXXXXXXXX";
   1211   char temp_file[sizeof(temp_file_template)];
   1212   int temp_file_fd = -1;
   1213   if (keep_fd) {
   1214     temp_file_fd = dumpfd;
   1215     // Rewind the destination, we are going to overwrite it.
   1216     if (lseek(dumpfd, 0, SEEK_SET) == -1) {
   1217       static const char msg[] = "Cannot upload crash dump: failed to "
   1218           "reposition minidump FD (2)\n";
   1219       WriteLog(msg, sizeof(msg) - 1);
   1220       IGNORE_RET(sys_close(dumpfd));
   1221       return;
   1222     }
   1223   } else {
   1224     if (info.upload) {
   1225       memcpy(temp_file, temp_file_template, sizeof(temp_file_template));
   1226 
   1227       for (unsigned i = 0; i < 10; ++i) {
   1228         uint64_t t;
   1229         sys_read(ufd, &t, sizeof(t));
   1230         write_uint64_hex(temp_file + sizeof(temp_file) - (16 + 1), t);
   1231 
   1232         temp_file_fd = sys_open(temp_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
   1233         if (temp_file_fd >= 0)
   1234           break;
   1235       }
   1236 
   1237       if (temp_file_fd < 0) {
   1238         static const char msg[] = "Failed to create temporary file in /tmp: "
   1239             "cannot upload crash dump\n";
   1240         WriteLog(msg, sizeof(msg) - 1);
   1241         IGNORE_RET(sys_close(ufd));
   1242         return;
   1243       }
   1244     } else {
   1245       temp_file_fd = sys_open(info.filename, O_WRONLY, 0600);
   1246       if (temp_file_fd < 0) {
   1247         static const char msg[] = "Failed to save crash dump: failed to open\n";
   1248         WriteLog(msg, sizeof(msg) - 1);
   1249         IGNORE_RET(sys_close(ufd));
   1250         return;
   1251       }
   1252     }
   1253   }
   1254 
   1255   // The MIME boundary is 28 hyphens, followed by a 64-bit nonce and a NUL.
   1256   char mime_boundary[28 + 16 + 1];
   1257   my_memset(mime_boundary, '-', 28);
   1258   uint64_t boundary_rand;
   1259   sys_read(ufd, &boundary_rand, sizeof(boundary_rand));
   1260   write_uint64_hex(mime_boundary + 28, boundary_rand);
   1261   mime_boundary[28 + 16] = 0;
   1262   IGNORE_RET(sys_close(ufd));
   1263 
   1264   // The MIME block looks like this:
   1265   //   BOUNDARY \r\n
   1266   //   Content-Disposition: form-data; name="prod" \r\n \r\n
   1267   //   Chrome_Linux \r\n
   1268   //   BOUNDARY \r\n
   1269   //   Content-Disposition: form-data; name="ver" \r\n \r\n
   1270   //   1.2.3.4 \r\n
   1271   //   BOUNDARY \r\n
   1272   //
   1273   //   zero or one:
   1274   //   Content-Disposition: form-data; name="ptime" \r\n \r\n
   1275   //   abcdef \r\n
   1276   //   BOUNDARY \r\n
   1277   //
   1278   //   zero or one:
   1279   //   Content-Disposition: form-data; name="ptype" \r\n \r\n
   1280   //   abcdef \r\n
   1281   //   BOUNDARY \r\n
   1282   //
   1283   //   zero or one:
   1284   //   Content-Disposition: form-data; name="lsb-release" \r\n \r\n
   1285   //   abcdef \r\n
   1286   //   BOUNDARY \r\n
   1287   //
   1288   //   zero or one:
   1289   //   Content-Disposition: form-data; name="oom-size" \r\n \r\n
   1290   //   1234567890 \r\n
   1291   //   BOUNDARY \r\n
   1292   //
   1293   //   zero or more (up to CrashKeyStorage::num_entries = 64):
   1294   //   Content-Disposition: form-data; name=crash-key-name \r\n
   1295   //   crash-key-value \r\n
   1296   //   BOUNDARY \r\n
   1297   //
   1298   //   Content-Disposition: form-data; name="dump"; filename="dump" \r\n
   1299   //   Content-Type: application/octet-stream \r\n \r\n
   1300   //   <dump contents>
   1301   //   \r\n BOUNDARY -- \r\n
   1302 
   1303 #if defined(OS_CHROMEOS)
   1304   CrashReporterWriter writer(temp_file_fd);
   1305 #else
   1306   MimeWriter writer(temp_file_fd, mime_boundary);
   1307 #endif
   1308   {
   1309     // TODO(thestig) Do not use this inside a compromised context.
   1310     std::string product_name;
   1311     std::string version;
   1312 
   1313     GetBreakpadClient()->GetProductNameAndVersion(&product_name, &version);
   1314 
   1315     writer.AddBoundary();
   1316     writer.AddPairString("prod", product_name.c_str());
   1317     writer.AddBoundary();
   1318     writer.AddPairString("ver", version.c_str());
   1319     writer.AddBoundary();
   1320     if (info.pid > 0) {
   1321       char pid_value_buf[kUint64StringSize];
   1322       uint64_t pid_value_len = my_uint64_len(info.pid);
   1323       my_uint64tos(pid_value_buf, info.pid, pid_value_len);
   1324       static const char pid_key_name[] = "pid";
   1325       writer.AddPairData(pid_key_name, sizeof(pid_key_name) - 1,
   1326                          pid_value_buf, pid_value_len);
   1327       writer.AddBoundary();
   1328     }
   1329 #if defined(OS_ANDROID)
   1330     // Addtional MIME blocks are added for logging on Android devices.
   1331     static const char android_build_id[] = "android_build_id";
   1332     static const char android_build_fp[] = "android_build_fp";
   1333     static const char device[] = "device";
   1334     static const char model[] = "model";
   1335     static const char brand[] = "brand";
   1336     static const char exception_info[] = "exception_info";
   1337 
   1338     base::android::BuildInfo* android_build_info =
   1339         base::android::BuildInfo::GetInstance();
   1340     writer.AddPairString(
   1341         android_build_id, android_build_info->android_build_id());
   1342     writer.AddBoundary();
   1343     writer.AddPairString(
   1344         android_build_fp, android_build_info->android_build_fp());
   1345     writer.AddBoundary();
   1346     writer.AddPairString(device, android_build_info->device());
   1347     writer.AddBoundary();
   1348     writer.AddPairString(model, android_build_info->model());
   1349     writer.AddBoundary();
   1350     writer.AddPairString(brand, android_build_info->brand());
   1351     writer.AddBoundary();
   1352     if (android_build_info->java_exception_info() != NULL) {
   1353       writer.AddPairString(exception_info,
   1354                            android_build_info->java_exception_info());
   1355       writer.AddBoundary();
   1356     }
   1357 #endif
   1358     writer.Flush();
   1359   }
   1360 
   1361   if (info.process_start_time > 0) {
   1362     struct kernel_timeval tv;
   1363     if (!sys_gettimeofday(&tv, NULL)) {
   1364       uint64_t time = kernel_timeval_to_ms(&tv);
   1365       if (time > info.process_start_time) {
   1366         time -= info.process_start_time;
   1367         char time_str[kUint64StringSize];
   1368         const unsigned time_len = my_uint64_len(time);
   1369         my_uint64tos(time_str, time, time_len);
   1370 
   1371         static const char process_time_msg[] = "ptime";
   1372         writer.AddPairData(process_time_msg, sizeof(process_time_msg) - 1,
   1373                            time_str, time_len);
   1374         writer.AddBoundary();
   1375         writer.Flush();
   1376       }
   1377     }
   1378   }
   1379 
   1380   if (info.process_type_length) {
   1381     writer.AddPairString("ptype", info.process_type);
   1382     writer.AddBoundary();
   1383     writer.Flush();
   1384   }
   1385 
   1386   if (info.distro_length) {
   1387     static const char distro_msg[] = "lsb-release";
   1388     writer.AddPairString(distro_msg, info.distro);
   1389     writer.AddBoundary();
   1390     writer.Flush();
   1391   }
   1392 
   1393   if (info.oom_size) {
   1394     char oom_size_str[kUint64StringSize];
   1395     const unsigned oom_size_len = my_uint64_len(info.oom_size);
   1396     my_uint64tos(oom_size_str, info.oom_size, oom_size_len);
   1397     static const char oom_size_msg[] = "oom-size";
   1398     writer.AddPairData(oom_size_msg, sizeof(oom_size_msg) - 1,
   1399                        oom_size_str, oom_size_len);
   1400     writer.AddBoundary();
   1401     writer.Flush();
   1402   }
   1403 
   1404   if (info.crash_keys) {
   1405     CrashKeyStorage::Iterator crash_key_iterator(*info.crash_keys);
   1406     const CrashKeyStorage::Entry* entry;
   1407     while ((entry = crash_key_iterator.Next())) {
   1408       writer.AddPairString(entry->key, entry->value);
   1409       writer.AddBoundary();
   1410       writer.Flush();
   1411     }
   1412   }
   1413 
   1414   writer.AddFileContents(g_dump_msg, dump_data, dump_size);
   1415 #if defined(ADDRESS_SANITIZER)
   1416   // Append a multipart boundary and the contents of the AddressSanitizer log.
   1417   writer.AddBoundary();
   1418   writer.AddFileContents(g_log_msg, log_data, log_size);
   1419 #endif
   1420   writer.AddEnd();
   1421   writer.Flush();
   1422 
   1423   IGNORE_RET(sys_close(temp_file_fd));
   1424 
   1425 #if defined(OS_ANDROID)
   1426   if (info.filename) {
   1427     int filename_length = my_strlen(info.filename);
   1428 
   1429     // If this was a file, we need to copy it to the right place and use the
   1430     // right file name so it gets uploaded by the browser.
   1431     const char msg[] = "Output crash dump file:";
   1432     WriteLog(msg, sizeof(msg) - 1);
   1433     WriteLog(info.filename, filename_length - 1);
   1434 
   1435     char pid_buf[kUint64StringSize];
   1436     uint64_t pid_str_length = my_uint64_len(info.pid);
   1437     my_uint64tos(pid_buf, info.pid, pid_str_length);
   1438 
   1439     // -1 because we won't need the null terminator on the original filename.
   1440     unsigned done_filename_len = filename_length - 1 + pid_str_length;
   1441     char* done_filename = reinterpret_cast<char*>(
   1442         allocator.Alloc(done_filename_len));
   1443     // Rename the file such that the pid is the suffix in order signal to other
   1444     // processes that the minidump is complete. The advantage of using the pid
   1445     // as the suffix is that it is trivial to associate the minidump with the
   1446     // crashed process.
   1447     // Finally, note strncpy prevents null terminators from
   1448     // being copied. Pad the rest with 0's.
   1449     my_strncpy(done_filename, info.filename, done_filename_len);
   1450     // Append the suffix a null terminator should be added.
   1451     my_strncat(done_filename, pid_buf, pid_str_length);
   1452     // Rename the minidump file to signal that it is complete.
   1453     if (rename(info.filename, done_filename)) {
   1454       const char failed_msg[] = "Failed to rename:";
   1455       WriteLog(failed_msg, sizeof(failed_msg) - 1);
   1456       WriteLog(info.filename, filename_length - 1);
   1457       const char to_msg[] = "to";
   1458       WriteLog(to_msg, sizeof(to_msg) - 1);
   1459       WriteLog(done_filename, done_filename_len - 1);
   1460     }
   1461   }
   1462 #endif
   1463 
   1464   if (!info.upload)
   1465     return;
   1466 
   1467   const pid_t child = sys_fork();
   1468   if (!child) {
   1469     // Spawned helper process.
   1470     //
   1471     // This code is called both when a browser is crashing (in which case,
   1472     // nothing really matters any more) and when a renderer/plugin crashes, in
   1473     // which case we need to continue.
   1474     //
   1475     // Since we are a multithreaded app, if we were just to fork(), we might
   1476     // grab file descriptors which have just been created in another thread and
   1477     // hold them open for too long.
   1478     //
   1479     // Thus, we have to loop and try and close everything.
   1480     const int fd = sys_open("/proc/self/fd", O_DIRECTORY | O_RDONLY, 0);
   1481     if (fd < 0) {
   1482       for (unsigned i = 3; i < 8192; ++i)
   1483         IGNORE_RET(sys_close(i));
   1484     } else {
   1485       google_breakpad::DirectoryReader reader(fd);
   1486       const char* name;
   1487       while (reader.GetNextEntry(&name)) {
   1488         int i;
   1489         if (my_strtoui(&i, name) && i > 2 && i != fd)
   1490           IGNORE_RET(sys_close(i));
   1491         reader.PopEntry();
   1492       }
   1493 
   1494       IGNORE_RET(sys_close(fd));
   1495     }
   1496 
   1497     IGNORE_RET(sys_setsid());
   1498 
   1499     // Leave one end of a pipe in the upload process and watch for it getting
   1500     // closed by the upload process exiting.
   1501     int fds[2];
   1502     if (sys_pipe(fds) >= 0) {
   1503       const pid_t upload_child = sys_fork();
   1504       if (!upload_child) {
   1505         // Upload process.
   1506         IGNORE_RET(sys_close(fds[0]));
   1507         IGNORE_RET(sys_dup2(fds[1], 3));
   1508         ExecUploadProcessOrTerminate(info, temp_file, mime_boundary, exe_buf,
   1509                                      &allocator);
   1510       }
   1511 
   1512       // Helper process.
   1513       if (upload_child > 0) {
   1514         IGNORE_RET(sys_close(fds[1]));
   1515 
   1516         const size_t kCrashIdLength = 16;
   1517         char id_buf[kCrashIdLength + 1];
   1518         size_t bytes_read =
   1519             WaitForCrashReportUploadProcess(fds[0], kCrashIdLength, id_buf);
   1520         HandleCrashReportId(id_buf, bytes_read, kCrashIdLength);
   1521 
   1522         if (sys_waitpid(upload_child, NULL, WNOHANG) == 0) {
   1523           // Upload process is still around, kill it.
   1524           sys_kill(upload_child, SIGKILL);
   1525         }
   1526       }
   1527     }
   1528 
   1529     // Helper process.
   1530     IGNORE_RET(sys_unlink(info.filename));
   1531 #if defined(ADDRESS_SANITIZER)
   1532     IGNORE_RET(sys_unlink(info.log_filename));
   1533 #endif
   1534     IGNORE_RET(sys_unlink(temp_file));
   1535     sys__exit(0);
   1536   }
   1537 
   1538   // Main browser process.
   1539   if (child <= 0)
   1540     return;
   1541   (void) HANDLE_EINTR(sys_waitpid(child, NULL, 0));
   1542 }
   1543 
   1544 void InitCrashReporter(const std::string& process_type) {
   1545 #if defined(OS_ANDROID)
   1546   // This will guarantee that the BuildInfo has been initialized and subsequent
   1547   // calls will not require memory allocation.
   1548   base::android::BuildInfo::GetInstance();
   1549 #endif
   1550   // Determine the process type and take appropriate action.
   1551   const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
   1552   if (parsed_command_line.HasSwitch(switches::kDisableBreakpad))
   1553     return;
   1554 
   1555   if (process_type.empty()) {
   1556     bool enable_breakpad = GetBreakpadClient()->GetCollectStatsConsent() ||
   1557                            GetBreakpadClient()->IsRunningUnattended();
   1558     enable_breakpad &=
   1559         !parsed_command_line.HasSwitch(switches::kDisableBreakpad);
   1560     if (!enable_breakpad) {
   1561       enable_breakpad = parsed_command_line.HasSwitch(
   1562           switches::kEnableCrashReporterForTesting);
   1563     }
   1564     if (!enable_breakpad) {
   1565       VLOG(1) << "Breakpad disabled";
   1566       return;
   1567     }
   1568 
   1569     InitCrashKeys();
   1570     EnableCrashDumping(GetBreakpadClient()->IsRunningUnattended());
   1571   } else if (GetBreakpadClient()->EnableBreakpadForProcess(process_type)) {
   1572 #if defined(OS_ANDROID)
   1573     NOTREACHED() << "Breakpad initialized with InitCrashReporter() instead of "
   1574       "InitNonBrowserCrashReporter in " << process_type << " process.";
   1575     return;
   1576 #else
   1577     // We might be chrooted in a zygote or renderer process so we cannot call
   1578     // GetCollectStatsConsent because that needs access the the user's home
   1579     // dir. Instead, we set a command line flag for these processes.
   1580     // Even though plugins are not chrooted, we share the same code path for
   1581     // simplicity.
   1582     if (!parsed_command_line.HasSwitch(switches::kEnableCrashReporter))
   1583       return;
   1584     InitCrashKeys();
   1585     SetClientIdFromCommandLine(parsed_command_line);
   1586     EnableNonBrowserCrashDumping();
   1587     VLOG(1) << "Non Browser crash dumping enabled for: " << process_type;
   1588 #endif  // #if defined(OS_ANDROID)
   1589   }
   1590 
   1591   PostEnableBreakpadInitialization();
   1592 }
   1593 
   1594 #if defined(OS_ANDROID)
   1595 void InitNonBrowserCrashReporterForAndroid(const std::string& process_type) {
   1596   const CommandLine* command_line = CommandLine::ForCurrentProcess();
   1597   if (command_line->HasSwitch(switches::kEnableCrashReporter)) {
   1598     // On Android we need to provide a FD to the file where the minidump is
   1599     // generated as the renderer and browser run with different UIDs
   1600     // (preventing the browser from inspecting the renderer process).
   1601     int minidump_fd = base::GlobalDescriptors::GetInstance()->MaybeGet(
   1602         GetBreakpadClient()->GetAndroidMinidumpDescriptor());
   1603     if (minidump_fd < 0) {
   1604       NOTREACHED() << "Could not find minidump FD, crash reporting disabled.";
   1605     } else {
   1606       EnableNonBrowserCrashDumping(process_type, minidump_fd);
   1607     }
   1608   }
   1609 }
   1610 #endif  // OS_ANDROID
   1611 
   1612 bool IsCrashReporterEnabled() {
   1613   return g_is_crash_reporter_enabled;
   1614 }
   1615 
   1616 }  // namespace breakpad
   1617