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