1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // For linux_syscall_support.h. This makes it safe to call embedded system
6 // calls when in seccomp mode.
7 
8 #include "components/crash/core/app/breakpad_linux.h"
9 
10 #include <fcntl.h>
11 #include <poll.h>
12 #include <signal.h>
13 #include <stddef.h>
14 #include <stdint.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <sys/socket.h>
18 #include <sys/time.h>
19 #include <sys/types.h>
20 #include <sys/uio.h>
21 #include <sys/wait.h>
22 #include <time.h>
23 #include <unistd.h>
24 
25 #include <algorithm>
26 #include <string>
27 
28 #include "base/base_switches.h"
29 #include "base/command_line.h"
30 #include "base/debug/dump_without_crashing.h"
31 #include "base/files/file_path.h"
32 #include "base/lazy_instance.h"
33 #include "base/linux_util.h"
34 #include "base/macros.h"
35 #include "base/path_service.h"
36 #include "base/posix/eintr_wrapper.h"
37 #include "base/posix/global_descriptors.h"
38 #include "base/process/memory.h"
39 #include "base/strings/string_number_conversions.h"
40 #include "base/strings/string_split.h"
41 #include "base/strings/string_util.h"
42 #include "base/threading/thread_checker.h"
43 #include "build/build_config.h"
44 #include "components/crash/core/app/breakpad_linux_impl.h"
45 #include "components/crash/core/app/crash_reporter_client.h"
46 #include "components/crash/core/common/crash_keys.h"
47 #include "services/service_manager/embedder/descriptors.h"
48 #include "third_party/breakpad/breakpad/src/client/linux/crash_generation/crash_generation_client.h"
49 #include "third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.h"
50 #include "third_party/breakpad/breakpad/src/client/linux/minidump_writer/directory_reader.h"
51 #include "third_party/breakpad/breakpad/src/common/linux/linux_libc_support.h"
52 #include "third_party/breakpad/breakpad/src/common/memory_allocator.h"
53 
54 #if defined(OS_ANDROID)
55 #include <android/log.h>
56 #include <sys/stat.h>
57 
58 #include "base/android/build_info.h"
59 #include "base/android/java_exception_reporter.h"
60 #include "base/android/path_utils.h"
61 #include "base/debug/leak_annotations.h"
62 #endif
63 #include "third_party/lss/linux_syscall_support.h"
64 
65 #if defined(OS_CHROMEOS)
66 #include "components/crash/core/app/crash_switches.h"
67 #include "services/service_manager/embedder/switches.h"  // nogncheck
68 #endif
69 
70 #if defined(ADDRESS_SANITIZER)
71 #include <ucontext.h>  // for getcontext().
72 #endif
73 
74 #if defined(OS_ANDROID)
75 #define STAT_STRUCT struct stat
76 #define FSTAT_FUNC fstat
77 #else
78 #define STAT_STRUCT struct kernel_stat
79 #define FSTAT_FUNC sys_fstat
80 #endif
81 
82 // Some versions of gcc are prone to warn about unused return values. In cases
83 // where we either a) know the call cannot fail, or b) there is nothing we
84 // can do when a call fails, we mark the return code as ignored. This avoids
85 // spurious compiler warnings.
86 #define IGNORE_RET(x) ignore_result(x)
87 
88 using crash_reporter::GetCrashReporterClient;
89 using google_breakpad::ExceptionHandler;
90 using google_breakpad::MinidumpDescriptor;
91 
92 namespace breakpad {
93 
94 namespace {
95 
96 #if defined(OS_CHROMEOS)
97 // An optional UNIX timestamp passed to us from session_manager. If set,
98 // session_manager thinks we are in a possible crash-loop and will log the user
99 // out if we crash again before the indicated time. We don't actually do much
100 // with this value, just pass it along to crash_reporter. This should really
101 // be a time_t, but it's basically an opaque value (we don't anything with it
102 // except pass it along) and we don't have functions to deal with time_t's well,
103 // while we do have functions to deal with uint64_t's.
104 uint64_t g_crash_loop_before_time = 0;
105 #else
106 const char kUploadURL[] = "https://clients2.google.com/cr/report";
107 #endif
108 
109 bool g_is_crash_reporter_enabled = false;
110 uint64_t g_process_start_time = 0;
111 pid_t g_pid = 0;
112 char* g_crash_log_path = nullptr;
113 ExceptionHandler* g_breakpad = nullptr;
114 
115 #if defined(ADDRESS_SANITIZER)
116 const char* g_asan_report_str = nullptr;
117 #endif
118 
119 bool g_use_crash_key_white_list = false;
120 const char* const* g_crash_key_white_list = nullptr;
121 
122 #if defined(OS_ANDROID)
123 #define G_DUMPS_SUPPRESSED_MAGIC 0x5AFECEDE
124 uint32_t g_dumps_suppressed = 0;
125 char* g_process_type = nullptr;
126 ExceptionHandler* g_microdump = nullptr;
127 int g_signal_code_pipe_fd = -1;
128 char* g_java_exception_info = nullptr;
129 
SetJavaExceptionInfo(const char * exception)130 void SetJavaExceptionInfo(const char* exception) {
131   if (g_java_exception_info) {
132     // The old exception should be cleared before setting a new one.
133     DCHECK(!exception);
134     free(g_java_exception_info);
135   }
136 
137   if (exception) {
138     g_java_exception_info = strndup(exception, 5 * 4096);
139   } else {
140     g_java_exception_info = nullptr;
141   }
142 }
143 
144 class MicrodumpInfo {
145  public:
MicrodumpInfo()146   MicrodumpInfo() : microdump_gpu_fingerprint_(nullptr) {}
147 
148   // The order in which SetGpuFingerprint and Initialize are called
149   // may be dependent on the timing of the availability of GPU
150   // information. For this reason, they can be called in either order,
151   // resulting in the same effect.
152   //
153   // The following restrictions apply, however:
154   // * Both methods must be called from the same thread.
155   // * Both methods must be called at most once.
156   //
157   // Microdumps will only be generated if Initialize is called. If
158   // SetGpuFingerprint has not been called called at the point at
159   // which a microdump is generated, then the GPU fingerprint will be
160   // UNKNOWN.
161   void SetGpuFingerprintForMicrodump(const std::string& gpu_fingerprint);
162   void Initialize(const std::string& process_type,
163                   const char* product_name,
164                   const char* product_version,
165                   const char* android_build_fp,
166                   const SanitizationInfo& sanitization_info);
167 
168  private:
169   base::ThreadChecker thread_checker_;
170   const char* microdump_gpu_fingerprint_;
171 };
172 
173 void SetMinidumpSanitizationFields(MinidumpDescriptor* minidump_descriptor,
174                                    const SanitizationInfo& sanitization_info);
175 
176 base::LazyInstance<MicrodumpInfo>::DestructorAtExit g_microdump_info =
177     LAZY_INSTANCE_INITIALIZER;
178 
179 #endif
180 
181 // Writes the value |v| as 16 hex characters to the memory pointed at by
182 // |output|.
write_uint64_hex(char * output,uint64_t v)183 void write_uint64_hex(char* output, uint64_t v) {
184   static const char hextable[] = "0123456789abcdef";
185 
186   for (int i = 15; i >= 0; --i) {
187     output[i] = hextable[v & 15];
188     v >>= 4;
189   }
190 }
191 
192 // The following helper functions are for calculating uptime.
193 
194 // Converts a struct timeval to milliseconds.
timeval_to_ms(struct timeval * tv)195 uint64_t timeval_to_ms(struct timeval *tv) {
196   uint64_t ret = tv->tv_sec;  // Avoid overflow by explicitly using a uint64_t.
197   ret *= 1000;
198   ret += tv->tv_usec / 1000;
199   return ret;
200 }
201 
202 // Converts a struct timeval to milliseconds.
kernel_timeval_to_ms(struct kernel_timeval * tv)203 uint64_t kernel_timeval_to_ms(struct kernel_timeval *tv) {
204   uint64_t ret = tv->tv_sec;  // Avoid overflow by explicitly using a uint64_t.
205   ret *= 1000;
206   ret += tv->tv_usec / 1000;
207   return ret;
208 }
209 
210 // String buffer size to use to convert a uint64_t to string.
211 const size_t kUint64StringSize = 21;
212 
SetProcessStartTime()213 void SetProcessStartTime() {
214   // Set the base process start time value.
215   struct timeval tv;
216   if (!gettimeofday(&tv, nullptr))
217     g_process_start_time = timeval_to_ms(&tv);
218   else
219     g_process_start_time = 0;
220 }
221 
222 // uint64_t version of my_int_len() from
223 // third_party/breakpad/breakpad/src/common/linux/linux_libc_support.h. Return
224 // the length of the given, non-negative integer when expressed in base 10.
my_uint64_len(uint64_t i)225 unsigned my_uint64_len(uint64_t i) {
226   if (!i)
227     return 1;
228 
229   unsigned len = 0;
230   while (i) {
231     len++;
232     i /= 10;
233   }
234 
235   return len;
236 }
237 
238 // uint64_t version of my_uitos() from
239 // third_party/breakpad/breakpad/src/common/linux/linux_libc_support.h. Convert
240 // a non-negative integer to a string (not null-terminated).
my_uint64tos(char * output,uint64_t i,unsigned i_len)241 void my_uint64tos(char* output, uint64_t i, unsigned i_len) {
242   for (unsigned index = i_len; index; --index, i /= 10)
243     output[index - 1] = '0' + (i % 10);
244 }
245 
246 #if !defined(OS_CHROMEOS)
my_isxdigit(char c)247 bool my_isxdigit(char c) {
248   return base::IsAsciiDigit(c) || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f');
249 }
250 #endif
251 
LengthWithoutTrailingSpaces(const char * str,size_t len)252 size_t LengthWithoutTrailingSpaces(const char* str, size_t len) {
253   while (len > 0 && str[len - 1] == ' ') {
254     len--;
255   }
256   return len;
257 }
258 
GetEnableCrashReporterSwitchParts(const base::CommandLine & command_line,std::vector<std::string> * switch_parts)259 bool GetEnableCrashReporterSwitchParts(const base::CommandLine& command_line,
260                                        std::vector<std::string>* switch_parts) {
261   std::string switch_value =
262       command_line.GetSwitchValueASCII(switches::kEnableCrashReporter);
263   std::vector<std::string> parts = base::SplitString(switch_value,
264                                                      ",",
265                                                      base::KEEP_WHITESPACE,
266                                                      base::SPLIT_WANT_ALL);
267   if (parts.size() != 2)
268     return false;
269 
270   *switch_parts = parts;
271   return true;
272 }
273 
274 #if !defined(OS_ANDROID)
SetChannelFromCommandLine(const base::CommandLine & command_line)275 void SetChannelFromCommandLine(const base::CommandLine& command_line) {
276   std::vector<std::string> switch_parts;
277   if (!GetEnableCrashReporterSwitchParts(command_line, &switch_parts))
278     return;
279 
280   SetChannelCrashKey(switch_parts[1]);
281 }
282 #endif
283 
SetClientIdFromCommandLine(const base::CommandLine & command_line)284 void SetClientIdFromCommandLine(const base::CommandLine& command_line) {
285   std::vector<std::string> switch_parts;
286   if (!GetEnableCrashReporterSwitchParts(command_line, &switch_parts))
287     return;
288 
289   GetCrashReporterClient()->SetCrashReporterClientIdFromGUID(switch_parts[0]);
290 }
291 
292 // MIME substrings.
293 #if defined(OS_CHROMEOS)
294 const char g_sep[] = ":";
295 #endif
296 const char g_rn[] = "\r\n";
297 const char g_form_data_msg[] = "Content-Disposition: form-data; name=\"";
298 const char g_quote_msg[] = "\"";
299 const char g_dashdash_msg[] = "--";
300 const char g_dump_msg[] = "upload_file_minidump\"; filename=\"dump\"";
301 #if defined(ADDRESS_SANITIZER)
302 const char g_log_msg[] = "upload_file_log\"; filename=\"log\"";
303 #endif
304 const char g_content_type_msg[] = "Content-Type: application/octet-stream";
305 
306 // MimeWriter manages an iovec for writing MIMEs to a file.
307 class MimeWriter {
308  public:
309   static const int kIovCapacity = 30;
310   static const size_t kMaxCrashChunkSize = 64;
311 
312   MimeWriter(int fd, const char* const mime_boundary);
313   ~MimeWriter();
314 
315   // Append boundary.
316   virtual void AddBoundary();
317 
318   // Append end of file boundary.
319   virtual void AddEnd();
320 
321   // Append key/value pair with specified sizes.
322   virtual void AddPairData(const char* msg_type,
323                            size_t msg_type_size,
324                            const char* msg_data,
325                            size_t msg_data_size);
326 
327   // Append key/value pair.
AddPairString(const char * msg_type,const char * msg_data)328   void AddPairString(const char* msg_type,
329                      const char* msg_data) {
330     AddPairData(msg_type, my_strlen(msg_type), msg_data, my_strlen(msg_data));
331   }
332 
333   // Append key/value pair, splitting value into chunks no larger than
334   // |chunk_size|. |chunk_size| cannot be greater than |kMaxCrashChunkSize|.
335   // The msg_type string will have a counter suffix to distinguish each chunk.
336   virtual void AddPairDataInChunks(const char* msg_type,
337                                    size_t msg_type_size,
338                                    const char* msg_data,
339                                    size_t msg_data_size,
340                                    size_t chunk_size,
341                                    bool strip_trailing_spaces);
342 
343   // Add binary file contents to be uploaded with the specified filename.
344   virtual void AddFileContents(const char* filename_msg,
345                                uint8_t* file_data,
346                                size_t file_size);
347 
348   // Flush any pending iovecs to the output file.
Flush()349   void Flush() {
350     IGNORE_RET(sys_writev(fd_, iov_, iov_index_));
351     iov_index_ = 0;
352   }
353 
354  protected:
355   void AddItem(const void* base, size_t size);
356   // Minor performance trade-off for easier-to-maintain code.
AddString(const char * str)357   void AddString(const char* str) {
358     AddItem(str, my_strlen(str));
359   }
360   void AddItemWithoutTrailingSpaces(const void* base, size_t size);
361 
362   struct kernel_iovec iov_[kIovCapacity];
363   int iov_index_;
364 
365   // Output file descriptor.
366   int fd_;
367 
368   const char* const mime_boundary_;
369 
370  private:
371   DISALLOW_COPY_AND_ASSIGN(MimeWriter);
372 };
373 
MimeWriter(int fd,const char * const mime_boundary)374 MimeWriter::MimeWriter(int fd, const char* const mime_boundary)
375     : iov_index_(0),
376       fd_(fd),
377       mime_boundary_(mime_boundary) {
378 }
379 
~MimeWriter()380 MimeWriter::~MimeWriter() {
381 }
382 
AddBoundary()383 void MimeWriter::AddBoundary() {
384   AddString(mime_boundary_);
385   AddString(g_rn);
386 }
387 
AddEnd()388 void MimeWriter::AddEnd() {
389   AddString(mime_boundary_);
390   AddString(g_dashdash_msg);
391   AddString(g_rn);
392 }
393 
AddPairData(const char * msg_type,size_t msg_type_size,const char * msg_data,size_t msg_data_size)394 void MimeWriter::AddPairData(const char* msg_type,
395                              size_t msg_type_size,
396                              const char* msg_data,
397                              size_t msg_data_size) {
398   AddString(g_form_data_msg);
399   AddItem(msg_type, msg_type_size);
400   AddString(g_quote_msg);
401   AddString(g_rn);
402   AddString(g_rn);
403   AddItem(msg_data, msg_data_size);
404   AddString(g_rn);
405 }
406 
AddPairDataInChunks(const char * msg_type,size_t msg_type_size,const char * msg_data,size_t msg_data_size,size_t chunk_size,bool strip_trailing_spaces)407 void MimeWriter::AddPairDataInChunks(const char* msg_type,
408                                      size_t msg_type_size,
409                                      const char* msg_data,
410                                      size_t msg_data_size,
411                                      size_t chunk_size,
412                                      bool strip_trailing_spaces) {
413   if (chunk_size > kMaxCrashChunkSize)
414     return;
415 
416   unsigned i = 0;
417   size_t done = 0, msg_length = msg_data_size;
418 
419   while (msg_length) {
420     char num[kUint64StringSize];
421     const unsigned num_len = my_uint_len(++i);
422     my_uitos(num, i, num_len);
423 
424     size_t chunk_len = std::min(chunk_size, msg_length);
425 
426     AddString(g_form_data_msg);
427     AddItem(msg_type, msg_type_size);
428     AddItem(num, num_len);
429     AddString(g_quote_msg);
430     AddString(g_rn);
431     AddString(g_rn);
432     if (strip_trailing_spaces) {
433       AddItemWithoutTrailingSpaces(msg_data + done, chunk_len);
434     } else {
435       AddItem(msg_data + done, chunk_len);
436     }
437     AddString(g_rn);
438     AddBoundary();
439     Flush();
440 
441     done += chunk_len;
442     msg_length -= chunk_len;
443   }
444 }
445 
AddFileContents(const char * filename_msg,uint8_t * file_data,size_t file_size)446 void MimeWriter::AddFileContents(const char* filename_msg, uint8_t* file_data,
447                                  size_t file_size) {
448   AddString(g_form_data_msg);
449   AddString(filename_msg);
450   AddString(g_rn);
451   AddString(g_content_type_msg);
452   AddString(g_rn);
453   AddString(g_rn);
454   AddItem(file_data, file_size);
455   AddString(g_rn);
456 }
457 
AddItem(const void * base,size_t size)458 void MimeWriter::AddItem(const void* base, size_t size) {
459   // Check if the iovec is full and needs to be flushed to output file.
460   if (iov_index_ == kIovCapacity) {
461     Flush();
462   }
463   iov_[iov_index_].iov_base = const_cast<void*>(base);
464   iov_[iov_index_].iov_len = size;
465   ++iov_index_;
466 }
467 
AddItemWithoutTrailingSpaces(const void * base,size_t size)468 void MimeWriter::AddItemWithoutTrailingSpaces(const void* base, size_t size) {
469   AddItem(base, LengthWithoutTrailingSpaces(static_cast<const char*>(base),
470                                             size));
471 }
472 
473 #if defined(OS_CHROMEOS)
474 // This subclass is used on Chromium OS to report crashes in a format easy for
475 // the central crash reporting facility to understand.
476 // Format is <name>:<data length in decimal>:<data>
477 class CrashReporterWriter : public MimeWriter {
478  public:
479   explicit CrashReporterWriter(int fd);
480 
481   void AddBoundary() override;
482 
483   void AddEnd() override;
484 
485   void AddPairData(const char* msg_type,
486                    size_t msg_type_size,
487                    const char* msg_data,
488                    size_t msg_data_size) override;
489 
490   void AddPairDataInChunks(const char* msg_type,
491                            size_t msg_type_size,
492                            const char* msg_data,
493                            size_t msg_data_size,
494                            size_t chunk_size,
495                            bool strip_trailing_spaces) override;
496 
497   void AddFileContents(const char* filename_msg,
498                        uint8_t* file_data,
499                        size_t file_size) override;
500 
501  private:
502   DISALLOW_COPY_AND_ASSIGN(CrashReporterWriter);
503 };
504 
505 
CrashReporterWriter(int fd)506 CrashReporterWriter::CrashReporterWriter(int fd) : MimeWriter(fd, "") {}
507 
508 // No-ops.
AddBoundary()509 void CrashReporterWriter::AddBoundary() {}
AddEnd()510 void CrashReporterWriter::AddEnd() {}
511 
AddPairData(const char * msg_type,size_t msg_type_size,const char * msg_data,size_t msg_data_size)512 void CrashReporterWriter::AddPairData(const char* msg_type,
513                                       size_t msg_type_size,
514                                       const char* msg_data,
515                                       size_t msg_data_size) {
516   char data[kUint64StringSize];
517   const unsigned data_len = my_uint_len(msg_data_size);
518   my_uitos(data, msg_data_size, data_len);
519 
520   AddItem(msg_type, msg_type_size);
521   AddString(g_sep);
522   AddItem(data, data_len);
523   AddString(g_sep);
524   AddItem(msg_data, msg_data_size);
525   Flush();
526 }
527 
AddPairDataInChunks(const char * msg_type,size_t msg_type_size,const char * msg_data,size_t msg_data_size,size_t chunk_size,bool strip_trailing_spaces)528 void CrashReporterWriter::AddPairDataInChunks(const char* msg_type,
529                                               size_t msg_type_size,
530                                               const char* msg_data,
531                                               size_t msg_data_size,
532                                               size_t chunk_size,
533                                               bool strip_trailing_spaces) {
534   if (chunk_size > kMaxCrashChunkSize)
535     return;
536 
537   unsigned i = 0;
538   size_t done = 0;
539   size_t msg_length = msg_data_size;
540 
541   while (msg_length) {
542     char num[kUint64StringSize];
543     const unsigned num_len = my_uint_len(++i);
544     my_uitos(num, i, num_len);
545 
546     size_t chunk_len = std::min(chunk_size, msg_length);
547 
548     size_t write_len = chunk_len;
549     if (strip_trailing_spaces) {
550       // Take care of this here because we need to know the exact length of
551       // what is going to be written.
552       write_len = LengthWithoutTrailingSpaces(msg_data + done, write_len);
553     }
554 
555     char data[kUint64StringSize];
556     const unsigned data_len = my_uint_len(write_len);
557     my_uitos(data, write_len, data_len);
558 
559     AddItem(msg_type, msg_type_size);
560     AddItem(num, num_len);
561     AddString(g_sep);
562     AddItem(data, data_len);
563     AddString(g_sep);
564     AddItem(msg_data + done, write_len);
565     Flush();
566 
567     done += chunk_len;
568     msg_length -= chunk_len;
569   }
570 }
571 
AddFileContents(const char * filename_msg,uint8_t * file_data,size_t file_size)572 void CrashReporterWriter::AddFileContents(const char* filename_msg,
573                                           uint8_t* file_data,
574                                           size_t file_size) {
575   char data[kUint64StringSize];
576   const unsigned data_len = my_uint_len(file_size);
577   my_uitos(data, file_size, data_len);
578 
579   AddString(filename_msg);
580   AddString(g_sep);
581   AddItem(data, data_len);
582   AddString(g_sep);
583   AddItem(file_data, file_size);
584   Flush();
585 }
586 #endif  // defined(OS_CHROMEOS)
587 
588 #if defined(OS_ANDROID)
589 // Writes the "package" field, which is in the format:
590 // $FIREBASE_APP_ID v$VERSION_CODE ($VERSION_NAME)
WriteAndroidPackage(MimeWriter & writer,base::android::BuildInfo * android_build_info)591 void WriteAndroidPackage(MimeWriter& writer,
592                          base::android::BuildInfo* android_build_info) {
593   // The actual size limits on packageId and versionName are quite generous.
594   // Limit to a reasonable size rather than allocating theoretical limits.
595   const int kMaxSize = 1024;
596   char buf[kMaxSize];
597 
598   // Not using sprintf to ensure no heap allocations.
599   my_strlcpy(buf, android_build_info->firebase_app_id(), kMaxSize);
600   my_strlcat(buf, " v", kMaxSize);
601   my_strlcat(buf, android_build_info->package_version_code(), kMaxSize);
602   my_strlcat(buf, " (", kMaxSize);
603   my_strlcat(buf, android_build_info->package_version_name(), kMaxSize);
604   my_strlcat(buf, ")", kMaxSize);
605 
606   writer.AddPairString("package", buf);
607 }
608 #endif  // defined(OS_ANDROID)
609 
610 #if defined(OS_ANDROID)
611 const char kGoogleBreakpad[] = "google-breakpad";
612 #endif
613 
WriteLog(const char * buf,size_t nbytes)614 size_t WriteLog(const char* buf, size_t nbytes) {
615 #if defined(OS_ANDROID)
616   return __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad, buf);
617 #else
618   return sys_write(2, buf, nbytes);
619 #endif
620 }
621 
WriteNewline()622 size_t WriteNewline() {
623   return WriteLog("\n", 1);
624 }
625 
626 #if defined(OS_ANDROID)
ShouldGenerateDump(void * context)627 bool ShouldGenerateDump(void *context) {
628   return g_dumps_suppressed != G_DUMPS_SUPPRESSED_MAGIC;
629 }
630 
AndroidLogWriteHorizontalRule()631 void AndroidLogWriteHorizontalRule() {
632   __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad,
633                       "### ### ### ### ### ### ### ### ### ### ### ### ###");
634 }
635 
636 // Android's native crash handler outputs a diagnostic tombstone to the device
637 // log. By returning false from the HandlerCallbacks, breakpad will reinstall
638 // the previous (i.e. native) signal handlers before returning from its own
639 // handler. A Chrome build fingerprint is written to the log, so that the
640 // specific build of Chrome and the location of the archived Chrome symbols can
641 // be determined directly from it.
FinalizeCrashDoneAndroid(bool is_browser_process)642 bool FinalizeCrashDoneAndroid(bool is_browser_process) {
643   base::android::BuildInfo* android_build_info =
644       base::android::BuildInfo::GetInstance();
645 
646   AndroidLogWriteHorizontalRule();
647   __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad,
648                       "Chrome build fingerprint:");
649   __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad,
650                       android_build_info->package_version_name());
651   __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad,
652                       android_build_info->package_version_code());
653   AndroidLogWriteHorizontalRule();
654 
655   if (!is_browser_process &&
656       android_build_info->sdk_int() >=
657           base::android::SDK_VERSION_JELLY_BEAN_MR2 &&
658       my_strcmp(android_build_info->build_type(), "eng") != 0 &&
659       my_strcmp(android_build_info->build_type(), "userdebug") != 0) {
660     // On JB MR2 and later, the system crash handler displays a dialog. For
661     // renderer crashes, this is a bad user experience and so this is disabled
662     // for user builds of Android.
663     // TODO(cjhopman): There should be some way to recover the crash stack from
664     // non-uploading user clients. See http://crbug.com/273706.
665     __android_log_write(ANDROID_LOG_WARN,
666                         kGoogleBreakpad,
667                         "Tombstones are disabled on JB MR2+ user builds.");
668     AndroidLogWriteHorizontalRule();
669     return true;
670   }
671   return false;
672 }
673 
MicrodumpCrashDone(const MinidumpDescriptor & minidump,void * context,bool succeeded)674 bool MicrodumpCrashDone(const MinidumpDescriptor& minidump,
675                         void* context,
676                         bool succeeded) {
677   // WARNING: this code runs in a compromised context. It may not call into
678   // libc nor allocate memory normally.
679   if (!succeeded) {
680     static const char msg[] = "Microdump crash handler failed.\n";
681     WriteLog(msg, sizeof(msg) - 1);
682     return false;
683   }
684 
685   const bool is_browser_process = (context != nullptr);
686   return FinalizeCrashDoneAndroid(is_browser_process);
687 }
688 #endif  // defined(OS_ANDROID)
689 
CrashDone(const MinidumpDescriptor & minidump,const bool upload,const bool should_finalize,const bool succeeded)690 bool CrashDone(const MinidumpDescriptor& minidump,
691                const bool upload,
692                const bool should_finalize,
693                const bool succeeded) {
694   // WARNING: this code runs in a compromised context. It may not call into
695   // libc nor allocate memory normally.
696   if (!succeeded) {
697     const char msg[] = "Failed to generate minidump.";
698     WriteLog(msg, sizeof(msg) - 1);
699     return false;
700   }
701 
702   DCHECK(!(upload && minidump.IsFD()));
703 
704   BreakpadInfo info = {0};
705   info.filename = minidump.path();
706   info.fd = minidump.fd();
707 #if defined(ADDRESS_SANITIZER)
708   google_breakpad::PageAllocator allocator;
709   const size_t log_path_len = my_strlen(minidump.path());
710   char* log_path = reinterpret_cast<char*>(allocator.Alloc(log_path_len + 1));
711   my_memcpy(log_path, minidump.path(), log_path_len);
712   my_memcpy(log_path + log_path_len - 4, ".log", 4);
713   log_path[log_path_len] = '\0';
714   info.log_filename = log_path;
715 #endif
716   info.process_type = "browser";
717   info.process_type_length = 7;
718   info.distro = base::g_linux_distro;
719   info.distro_length = my_strlen(base::g_linux_distro);
720   info.upload = upload;
721   info.process_start_time = g_process_start_time;
722   info.oom_size = base::g_oom_size;
723   info.pid = g_pid;
724   info.crash_keys = crash_reporter::internal::GetCrashKeyStorage();
725   HandleCrashDump(info);
726 #if defined(OS_ANDROID)
727   return !should_finalize ||
728          FinalizeCrashDoneAndroid(true /* is_browser_process */);
729 #else
730   return true;
731 #endif
732 }
733 
734 #if defined(OS_ANDROID)
735 // Wrapper function, do not add more code here.
MinidumpGenerated(const MinidumpDescriptor & minidump,void * context,bool succeeded)736 bool MinidumpGenerated(const MinidumpDescriptor& minidump,
737                        void* context,
738                        bool succeeded) {
739   return CrashDone(minidump, false, false, succeeded);
740 }
741 #endif
742 
743 // Wrapper function, do not add more code here.
CrashDoneNoUpload(const MinidumpDescriptor & minidump,void * context,bool succeeded)744 bool CrashDoneNoUpload(const MinidumpDescriptor& minidump,
745                        void* context,
746                        bool succeeded) {
747   return CrashDone(minidump, false, true, succeeded);
748 }
749 
750 #if !defined(OS_ANDROID)
751 // Wrapper function, do not add more code here.
CrashDoneUpload(const MinidumpDescriptor & minidump,void * context,bool succeeded)752 bool CrashDoneUpload(const MinidumpDescriptor& minidump,
753                      void* context,
754                      bool succeeded) {
755   return CrashDone(minidump, true, true, succeeded);
756 }
757 #endif
758 
DumpProcess()759 void DumpProcess() {
760 #if defined(OS_ANDROID)
761   // Don't use g_breakpad and g_microdump directly here, because their
762   // output might currently be suppressed.
763 
764   // If a breakpad handler is installed, but its target is a file
765   // descriptor, we can't generate a dump because we can't risk
766   // writing multiple minidumps to the FD, so it can only be used for
767   // dumps that are associated with a crash.
768   if (g_breakpad && !g_breakpad->minidump_descriptor().IsFD()) {
769     ExceptionHandler(g_breakpad->minidump_descriptor(),
770                      nullptr,
771                      CrashDoneNoUpload,
772                      nullptr,
773                      false, -1).WriteMinidump();
774   }
775   // If microdumps are enabled write also a microdump on the system log.
776   if (g_microdump) {
777     ExceptionHandler(g_microdump->minidump_descriptor(),
778                      nullptr,
779                      MicrodumpCrashDone,
780                      nullptr,
781                      false, -1).WriteMinidump();
782   }
783 #else
784   if (g_breakpad)
785     g_breakpad->WriteMinidump();
786 #endif
787 }
788 
789 #if defined(ADDRESS_SANITIZER)
790 extern "C"
791 void __asan_set_error_report_callback(void (*cb)(const char*));
792 
793 extern "C"
AsanLinuxBreakpadCallback(const char * report)794 void AsanLinuxBreakpadCallback(const char* report) {
795   g_asan_report_str = report;
796   // Send minidump here.
797   g_breakpad->SimulateSignalDelivery(SIGKILL);
798 }
799 #endif
800 
801 #if defined(OS_ANDROID)
EnableCrashDumping(bool unattended,const SanitizationInfo & sanitization_info)802 void EnableCrashDumping(bool unattended,
803                         const SanitizationInfo& sanitization_info) {
804 #else
805 void EnableCrashDumping(bool unattended) {
806 #endif  // defined(OS_ANDROID)
807   g_is_crash_reporter_enabled = true;
808 
809   base::FilePath tmp_path("/tmp");
810   base::PathService::Get(base::DIR_TEMP, &tmp_path);
811 
812   base::FilePath dumps_path(tmp_path);
813   if (GetCrashReporterClient()->GetCrashDumpLocation(&dumps_path)) {
814     base::FilePath logfile =
815         dumps_path.Append(GetCrashReporterClient()->GetReporterLogFilename());
816     std::string logfile_str = logfile.value();
817     const size_t crash_log_path_len = logfile_str.size() + 1;
818     g_crash_log_path = new char[crash_log_path_len];
819     strncpy(g_crash_log_path, logfile_str.c_str(), crash_log_path_len);
820   }
821   DCHECK(!g_breakpad);
822   MinidumpDescriptor minidump_descriptor(dumps_path.value());
823   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
824           switches::kFullMemoryCrashReport)) {
825     minidump_descriptor.set_size_limit(-1);  // unlimited.
826   } else {
827     minidump_descriptor.set_size_limit(kMaxMinidumpFileSize);
828   }
829 #if defined(OS_ANDROID)
830   unattended = true;  // Android never uploads directly.
831   SetMinidumpSanitizationFields(&minidump_descriptor, sanitization_info);
832 #endif
833   if (unattended) {
834     g_breakpad = new ExceptionHandler(
835         minidump_descriptor,
836 #if defined(OS_ANDROID)
837         ShouldGenerateDump,
838 #else
839         nullptr,
840 #endif
841         CrashDoneNoUpload,
842         nullptr,
843         true,  // Install handlers.
844         -1);   // Server file descriptor. -1 for in-process.
845     return;
846   }
847 
848 #if !defined(OS_ANDROID)
849   // Attended mode
850   g_breakpad = new ExceptionHandler(
851       minidump_descriptor,
852       nullptr,
853       CrashDoneUpload,
854       nullptr,
855       true,  // Install handlers.
856       -1);   // Server file descriptor. -1 for in-process.
857 #endif
858 }
859 
860 #if defined(OS_ANDROID)
861 bool WriteSignalCodeToPipe(const void* crash_context,
862                            size_t crash_context_size,
863                            void* context) {
864   if (g_signal_code_pipe_fd == -1)
865     return false;
866   int signo = INT_MAX;
867   if (crash_context_size == sizeof(ExceptionHandler::CrashContext)) {
868     const ExceptionHandler::CrashContext* eh_context =
869         static_cast<const ExceptionHandler::CrashContext*>(crash_context);
870     signo = eh_context->siginfo.si_signo;
871   }
872   sys_write(g_signal_code_pipe_fd, &signo, sizeof(signo));
873   IGNORE_RET(sys_close(g_signal_code_pipe_fd));
874   g_signal_code_pipe_fd = -1;
875   return false;
876 }
877 
878 bool CrashDoneInProcessNoUpload(
879     const google_breakpad::MinidumpDescriptor& descriptor,
880     void* context,
881     const bool succeeded) {
882   // WARNING: this code runs in a compromised context. It may not call into
883   // libc nor allocate memory normally.
884   if (!succeeded) {
885     if (ShouldGenerateDump(nullptr)) {
886       static const char msg[] = "Crash dump generation failed.\n";
887       WriteLog(msg, sizeof(msg) - 1);
888     }
889     return false;
890   }
891 
892   // Start constructing the message to send to the browser.
893   BreakpadInfo info = {0};
894   info.filename = nullptr;
895   info.fd = descriptor.fd();
896   info.process_type = g_process_type;
897   info.process_type_length = my_strlen(g_process_type);
898   info.distro = nullptr;
899   info.distro_length = 0;
900   info.upload = false;
901   info.process_start_time = g_process_start_time;
902   info.pid = g_pid;
903   info.crash_keys = crash_reporter::internal::GetCrashKeyStorage();
904   HandleCrashDump(info);
905   return FinalizeCrashDoneAndroid(false /* is_browser_process */);
906 }
907 
908 void EnableNonBrowserCrashDumping(const std::string& process_type,
909                                   int minidump_fd,
910                                   const SanitizationInfo& sanitization_info) {
911   // This will guarantee that the BuildInfo has been initialized and subsequent
912   // calls will not require memory allocation.
913   base::android::BuildInfo::GetInstance();
914   SetClientIdFromCommandLine(*base::CommandLine::ForCurrentProcess());
915 
916   // On Android, the current sandboxing uses process isolation, in which the
917   // child process runs with a different UID. That breaks the normal crash
918   // reporting where the browser process generates the minidump by inspecting
919   // the child process. This is because the browser process now does not have
920   // the permission to access the states of the child process (as it has a
921   // different UID).
922   // TODO(jcivelli): http://b/issue?id=6776356 we should use a watchdog
923   // process forked from the renderer process that generates the minidump.
924   if (minidump_fd == -1) {
925     LOG(ERROR) << "Minidump file descriptor not found, crash reporting will "
926         " not work.";
927     return;
928   }
929   SetProcessStartTime();
930   g_pid = getpid();
931 
932   g_is_crash_reporter_enabled = true;
933   // Save the process type (it is leaked).
934   const size_t process_type_len = process_type.size() + 1;
935   g_process_type = new char[process_type_len];
936   strncpy(g_process_type, process_type.c_str(), process_type_len);
937 
938   MinidumpDescriptor descriptor(minidump_fd);
939   SetMinidumpSanitizationFields(&descriptor, sanitization_info);
940   g_breakpad =
941       new ExceptionHandler(descriptor, ShouldGenerateDump,
942                            CrashDoneInProcessNoUpload, nullptr, true, -1);
943 }
944 
945 void MicrodumpInfo::SetGpuFingerprintForMicrodump(
946     const std::string& gpu_fingerprint) {
947   DCHECK(thread_checker_.CalledOnValidThread());
948   DCHECK(!microdump_gpu_fingerprint_);
949   microdump_gpu_fingerprint_ = strdup(gpu_fingerprint.c_str());
950   ANNOTATE_LEAKING_OBJECT_PTR(microdump_gpu_fingerprint_);
951 
952   if (g_microdump) {
953     MinidumpDescriptor descriptor(g_microdump->minidump_descriptor());
954     descriptor.microdump_extra_info()->gpu_fingerprint =
955         microdump_gpu_fingerprint_;
956     g_microdump->set_minidump_descriptor(descriptor);
957   }
958 }
959 
960 void SetMinidumpSanitizationFields(MinidumpDescriptor* minidump_descriptor,
961                                    const SanitizationInfo& sanitization_info) {
962   minidump_descriptor->set_skip_dump_if_principal_mapping_not_referenced(
963       sanitization_info.skip_dump_if_principal_mapping_not_referenced);
964   minidump_descriptor->set_address_within_principal_mapping(
965       sanitization_info.address_within_principal_mapping);
966   minidump_descriptor->set_sanitize_stacks(
967       sanitization_info.should_sanitize_dumps);
968 }
969 
970 void MicrodumpInfo::Initialize(const std::string& process_type,
971                                const char* product_name,
972                                const char* product_version,
973                                const char* android_build_fp,
974                                const SanitizationInfo& sanitization_info) {
975   DCHECK(thread_checker_.CalledOnValidThread());
976   DCHECK(!g_microdump);
977   // |process_type| for webview's browser process is kBrowserProcessType or
978   // kWebViewSingleProcessType. |process_type| for chrome's browser process is
979   // an empty string.
980   bool is_browser_process = process_type.empty() ||
981                             process_type == kWebViewSingleProcessType ||
982                             process_type == kBrowserProcessType;
983 
984   MinidumpDescriptor descriptor(MinidumpDescriptor::kMicrodumpOnConsole);
985   google_breakpad::MicrodumpExtraInfo* microdump_extra_info =
986       descriptor.microdump_extra_info();
987 
988   if (product_name && product_version) {
989     microdump_extra_info->product_info =
990         strdup((product_name + std::string(":") + product_version).c_str());
991     ANNOTATE_LEAKING_OBJECT_PTR(microdump_extra_info->product_info);
992   }
993 
994   microdump_extra_info->process_type =
995       strdup(process_type.empty() ? kBrowserProcessType : process_type.c_str());
996   ANNOTATE_LEAKING_OBJECT_PTR(microdump_extra_info->process_type);
997 
998   if (android_build_fp) {
999     microdump_extra_info->build_fingerprint = strdup(android_build_fp);
1000     ANNOTATE_LEAKING_OBJECT_PTR(microdump_extra_info->build_fingerprint);
1001   }
1002 
1003   SetMinidumpSanitizationFields(&descriptor, sanitization_info);
1004   microdump_extra_info->gpu_fingerprint = microdump_gpu_fingerprint_;
1005 
1006   g_microdump =
1007       new ExceptionHandler(descriptor, ShouldGenerateDump, MicrodumpCrashDone,
1008                            reinterpret_cast<void*>(is_browser_process),
1009                            true,  // Install handlers.
1010                            -1);   // Server file descriptor. -1 for in-process.
1011 
1012   if (!is_browser_process) {
1013     g_signal_code_pipe_fd =
1014         GetCrashReporterClient()->GetAndroidCrashSignalFD();
1015     if (g_signal_code_pipe_fd != -1)
1016       g_microdump->set_crash_handler(WriteSignalCodeToPipe);
1017   }
1018 }
1019 
1020 #else
1021 // Non-Browser = Extension, Gpu, Plugins, Ppapi and Renderer
1022 class NonBrowserCrashHandler : public google_breakpad::CrashGenerationClient {
1023  public:
1024   NonBrowserCrashHandler()
1025       : server_fd_(base::GlobalDescriptors::GetInstance()->Get(
1026             service_manager::kCrashDumpSignal)) {}
1027 
1028   ~NonBrowserCrashHandler() override {}
1029 
1030   bool RequestDump(const void* crash_context,
1031                    size_t crash_context_size) override {
1032     int fds[2] = { -1, -1 };
1033     if (sys_socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
1034       static const char msg[] = "Failed to create socket for crash dumping.\n";
1035       WriteLog(msg, sizeof(msg) - 1);
1036       return false;
1037     }
1038 
1039     // Start constructing the message to send to the browser.
1040     char b;  // Dummy variable for sys_read below.
1041     const char* b_addr = &b;  // Get the address of |b| so we can create the
1042                               // expected /proc/[pid]/syscall content in the
1043                               // browser to convert namespace tids.
1044 
1045     // The length of the control message:
1046     static const unsigned kControlMsgSize = sizeof(int);
1047     static const unsigned kControlMsgSpaceSize = CMSG_SPACE(kControlMsgSize);
1048     static const unsigned kControlMsgLenSize = CMSG_LEN(kControlMsgSize);
1049 
1050     struct kernel_msghdr msg;
1051     my_memset(&msg, 0, sizeof(struct kernel_msghdr));
1052     struct kernel_iovec iov[kCrashIovSize];
1053     iov[0].iov_base = const_cast<void*>(crash_context);
1054     iov[0].iov_len = crash_context_size;
1055     iov[1].iov_base = &b_addr;
1056     iov[1].iov_len = sizeof(b_addr);
1057     iov[2].iov_base = &fds[0];
1058     iov[2].iov_len = sizeof(fds[0]);
1059     iov[3].iov_base = &g_process_start_time;
1060     iov[3].iov_len = sizeof(g_process_start_time);
1061     iov[4].iov_base = &base::g_oom_size;
1062     iov[4].iov_len = sizeof(base::g_oom_size);
1063     google_breakpad::SerializedNonAllocatingMap* serialized_map;
1064     iov[5].iov_len = crash_reporter::internal::GetCrashKeyStorage()->Serialize(
1065         const_cast<const google_breakpad::SerializedNonAllocatingMap**>(
1066             &serialized_map));
1067     iov[5].iov_base = serialized_map;
1068 #if !defined(ADDRESS_SANITIZER)
1069     static_assert(5 == kCrashIovSize - 1, "kCrashIovSize should equal 6");
1070 #else
1071     if (g_asan_report_str != nullptr) {
1072       iov[6].iov_base = const_cast<char*>(g_asan_report_str);
1073     } else {
1074       static char empty_asan_report[kMaxAsanReportSize + 1];
1075       iov[6].iov_base = empty_asan_report;
1076     }
1077     iov[6].iov_len = kMaxAsanReportSize + 1;
1078     static_assert(6 == kCrashIovSize - 1, "kCrashIovSize should equal 7");
1079 #endif
1080 
1081     msg.msg_iov = iov;
1082     msg.msg_iovlen = kCrashIovSize;
1083     char cmsg[kControlMsgSpaceSize];
1084     my_memset(cmsg, 0, kControlMsgSpaceSize);
1085     msg.msg_control = cmsg;
1086     msg.msg_controllen = sizeof(cmsg);
1087 
1088     struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg);
1089     hdr->cmsg_level = SOL_SOCKET;
1090     hdr->cmsg_type = SCM_RIGHTS;
1091     hdr->cmsg_len = kControlMsgLenSize;
1092     ((int*)CMSG_DATA(hdr))[0] = fds[1];
1093 
1094     if (HANDLE_EINTR(sys_sendmsg(server_fd_, &msg, 0)) < 0) {
1095       static const char errmsg[] = "Failed to tell parent about crash.\n";
1096       WriteLog(errmsg, sizeof(errmsg) - 1);
1097       IGNORE_RET(sys_close(fds[0]));
1098       IGNORE_RET(sys_close(fds[1]));
1099       return false;
1100     }
1101     IGNORE_RET(sys_close(fds[1]));
1102 
1103     if (HANDLE_EINTR(sys_read(fds[0], &b, 1)) != 1) {
1104       static const char errmsg[] = "Parent failed to complete crash dump.\n";
1105       WriteLog(errmsg, sizeof(errmsg) - 1);
1106     }
1107     IGNORE_RET(sys_close(fds[0]));
1108 
1109     return true;
1110   }
1111 
1112  private:
1113   // The pipe FD to the browser process, which will handle the crash dumping.
1114   const int server_fd_;
1115 
1116   DISALLOW_COPY_AND_ASSIGN(NonBrowserCrashHandler);
1117 };
1118 
1119 void EnableNonBrowserCrashDumping() {
1120   g_is_crash_reporter_enabled = true;
1121   // We deliberately leak this object.
1122   DCHECK(!g_breakpad);
1123 
1124   g_breakpad = new ExceptionHandler(
1125       MinidumpDescriptor("/tmp"),  // Unused but needed or Breakpad will assert.
1126       nullptr,
1127       nullptr,
1128       nullptr,
1129       true,
1130       -1);
1131   g_breakpad->set_crash_generation_client(new NonBrowserCrashHandler());
1132 }
1133 #endif  // defined(OS_ANDROID)
1134 
1135 bool IsInWhiteList(const base::StringPiece& key) {
1136   DCHECK(g_crash_key_white_list);
1137   for (size_t i = 0; g_crash_key_white_list[i]; ++i) {
1138     if (0 == my_strcmp(g_crash_key_white_list[i], key.data())) {
1139       return true;
1140     }
1141   }
1142   return false;
1143 }
1144 
1145 // GetCrashReporterClient() cannot call any Set methods until after
1146 // InitCrashKeys().
1147 void InitCrashKeys() {
1148   crash_reporter::InitializeCrashKeys();
1149   g_use_crash_key_white_list =
1150       GetCrashReporterClient()->UseCrashKeysWhiteList();
1151   g_crash_key_white_list = GetCrashReporterClient()->GetCrashKeyWhiteList();
1152 }
1153 
1154 void SetCrashLoopBeforeTime(const std::string& process_type,
1155                             const base::CommandLine& parsed_command_line) {
1156 #if defined(OS_CHROMEOS)
1157   std::string crash_loop_before = parsed_command_line.GetSwitchValueASCII(
1158       crash_reporter::switches::kCrashLoopBefore);
1159   if (crash_loop_before.empty()) {
1160     return;
1161   }
1162 
1163   if (!base::StringToUint64(crash_loop_before, &g_crash_loop_before_time)) {
1164     LOG(WARNING) << "Could not convert --crash-loop-before="
1165                  << crash_loop_before << " to integer";
1166     g_crash_loop_before_time = 0;
1167   }
1168 #endif  // defined(OS_CHROMEOS)
1169 }
1170 
1171 // Miscellaneous initialization functions to call after Breakpad has been
1172 // enabled.
1173 void PostEnableBreakpadInitialization(
1174     const std::string& process_type,
1175     const base::CommandLine& parsed_command_line) {
1176   SetProcessStartTime();
1177   g_pid = getpid();
1178   SetCrashLoopBeforeTime(process_type, parsed_command_line);
1179 
1180   base::debug::SetDumpWithoutCrashingFunction(&DumpProcess);
1181 #if defined(ADDRESS_SANITIZER)
1182   // Register the callback for AddressSanitizer error reporting.
1183   __asan_set_error_report_callback(AsanLinuxBreakpadCallback);
1184 #endif
1185 }
1186 
1187 }  // namespace
1188 
LoadDataFromFD(google_breakpad::PageAllocator & allocator,int fd,bool close_fd,uint8_t ** file_data,size_t * size)1189 void LoadDataFromFD(google_breakpad::PageAllocator& allocator,
1190                     int fd, bool close_fd, uint8_t** file_data, size_t* size) {
1191   STAT_STRUCT st;
1192   if (FSTAT_FUNC(fd, &st) != 0) {
1193     static const char msg[] = "Cannot upload crash dump: stat failed\n";
1194     WriteLog(msg, sizeof(msg) - 1);
1195     if (close_fd)
1196       IGNORE_RET(sys_close(fd));
1197     return;
1198   }
1199 
1200   *file_data = reinterpret_cast<uint8_t*>(allocator.Alloc(st.st_size));
1201   if (!(*file_data)) {
1202     static const char msg[] = "Cannot upload crash dump: cannot alloc\n";
1203     WriteLog(msg, sizeof(msg) - 1);
1204     if (close_fd)
1205       IGNORE_RET(sys_close(fd));
1206     return;
1207   }
1208   my_memset(*file_data, 0xf, st.st_size);
1209 
1210   *size = st.st_size;
1211   int byte_read = sys_read(fd, *file_data, *size);
1212   if (byte_read == -1) {
1213     static const char msg[] = "Cannot upload crash dump: read failed\n";
1214     WriteLog(msg, sizeof(msg) - 1);
1215     if (close_fd)
1216       IGNORE_RET(sys_close(fd));
1217     return;
1218   }
1219 
1220   if (close_fd)
1221     IGNORE_RET(sys_close(fd));
1222 }
1223 
LoadDataFromFile(google_breakpad::PageAllocator & allocator,const char * filename,int * fd,uint8_t ** file_data,size_t * size)1224 void LoadDataFromFile(google_breakpad::PageAllocator& allocator,
1225                       const char* filename,
1226                       int* fd, uint8_t** file_data, size_t* size) {
1227   // WARNING: this code runs in a compromised context. It may not call into
1228   // libc nor allocate memory normally.
1229   *fd = sys_open(filename, O_RDONLY, 0);
1230   *size = 0;
1231 
1232   if (*fd < 0) {
1233     static const char msg[] = "Cannot upload crash dump: failed to open\n";
1234     WriteLog(msg, sizeof(msg) - 1);
1235     return;
1236   }
1237 
1238   LoadDataFromFD(allocator, *fd, true, file_data, size);
1239 }
1240 
1241 // Concatenates a |prefix| and a |number| to get a string like "--foo=123" or
1242 // "/dev/fd/4". Safe to run in a compromised context. The returned memory is
1243 // internally owned by |allocator|.
StringFromPrefixAndUint(const char * prefix,uint64_t number,google_breakpad::PageAllocator * allocator)1244 char* StringFromPrefixAndUint(const char* prefix,
1245                               uint64_t number,
1246                               google_breakpad::PageAllocator* allocator) {
1247   // Convert the number to a string.
1248   char number_buf[kUint64StringSize];
1249   const unsigned number_len = my_uint64_len(number);
1250   my_uint64tos(number_buf, number, number_len);
1251   number_buf[number_len] = '\0';
1252 
1253   // Concatenate the prefix and number.
1254   size_t output_len = my_strlen(prefix) + my_strlen(number_buf) + 1;
1255   char* output = reinterpret_cast<char*>(allocator->Alloc(output_len));
1256   my_strlcpy(output, prefix, output_len);
1257   my_strlcat(output, number_buf, output_len);
1258   return output;
1259 }
1260 
1261 // Spawn the appropriate upload process for the current OS:
1262 // - generic Linux invokes wget.
1263 // - Chrome OS invokes crash_reporter. Crashes are uploaded by a separate
1264 //   crash_sender script that runs periodically.
1265 // |dumpfile| is the path to the dump data file.
1266 // |mime_boundary| is only used on Linux.
1267 // |exe_buf| is only used on CrOS and is the crashing process' name.
1268 // |upload_status_fd| is the file descriptor of a pipe that will receive:
1269 // - On Linux, the crash report id
1270 // - On Chrome OS, the magic crash complete string.
ExecUploadProcessOrTerminate(const BreakpadInfo & info,const char * dumpfile,const char * mime_boundary,const char * exe_buf,int upload_status_fd,google_breakpad::PageAllocator * allocator)1271 void ExecUploadProcessOrTerminate(const BreakpadInfo& info,
1272                                   const char* dumpfile,
1273                                   const char* mime_boundary,
1274                                   const char* exe_buf,
1275                                   int upload_status_fd,
1276                                   google_breakpad::PageAllocator* allocator) {
1277 #if defined(OS_CHROMEOS)
1278   // CrOS uses crash_reporter instead of wget to report crashes,
1279   // it needs to know where the crash dump lives and the pid and uid of the
1280   // crashing process.
1281   static const char kCrashReporterBinary[] = "/sbin/crash_reporter";
1282 
1283   // crash_reporter writes output to stdout. Connect it to the status pipe fd.
1284   if (sys_dup2(upload_status_fd, STDOUT_FILENO) == -1) {
1285     const char err[] = "dup2 failed\n";
1286     WriteLog(err, sizeof(err) - 1);
1287     // Continue anyway, as crash_report may succeed even if we can't read its
1288     // status.
1289   }
1290 
1291   const char kChromeFlag[] = "--chrome=";
1292   size_t buf_len = my_strlen(dumpfile) + sizeof(kChromeFlag);
1293   char* chrome_flag = reinterpret_cast<char*>(allocator->Alloc(buf_len));
1294   chrome_flag[0] = '\0';
1295   my_strlcat(chrome_flag, kChromeFlag, buf_len);
1296   my_strlcat(chrome_flag, dumpfile, buf_len);
1297 
1298   char* pid_flag = StringFromPrefixAndUint("--pid=", info.pid, allocator);
1299   char* uid_flag = StringFromPrefixAndUint("--uid=", geteuid(), allocator);
1300 
1301   const char kExeBuf[] = "--exe=";
1302   buf_len = my_strlen(exe_buf) + sizeof(kExeBuf);
1303   char* exe_flag = reinterpret_cast<char*>(allocator->Alloc(buf_len));
1304   exe_flag[0] = '\0';
1305   my_strlcat(exe_flag, kExeBuf, buf_len);
1306   my_strlcat(exe_flag, exe_buf, buf_len);
1307 
1308   char* crash_loop_before_flag = nullptr;
1309   if (g_crash_loop_before_time != 0) {
1310     crash_loop_before_flag = StringFromPrefixAndUint(
1311         "--crash_loop_before=", g_crash_loop_before_time, allocator);
1312   }
1313 
1314   const char* args[] = {
1315       kCrashReporterBinary,
1316       chrome_flag,
1317       pid_flag,
1318       uid_flag,
1319       exe_flag,
1320       crash_loop_before_flag,  // Leave last, might be nullptr.
1321       nullptr,
1322   };
1323   static const char msg[] = "Cannot upload crash dump: cannot exec "
1324                             "/sbin/crash_reporter\n";
1325 
1326 #else  // defined(OS_CHROMEOS)
1327 
1328   // Compress |dumpfile| with gzip.
1329   const pid_t gzip_child = sys_fork();
1330   if (gzip_child < 0) {
1331     static const char msg[] = "sys_fork() for gzip process failed.\n";
1332     WriteLog(msg, sizeof(msg) - 1);
1333     sys__exit(1);
1334   }
1335   if (!gzip_child) {
1336     // gzip process.
1337     const char* args[] = {
1338       "/bin/gzip",
1339       "-f",  // Do not prompt to verify before overwriting.
1340       dumpfile,
1341       nullptr,
1342     };
1343     execve(args[0], const_cast<char**>(args), environ);
1344     static const char msg[] = "Cannot exec gzip.\n";
1345     WriteLog(msg, sizeof(msg) - 1);
1346     sys__exit(1);
1347   }
1348   // Wait for gzip process.
1349   int status = 0;
1350   if (sys_waitpid(gzip_child, &status, 0) != gzip_child ||
1351       !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
1352     static const char msg[] = "sys_waitpid() for gzip process failed.\n";
1353     WriteLog(msg, sizeof(msg) - 1);
1354     sys_kill(gzip_child, SIGKILL);
1355     sys__exit(1);
1356   }
1357 
1358   static const char kGzipExtension[] = ".gz";
1359   const size_t gzip_file_size = my_strlen(dumpfile) + sizeof(kGzipExtension);
1360   char* const gzip_file = reinterpret_cast<char*>(allocator->Alloc(
1361       gzip_file_size));
1362   my_strlcpy(gzip_file, dumpfile, gzip_file_size);
1363   my_strlcat(gzip_file, kGzipExtension, gzip_file_size);
1364 
1365   // Rename |gzip_file| to |dumpfile| (the original file was deleted by gzip).
1366   if (rename(gzip_file, dumpfile)) {
1367     static const char msg[] = "Failed to rename gzipped file.\n";
1368     WriteLog(msg, sizeof(msg) - 1);
1369     sys__exit(1);
1370   }
1371 
1372   // The --header argument to wget looks like:
1373   //   --header=Content-Encoding: gzip
1374   //   --header=Content-Type: multipart/form-data; boundary=XYZ
1375   // where the boundary has two fewer leading '-' chars
1376   static const char header_content_encoding[] =
1377       "--header=Content-Encoding: gzip";
1378   static const char header_msg[] =
1379       "--header=Content-Type: multipart/form-data; boundary=";
1380   const size_t header_content_type_size =
1381       sizeof(header_msg) - 1 + my_strlen(mime_boundary) - 2 + 1;
1382   char* const header_content_type = reinterpret_cast<char*>(allocator->Alloc(
1383       header_content_type_size));
1384   my_strlcpy(header_content_type, header_msg, header_content_type_size);
1385   my_strlcat(header_content_type, mime_boundary + 2, header_content_type_size);
1386 
1387   // The --post-file argument to wget looks like:
1388   //   --post-file=/tmp/...
1389   static const char post_file_msg[] = "--post-file=";
1390   const size_t post_file_size =
1391       sizeof(post_file_msg) - 1 + my_strlen(dumpfile) + 1;
1392   char* const post_file = reinterpret_cast<char*>(allocator->Alloc(
1393       post_file_size));
1394   my_strlcpy(post_file, post_file_msg, post_file_size);
1395   my_strlcat(post_file, dumpfile, post_file_size);
1396 
1397   // Write the wget status output to the status pipe file descriptor path.
1398   char* status_fd_path =
1399       StringFromPrefixAndUint("/dev/fd/", upload_status_fd, allocator);
1400 
1401   static const char kWgetBinary[] = "/usr/bin/wget";
1402   const char* args[] = {
1403     kWgetBinary,
1404     header_content_encoding,
1405     header_content_type,
1406     post_file,
1407     kUploadURL,
1408     "--timeout=10",  // Set a timeout so we don't hang forever.
1409     "--tries=1",     // Don't retry if the upload fails.
1410     "-O",  // Output reply to the file descriptor path.
1411     status_fd_path,
1412     nullptr,
1413   };
1414   static const char msg[] = "Cannot upload crash dump: cannot exec "
1415                             "/usr/bin/wget\n";
1416 #endif  // defined(OS_CHROMEOS)
1417 
1418   execve(args[0], const_cast<char**>(args), environ);
1419   WriteLog(msg, sizeof(msg) - 1);
1420   sys__exit(1);
1421 }
1422 
1423 // Runs in the helper process to wait for the upload process running
1424 // ExecUploadProcessOrTerminate() to finish. Returns the number of bytes written
1425 // to |fd| and save the written contents to |buf|.
1426 // |buf| needs to be big enough to hold |bytes_to_read| + 1 characters.
WaitForCrashReportUploadProcess(int fd,size_t bytes_to_read,char * buf)1427 size_t WaitForCrashReportUploadProcess(int fd, size_t bytes_to_read,
1428                                        char* buf) {
1429   size_t bytes_read = 0;
1430 
1431   // Upload should finish in about 10 seconds. Add a few more 500 ms
1432   // internals to account for process startup time.
1433   for (size_t wait_count = 0; wait_count < 24; ++wait_count) {
1434     struct kernel_pollfd poll_fd;
1435     poll_fd.fd = fd;
1436     poll_fd.events = POLLIN | POLLPRI | POLLERR;
1437     int ret = sys_poll(&poll_fd, 1, 500);
1438     if (ret < 0) {
1439       // Error
1440       break;
1441     }
1442     if (ret > 0) {
1443       // There is data to read.
1444       ssize_t len = HANDLE_EINTR(
1445           sys_read(fd, buf + bytes_read, bytes_to_read - bytes_read));
1446       if (len < 0)
1447         break;
1448       bytes_read += len;
1449       if (bytes_read == bytes_to_read)
1450         break;
1451     }
1452     // |ret| == 0 -> timed out, continue waiting.
1453     // or |bytes_read| < |bytes_to_read| still, keep reading.
1454   }
1455   buf[bytes_to_read] = 0;  // Always NUL terminate the buffer.
1456   return bytes_read;
1457 }
1458 
1459 // |buf| should be |expected_len| + 1 characters in size and nullptr terminated.
IsValidCrashReportId(const char * buf,size_t bytes_read,size_t expected_len)1460 bool IsValidCrashReportId(const char* buf, size_t bytes_read,
1461                           size_t expected_len) {
1462   if (bytes_read != expected_len) {
1463     static const char msg[] = "Unexpected crash report id length\n";
1464     WriteLog(msg, sizeof(msg) - 1);
1465     return false;
1466   }
1467 #if defined(OS_CHROMEOS)
1468   // See kSuccessMagic in platform2/crash-reporter/chrome_collector.cc.
1469   return my_strcmp(buf, "_sys_cr_finished") == 0;
1470 #else
1471   for (size_t i = 0; i < bytes_read; ++i) {
1472     if (!my_isxdigit(buf[i]))
1473       return false;
1474   }
1475   return true;
1476 #endif
1477 }
1478 
1479 // |buf| should be |expected_len| + 1 characters in size and nullptr terminated.
HandleCrashReportId(const char * buf,size_t bytes_read,size_t expected_len)1480 void HandleCrashReportId(const char* buf, size_t bytes_read,
1481                          size_t expected_len) {
1482   WriteNewline();
1483   if (!IsValidCrashReportId(buf, bytes_read, expected_len)) {
1484 #if defined(OS_CHROMEOS)
1485     static const char msg[] =
1486         "System crash_reporter failed to process crash report.";
1487 #else
1488     static const char msg[] = "Failed to get crash dump id.";
1489 #endif
1490     WriteLog(msg, sizeof(msg) - 1);
1491     WriteNewline();
1492 
1493     static const char id_msg[] = "Report Id: ";
1494     WriteLog(id_msg, sizeof(id_msg) - 1);
1495     WriteLog(buf, bytes_read);
1496     WriteNewline();
1497     return;
1498   }
1499 
1500 #if defined(OS_CHROMEOS)
1501   static const char msg[] = "Crash dump received by crash_reporter\n";
1502   WriteLog(msg, sizeof(msg) - 1);
1503 #else
1504   // Write crash dump id to stderr.
1505   static const char msg[] = "Crash dump id: ";
1506   WriteLog(msg, sizeof(msg) - 1);
1507   WriteLog(buf, my_strlen(buf));
1508   WriteNewline();
1509 
1510   // Write crash dump id to crash log as: seconds_since_epoch,crash_id
1511   struct kernel_timeval tv;
1512   if (g_crash_log_path && !sys_gettimeofday(&tv, nullptr)) {
1513     uint64_t time = kernel_timeval_to_ms(&tv) / 1000;
1514     char time_str[kUint64StringSize];
1515     const unsigned time_len = my_uint64_len(time);
1516     my_uint64tos(time_str, time, time_len);
1517 
1518     const int kLogOpenFlags = O_CREAT | O_WRONLY | O_APPEND | O_CLOEXEC;
1519     int log_fd = sys_open(g_crash_log_path, kLogOpenFlags, 0600);
1520     if (log_fd > 0) {
1521       sys_write(log_fd, time_str, time_len);
1522       sys_write(log_fd, ",", 1);
1523       sys_write(log_fd, buf, my_strlen(buf));
1524       sys_write(log_fd, "\n", 1);
1525       IGNORE_RET(sys_close(log_fd));
1526     }
1527   }
1528 #endif
1529 }
1530 
1531 #if defined(OS_CHROMEOS)
GetCrashingProcessName(const BreakpadInfo & info,google_breakpad::PageAllocator * allocator)1532 const char* GetCrashingProcessName(const BreakpadInfo& info,
1533                                    google_breakpad::PageAllocator* allocator) {
1534   // Symlink to process binary is at /proc/###/exe.
1535   char linkpath[kUint64StringSize + sizeof("/proc/") + sizeof("/exe")] =
1536     "/proc/";
1537   uint64_t pid_value_len = my_uint64_len(info.pid);
1538   my_uint64tos(linkpath + sizeof("/proc/") - 1, info.pid, pid_value_len);
1539   linkpath[sizeof("/proc/") - 1 + pid_value_len] = '\0';
1540   my_strlcat(linkpath, "/exe", sizeof(linkpath));
1541 
1542   const int kMaxSize = 4096;
1543   char* link = reinterpret_cast<char*>(allocator->Alloc(kMaxSize));
1544   if (link) {
1545     ssize_t size = readlink(linkpath, link, kMaxSize);
1546     if (size < kMaxSize && size > 0) {
1547       // readlink(2) doesn't add a terminating NUL, so do it now.
1548       link[size] = '\0';
1549 
1550       const char* name = my_strrchr(link, '/');
1551       if (name)
1552         return name + 1;
1553       return link;
1554     }
1555   }
1556   // Either way too long, or a read error.
1557   return "chrome-crash-unknown-process";
1558 }
1559 #endif  // defined(OS_CHROMEOS)
1560 
1561 // Attempts to close all open file descriptors other than stdin, stdout and
1562 // stderr (0, 1, and 2).
CloseAllFileDescriptors()1563 void CloseAllFileDescriptors() {
1564   const int fd = sys_open("/proc/self/fd", O_DIRECTORY | O_RDONLY, 0);
1565   if (fd < 0) {
1566     for (unsigned i = 3; i < 8192; ++i)
1567       IGNORE_RET(sys_close(i));
1568   } else {
1569     google_breakpad::DirectoryReader reader(fd);
1570     const char* name;
1571     while (reader.GetNextEntry(&name)) {
1572       int i;
1573       if (my_strtoui(&i, name) && i > 2 && i != fd)
1574         IGNORE_RET(sys_close(i));
1575       reader.PopEntry();
1576     }
1577 
1578     IGNORE_RET(sys_close(fd));
1579   }
1580 }
1581 
HandleCrashDump(const BreakpadInfo & info)1582 void HandleCrashDump(const BreakpadInfo& info) {
1583   int dumpfd;
1584   bool keep_fd = false;
1585   size_t dump_size;
1586   uint8_t* dump_data;
1587   google_breakpad::PageAllocator allocator;
1588   const char* exe_buf = nullptr;
1589 
1590   if (GetCrashReporterClient()->HandleCrashDump(info.filename, info.pid)) {
1591     return;
1592   }
1593 
1594 #if defined(OS_CHROMEOS)
1595   // Grab the crashing process' name now, when it should still be available.
1596   // If we try to do this later in our grandchild the crashing process has
1597   // already terminated.
1598   exe_buf = GetCrashingProcessName(info, &allocator);
1599 #endif
1600 
1601   if (info.fd != -1) {
1602     // Dump is provided with an open FD.
1603     keep_fd = true;
1604     dumpfd = info.fd;
1605 
1606     // The FD is pointing to the end of the file.
1607     // Rewind, we'll read the data next.
1608     if (lseek(dumpfd, 0, SEEK_SET) == -1) {
1609       static const char msg[] = "Cannot upload crash dump: failed to "
1610           "reposition minidump FD\n";
1611       WriteLog(msg, sizeof(msg) - 1);
1612       IGNORE_RET(sys_close(dumpfd));
1613       return;
1614     }
1615     LoadDataFromFD(allocator, info.fd, false, &dump_data, &dump_size);
1616   } else {
1617     // Dump is provided with a path.
1618     keep_fd = false;
1619     LoadDataFromFile(allocator, info.filename, &dumpfd, &dump_data, &dump_size);
1620   }
1621 
1622   // TODO(jcivelli): make log work when using FDs.
1623 #if defined(ADDRESS_SANITIZER)
1624   int logfd;
1625   size_t log_size;
1626   uint8_t* log_data;
1627   // Load the AddressSanitizer log into log_data.
1628   LoadDataFromFile(allocator, info.log_filename, &logfd, &log_data, &log_size);
1629 #endif
1630 
1631   // We need to build a MIME block for uploading to the server. Since we are
1632   // going to fork and run wget, it needs to be written to a temp file.
1633   const int ufd = sys_open("/dev/urandom", O_RDONLY, 0);
1634   if (ufd < 0) {
1635     static const char msg[] = "Cannot upload crash dump because /dev/urandom"
1636                               " is missing\n";
1637     WriteLog(msg, sizeof(msg) - 1);
1638     return;
1639   }
1640 
1641   static const char temp_file_template[] =
1642       "/tmp/chromium-upload-XXXXXXXXXXXXXXXX";
1643   char temp_file[sizeof(temp_file_template)];
1644   int temp_file_fd = -1;
1645   if (keep_fd) {
1646     temp_file_fd = dumpfd;
1647     // Rewind the destination, we are going to overwrite it.
1648     if (lseek(dumpfd, 0, SEEK_SET) == -1) {
1649       static const char msg[] = "Cannot upload crash dump: failed to "
1650           "reposition minidump FD (2)\n";
1651       WriteLog(msg, sizeof(msg) - 1);
1652       IGNORE_RET(sys_close(dumpfd));
1653       return;
1654     }
1655   } else {
1656     if (info.upload) {
1657       my_memcpy(temp_file, temp_file_template, sizeof(temp_file_template));
1658 
1659       for (unsigned i = 0; i < 10; ++i) {
1660         uint64_t t;
1661         sys_read(ufd, &t, sizeof(t));
1662         write_uint64_hex(temp_file + sizeof(temp_file) - (16 + 1), t);
1663 
1664         temp_file_fd = sys_open(temp_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
1665         if (temp_file_fd >= 0)
1666           break;
1667       }
1668 
1669       if (temp_file_fd < 0) {
1670         static const char msg[] = "Failed to create temporary file in /tmp: "
1671             "cannot upload crash dump\n";
1672         WriteLog(msg, sizeof(msg) - 1);
1673         IGNORE_RET(sys_close(ufd));
1674         return;
1675       }
1676     } else {
1677       temp_file_fd = sys_open(info.filename, O_WRONLY, 0600);
1678       if (temp_file_fd < 0) {
1679         static const char msg[] = "Failed to save crash dump: failed to open\n";
1680         WriteLog(msg, sizeof(msg) - 1);
1681         IGNORE_RET(sys_close(ufd));
1682         return;
1683       }
1684     }
1685   }
1686 
1687   // The MIME boundary is 28 hyphens, followed by a 64-bit nonce and a NUL.
1688   char mime_boundary[28 + 16 + 1];
1689   my_memset(mime_boundary, '-', 28);
1690   uint64_t boundary_rand;
1691   sys_read(ufd, &boundary_rand, sizeof(boundary_rand));
1692   write_uint64_hex(mime_boundary + 28, boundary_rand);
1693   mime_boundary[28 + 16] = 0;
1694   IGNORE_RET(sys_close(ufd));
1695 
1696   // The MIME block looks like this:
1697   //   BOUNDARY \r\n
1698   //   Content-Disposition: form-data; name="prod" \r\n \r\n
1699   //   Chrome_Linux \r\n
1700   //   BOUNDARY \r\n
1701   //   Content-Disposition: form-data; name="ver" \r\n \r\n
1702   //   1.2.3.4 \r\n
1703   //   BOUNDARY \r\n
1704   //
1705   //   zero or one:
1706   //   Content-Disposition: form-data; name="ptime" \r\n \r\n
1707   //   abcdef \r\n
1708   //   BOUNDARY \r\n
1709   //
1710   //   zero or one:
1711   //   Content-Disposition: form-data; name="ptype" \r\n \r\n
1712   //   abcdef \r\n
1713   //   BOUNDARY \r\n
1714   //
1715   //   zero or one:
1716   //   Content-Disposition: form-data; name="lsb-release" \r\n \r\n
1717   //   abcdef \r\n
1718   //   BOUNDARY \r\n
1719   //
1720   //   zero or one:
1721   //   Content-Disposition: form-data; name="oom-size" \r\n \r\n
1722   //   1234567890 \r\n
1723   //   BOUNDARY \r\n
1724   //
1725   //   zero or more (up to CrashKeyStorage::num_entries = 64):
1726   //   Content-Disposition: form-data; name=crash-key-name \r\n
1727   //   crash-key-value \r\n
1728   //   BOUNDARY \r\n
1729   //
1730   //   Content-Disposition: form-data; name="dump"; filename="dump" \r\n
1731   //   Content-Type: application/octet-stream \r\n \r\n
1732   //   <dump contents>
1733   //   \r\n BOUNDARY -- \r\n
1734 
1735 #if defined(OS_CHROMEOS)
1736   CrashReporterWriter writer(temp_file_fd);
1737 #else
1738   MimeWriter writer(temp_file_fd, mime_boundary);
1739 #endif
1740   {
1741     const char* product_name = "";
1742     const char* version = "";
1743 
1744     GetCrashReporterClient()->GetProductNameAndVersion(&product_name, &version);
1745 
1746     writer.AddBoundary();
1747     writer.AddPairString("prod", product_name);
1748     writer.AddBoundary();
1749     writer.AddPairString("ver", version);
1750     writer.AddBoundary();
1751     if (info.pid > 0) {
1752       char pid_value_buf[kUint64StringSize];
1753       uint64_t pid_value_len = my_uint64_len(info.pid);
1754       my_uint64tos(pid_value_buf, info.pid, pid_value_len);
1755       static const char pid_key_name[] = "pid";
1756       writer.AddPairData(pid_key_name, sizeof(pid_key_name) - 1,
1757                          pid_value_buf, pid_value_len);
1758       writer.AddBoundary();
1759     }
1760 #if defined(OS_ANDROID)
1761     // Addtional MIME blocks are added for logging on Android devices.
1762     // When make changes to the name, please sync it with
1763     // PureJavaExceptionReporter.java if needed.
1764     static const char android_build_id[] = "android_build_id";
1765     static const char android_build_fp[] = "android_build_fp";
1766     static const char device[] = "device";
1767     static const char gms_core_version[] = "gms_core_version";
1768     static const char installer_package_name[] = "installer_package_name";
1769     static const char abi_name[] = "abi_name";
1770     static const char model[] = "model";
1771     static const char brand[] = "brand";
1772     static const char board[] = "board";
1773     static const char exception_info[] = "exception_info";
1774     static const char custom_themes[] = "custom_themes";
1775     static const char resources_version[] = "resources_version";
1776 
1777     base::android::BuildInfo* android_build_info =
1778         base::android::BuildInfo::GetInstance();
1779     writer.AddPairString(
1780         android_build_id, android_build_info->android_build_id());
1781     writer.AddBoundary();
1782     writer.AddPairString(
1783         android_build_fp, android_build_info->android_build_fp());
1784     writer.AddBoundary();
1785     writer.AddPairString(device, android_build_info->device());
1786     writer.AddBoundary();
1787     writer.AddPairString(model, android_build_info->model());
1788     writer.AddBoundary();
1789     writer.AddPairString(brand, android_build_info->brand());
1790     writer.AddBoundary();
1791     writer.AddPairString(board, android_build_info->board());
1792     writer.AddBoundary();
1793     writer.AddPairString(gms_core_version,
1794         android_build_info->gms_version_code());
1795     writer.AddBoundary();
1796     writer.AddPairString(installer_package_name,
1797                          android_build_info->installer_package_name());
1798     writer.AddBoundary();
1799     writer.AddPairString(abi_name, android_build_info->abi_name());
1800     writer.AddBoundary();
1801     writer.AddPairString(custom_themes, android_build_info->custom_themes());
1802     writer.AddBoundary();
1803     writer.AddPairString(resources_version,
1804                          android_build_info->resources_version());
1805     writer.AddBoundary();
1806     // Don't write the field if no Firebase ID is set.
1807     if (android_build_info->firebase_app_id()[0] != '\0') {
1808       WriteAndroidPackage(writer, android_build_info);
1809       writer.AddBoundary();
1810     }
1811     if (g_java_exception_info != nullptr) {
1812       writer.AddPairString(exception_info, g_java_exception_info);
1813       writer.AddBoundary();
1814     }
1815 #endif
1816     writer.Flush();
1817   }
1818 
1819   if (info.process_start_time > 0) {
1820     struct kernel_timeval tv;
1821     if (!sys_gettimeofday(&tv, nullptr)) {
1822       uint64_t time = kernel_timeval_to_ms(&tv);
1823       if (time > info.process_start_time) {
1824         time -= info.process_start_time;
1825         char time_str[kUint64StringSize];
1826         const unsigned time_len = my_uint64_len(time);
1827         my_uint64tos(time_str, time, time_len);
1828 
1829         static const char process_time_msg[] = "ptime";
1830         writer.AddPairData(process_time_msg, sizeof(process_time_msg) - 1,
1831                            time_str, time_len);
1832         writer.AddBoundary();
1833         writer.Flush();
1834       }
1835     }
1836   }
1837 
1838   if (info.process_type_length) {
1839     writer.AddPairString("ptype", info.process_type);
1840     writer.AddBoundary();
1841     writer.Flush();
1842   }
1843 
1844   if (info.distro_length) {
1845     static const char distro_msg[] = "lsb-release";
1846     writer.AddPairString(distro_msg, info.distro);
1847     writer.AddBoundary();
1848     writer.Flush();
1849   }
1850 
1851   if (info.oom_size) {
1852     char oom_size_str[kUint64StringSize];
1853     const unsigned oom_size_len = my_uint64_len(info.oom_size);
1854     my_uint64tos(oom_size_str, info.oom_size, oom_size_len);
1855     static const char oom_size_msg[] = "oom-size";
1856     writer.AddPairData(oom_size_msg, sizeof(oom_size_msg) - 1,
1857                        oom_size_str, oom_size_len);
1858     writer.AddBoundary();
1859     writer.Flush();
1860   }
1861 
1862   if (info.crash_keys) {
1863     using CrashKeyStorage =
1864         crash_reporter::internal::TransitionalCrashKeyStorage;
1865     CrashKeyStorage::Iterator crash_key_iterator(*info.crash_keys);
1866     const CrashKeyStorage::Entry* entry;
1867     while ((entry = crash_key_iterator.Next())) {
1868       if (g_use_crash_key_white_list && !IsInWhiteList(entry->key))
1869         continue;
1870       size_t key_size, value_size;
1871       // Check for malformed messages.
1872       key_size = entry->key[CrashKeyStorage::key_size - 1] != '\0'
1873                      ? CrashKeyStorage::key_size - 1
1874                      : my_strlen(entry->key);
1875       value_size = entry->value[CrashKeyStorage::value_size - 1] != '\0'
1876                        ? CrashKeyStorage::value_size - 1
1877                        : my_strlen(entry->value);
1878 
1879       writer.AddPairData(entry->key, key_size, entry->value, value_size);
1880       writer.AddBoundary();
1881       writer.Flush();
1882     }
1883   }
1884 
1885   writer.AddFileContents(g_dump_msg, dump_data, dump_size);
1886 #if defined(ADDRESS_SANITIZER)
1887   // Append a multipart boundary and the contents of the AddressSanitizer log.
1888   writer.AddBoundary();
1889   writer.AddFileContents(g_log_msg, log_data, log_size);
1890 #endif
1891   writer.AddEnd();
1892   writer.Flush();
1893 
1894   IGNORE_RET(sys_close(temp_file_fd));
1895 
1896 #if defined(OS_ANDROID)
1897   if (info.filename) {
1898     size_t filename_length = my_strlen(info.filename);
1899 
1900     // If this was a file, we need to copy it to the right place and use the
1901     // right file name so it gets uploaded by the browser.
1902     const char msg[] = "Output crash dump file:";
1903     WriteLog(msg, sizeof(msg) - 1);
1904     WriteLog(info.filename, filename_length);
1905 
1906     char pid_buf[kUint64StringSize];
1907     size_t pid_str_length = my_uint64_len(info.pid);
1908     my_uint64tos(pid_buf, info.pid, pid_str_length);
1909     pid_buf[pid_str_length] = 0;  // my_uint64tos() doesn't null-terminate.
1910 
1911     size_t done_filename_len = filename_length + pid_str_length + 1;
1912     char* done_filename = reinterpret_cast<char*>(
1913         allocator.Alloc(done_filename_len));
1914     // Rename the file such that the pid is the suffix in order signal to other
1915     // processes that the minidump is complete. The advantage of using the pid
1916     // as the suffix is that it is trivial to associate the minidump with the
1917     // crashed process.
1918     my_strlcpy(done_filename, info.filename, done_filename_len);
1919     my_strlcat(done_filename, pid_buf, done_filename_len);
1920     // Rename the minidump file to signal that it is complete.
1921     if (rename(info.filename, done_filename)) {
1922       const char failed_msg[] = "Failed to rename:";
1923       WriteLog(failed_msg, sizeof(failed_msg) - 1);
1924       WriteLog(info.filename, filename_length);
1925       const char to_msg[] = "to";
1926       WriteLog(to_msg, sizeof(to_msg) - 1);
1927       WriteLog(done_filename, done_filename_len - 1);
1928     }
1929   }
1930 #endif
1931 
1932   if (!info.upload)
1933     return;
1934 
1935   const pid_t child = sys_fork();
1936   if (!child) {
1937     // Spawned helper process.
1938     //
1939     // This code is called both when a browser is crashing (in which case,
1940     // nothing really matters any more) and when a renderer/plugin crashes, in
1941     // which case we need to continue.
1942     //
1943     // Since we are a multithreaded app, if we were just to fork(), we might
1944     // grab file descriptors which have just been created in another thread and
1945     // hold them open for too long.
1946     //
1947     // Thus, we have to loop and try and close everything.
1948     CloseAllFileDescriptors();
1949 
1950     IGNORE_RET(sys_setsid());
1951 
1952     // Leave one end of a pipe in the upload process and watch for it getting
1953     // closed by the upload process exiting.
1954     int fds[2];
1955     if (sys_pipe(fds) >= 0) {
1956       const pid_t upload_child = sys_fork();
1957       if (!upload_child) {
1958         // Upload process.
1959         IGNORE_RET(sys_close(fds[0]));  // Close read end of pipe.
1960         // Write status to the pipe.
1961         ExecUploadProcessOrTerminate(info, temp_file, mime_boundary, exe_buf,
1962                                      fds[1], &allocator);
1963       }
1964 
1965       // Helper process.
1966       if (upload_child > 0) {
1967         IGNORE_RET(sys_close(fds[1]));  // Close write end of pipe.
1968 
1969         const size_t kCrashIdLength = 16;
1970         char id_buf[kCrashIdLength + 1];
1971         size_t bytes_read =
1972             WaitForCrashReportUploadProcess(fds[0], kCrashIdLength, id_buf);
1973         HandleCrashReportId(id_buf, bytes_read, kCrashIdLength);
1974 
1975         if (sys_waitpid(upload_child, nullptr, WNOHANG) == 0) {
1976           // Upload process is still around, kill it.
1977           sys_kill(upload_child, SIGKILL);
1978         }
1979       }
1980     }
1981 
1982     // Helper process.
1983     IGNORE_RET(sys_unlink(info.filename));
1984 #if defined(ADDRESS_SANITIZER)
1985     IGNORE_RET(sys_unlink(info.log_filename));
1986 #endif
1987     IGNORE_RET(sys_unlink(temp_file));
1988     sys__exit(0);
1989   }
1990 
1991   // Main browser process.
1992   if (child <= 0)
1993     return;
1994   (void) HANDLE_EINTR(sys_waitpid(child, nullptr, 0));
1995 }
1996 
1997 #if defined(OS_ANDROID)
1998 // In Android WebView, microdumps are generated conditionally (depending on the
1999 // cause of the crash) and can be sanitized to prevent exposing unnecessary data
2000 // from the embedding application.
InitCrashReporter(const std::string & process_type)2001 void InitCrashReporter(const std::string& process_type) {
2002   SanitizationInfo sanitization_info;
2003   InitCrashReporter(process_type, sanitization_info);
2004 }
2005 
InitCrashKeysForTesting()2006 void InitCrashKeysForTesting() {
2007   InitCrashKeys();
2008 }
2009 
InitCrashReporter(const std::string & process_type,const SanitizationInfo & sanitization_info)2010 void InitCrashReporter(const std::string& process_type,
2011                        const SanitizationInfo& sanitization_info) {
2012 #else
2013 void InitCrashReporter(const std::string& process_type) {
2014 #endif  // defined(OS_ANDROID)
2015 #if defined(OS_ANDROID)
2016   base::android::SetJavaExceptionCallback(SetJavaExceptionInfo);
2017 
2018   // This will guarantee that the BuildInfo has been initialized and subsequent
2019   // calls will not require memory allocation.
2020   base::android::BuildInfo::GetInstance();
2021 
2022   // Handler registration is LIFO. Install the microdump handler first, such
2023   // that if conventional minidump crash reporting is enabled below, it takes
2024   // precedence (i.e. its handler is run first) over the microdump handler.
2025   InitMicrodumpCrashHandlerIfNecessary(process_type, sanitization_info);
2026 #endif
2027   // Determine the process type and take appropriate action.
2028   const base::CommandLine& parsed_command_line =
2029       *base::CommandLine::ForCurrentProcess();
2030   if (parsed_command_line.HasSwitch(switches::kDisableBreakpad))
2031     return;
2032 
2033   bool is_browser_process =
2034 #if defined(OS_ANDROID)
2035       process_type == kWebViewSingleProcessType ||
2036       process_type == kBrowserProcessType ||
2037 #endif
2038       process_type.empty();
2039 
2040   if (is_browser_process) {
2041     bool enable_breakpad = GetCrashReporterClient()->GetCollectStatsConsent() ||
2042                            GetCrashReporterClient()->IsRunningUnattended();
2043     enable_breakpad &=
2044         !parsed_command_line.HasSwitch(switches::kDisableBreakpad);
2045     if (!enable_breakpad) {
2046       enable_breakpad = parsed_command_line.HasSwitch(
2047           switches::kEnableCrashReporterForTesting);
2048     }
2049     if (!enable_breakpad) {
2050       VLOG(1) << "Breakpad disabled";
2051       return;
2052     }
2053 
2054     InitCrashKeys();
2055 #if defined(OS_ANDROID)
2056     EnableCrashDumping(GetCrashReporterClient()->IsRunningUnattended(),
2057                        sanitization_info);
2058 #else
2059     EnableCrashDumping(GetCrashReporterClient()->IsRunningUnattended());
2060 #endif  // defined(OS_ANDROID)
2061   } else if (GetCrashReporterClient()->EnableBreakpadForProcess(process_type)) {
2062 #if defined(OS_ANDROID)
2063     NOTREACHED() << "Breakpad initialized with InitCrashReporter() instead of "
2064       "InitNonBrowserCrashReporter in " << process_type << " process.";
2065     return;
2066 #else
2067     // We might be chrooted in a zygote or renderer process so we cannot call
2068     // GetCollectStatsConsent because that needs access the the user's home
2069     // dir. Instead, we set a command line flag for these processes.
2070     // Even though plugins are not chrooted, we share the same code path for
2071     // simplicity.
2072     if (!parsed_command_line.HasSwitch(switches::kEnableCrashReporter))
2073       return;
2074 
2075     InitCrashKeys();
2076     SetChannelFromCommandLine(parsed_command_line);
2077     SetClientIdFromCommandLine(parsed_command_line);
2078     EnableNonBrowserCrashDumping();
2079     VLOG(1) << "Non Browser crash dumping enabled for: " << process_type;
2080 #endif  // #if defined(OS_ANDROID)
2081   }
2082 
2083   PostEnableBreakpadInitialization(process_type, parsed_command_line);
2084 }
2085 
2086 void SetChannelCrashKey(const std::string& channel) {
2087   static crash_reporter::CrashKeyString<16> channel_key("channel");
2088   channel_key.Set(channel);
2089 }
2090 
2091 #if defined(OS_ANDROID)
2092 void InitNonBrowserCrashReporterForAndroid(const std::string& process_type) {
2093   SanitizationInfo sanitization_info;
2094   sanitization_info.should_sanitize_dumps = false;
2095   sanitization_info.skip_dump_if_principal_mapping_not_referenced = false;
2096   InitNonBrowserCrashReporterForAndroid(process_type, sanitization_info);
2097 }
2098 
2099 void InitNonBrowserCrashReporterForAndroid(
2100     const std::string& process_type,
2101     const SanitizationInfo& sanitization_info) {
2102   const base::CommandLine* command_line =
2103       base::CommandLine::ForCurrentProcess();
2104 
2105   base::android::SetJavaExceptionCallback(SetJavaExceptionInfo);
2106 
2107   // Handler registration is LIFO. Install the microdump handler first, such
2108   // that if conventional minidump crash reporting is enabled below, it takes
2109   // precedence (i.e. its handler is run first) over the microdump handler.
2110   InitMicrodumpCrashHandlerIfNecessary(process_type, sanitization_info);
2111 
2112   if (command_line->HasSwitch(switches::kEnableCrashReporter)) {
2113     // On Android we need to provide a FD to the file where the minidump is
2114     // generated as the renderer and browser run with different UIDs
2115     // (preventing the browser from inspecting the renderer process).
2116     int minidump_fd = base::GlobalDescriptors::GetInstance()->MaybeGet(
2117         GetCrashReporterClient()->GetAndroidMinidumpDescriptor());
2118     if (minidump_fd < 0) {
2119       NOTREACHED() << "Could not find minidump FD, crash reporting disabled.";
2120     } else {
2121       InitCrashKeys();
2122       EnableNonBrowserCrashDumping(process_type, minidump_fd,
2123                                    sanitization_info);
2124       // Note: not installing DumpWithoutCrash handler here because browser
2125       // is not set up to receive multiple reports from child process.
2126     }
2127   }
2128 }
2129 
2130 // The microdump handler does NOT upload anything. It just dumps out on the
2131 // system console (logcat) a restricted and serialized variant of a minidump.
2132 // See crbug.com/410294 for more details.
2133 void InitMicrodumpCrashHandlerIfNecessary(
2134     const std::string& process_type,
2135     const SanitizationInfo& sanitization_info) {
2136   if (!GetCrashReporterClient()->ShouldEnableBreakpadMicrodumps())
2137     return;
2138 
2139   VLOG(1) << "Enabling microdumps crash handler (process_type:"
2140           << process_type << ")";
2141 
2142   // The exception handler runs in a compromised context and cannot use c_str()
2143   // as that would require the heap. Therefore, we have to guarantee that the
2144   // build fingerprint and product info pointers are always valid.
2145   const char* product_name = nullptr;
2146   const char* product_version = nullptr;
2147   GetCrashReporterClient()->GetProductNameAndVersion(&product_name,
2148                                                      &product_version);
2149 
2150   const char* android_build_fp =
2151       base::android::BuildInfo::GetInstance()->android_build_fp();
2152 
2153   g_microdump_info.Get().Initialize(process_type, product_name, product_version,
2154                                     android_build_fp, sanitization_info);
2155 }
2156 
2157 void AddGpuFingerprintToMicrodumpCrashHandler(
2158     const std::string& gpu_fingerprint) {
2159   g_microdump_info.Get().SetGpuFingerprintForMicrodump(gpu_fingerprint);
2160 }
2161 
2162 void GenerateMinidumpOnDemandForAndroid(int dump_fd) {
2163   if (dump_fd >= 0) {
2164     MinidumpDescriptor minidump_descriptor(dump_fd);
2165     minidump_descriptor.set_size_limit(-1);
2166     ExceptionHandler(minidump_descriptor, nullptr, MinidumpGenerated, nullptr,
2167                      false, -1)
2168         .WriteMinidump();
2169   }
2170 }
2171 
2172 void SuppressDumpGeneration() {
2173   g_dumps_suppressed = G_DUMPS_SUPPRESSED_MAGIC;
2174 }
2175 #endif  // OS_ANDROID
2176 
2177 bool IsCrashReporterEnabled() {
2178   return g_is_crash_reporter_enabled;
2179 }
2180 
2181 void SetFirstChanceExceptionHandler(bool (*handler)(int, siginfo_t*, void*)) {
2182   google_breakpad::SetFirstChanceExceptionHandler(handler);
2183 }
2184 
2185 }  // namespace breakpad
2186