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