| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // For linux_syscall_support.h. This makes it safe to call embedded system | 5 // For linux_syscall_support.h. This makes it safe to call embedded system |
| 6 // calls when in seccomp mode. | 6 // calls when in seccomp mode. |
| 7 #define SYS_SYSCALL_ENTRYPOINT "playground$syscallEntryPoint" | 7 #define SYS_SYSCALL_ENTRYPOINT "playground$syscallEntryPoint" |
| 8 | 8 |
| 9 #include "chrome/app/breakpad_linux.h" | 9 #include "chrome/app/breakpad_linux.h" |
| 10 | 10 |
| 11 #include <fcntl.h> | 11 #include <fcntl.h> |
| 12 #include <poll.h> | 12 #include <poll.h> |
| 13 #include <signal.h> |
| 13 #include <stdlib.h> | 14 #include <stdlib.h> |
| 14 #include <sys/socket.h> | 15 #include <sys/socket.h> |
| 15 #include <sys/time.h> | 16 #include <sys/time.h> |
| 16 #include <sys/types.h> | 17 #include <sys/types.h> |
| 17 #include <sys/wait.h> | 18 #include <sys/wait.h> |
| 18 #include <sys/uio.h> | 19 #include <sys/uio.h> |
| 19 #include <time.h> | 20 #include <time.h> |
| 20 #include <unistd.h> | 21 #include <unistd.h> |
| 21 | 22 |
| 22 #include <algorithm> | 23 #include <algorithm> |
| (...skipping 24 matching lines...) Expand all Loading... |
| 47 #include <android/log.h> | 48 #include <android/log.h> |
| 48 #include <sys/stat.h> | 49 #include <sys/stat.h> |
| 49 | 50 |
| 50 #include "base/android/build_info.h" | 51 #include "base/android/build_info.h" |
| 51 #include "base/android/path_utils.h" | 52 #include "base/android/path_utils.h" |
| 52 #include "third_party/lss/linux_syscall_support.h" | 53 #include "third_party/lss/linux_syscall_support.h" |
| 53 #else | 54 #else |
| 54 #include "sandbox/linux/seccomp-legacy/linux_syscall_support.h" | 55 #include "sandbox/linux/seccomp-legacy/linux_syscall_support.h" |
| 55 #endif | 56 #endif |
| 56 | 57 |
| 58 #if defined(ADDRESS_SANITIZER) |
| 59 #include <ucontext.h> // for getcontext(). |
| 60 #endif |
| 61 |
| 57 #if defined(OS_ANDROID) | 62 #if defined(OS_ANDROID) |
| 58 #define STAT_STRUCT struct stat | 63 #define STAT_STRUCT struct stat |
| 59 #define FSTAT_FUNC fstat | 64 #define FSTAT_FUNC fstat |
| 60 #else | 65 #else |
| 61 #define STAT_STRUCT struct kernel_stat | 66 #define STAT_STRUCT struct kernel_stat |
| 62 #define FSTAT_FUNC sys_fstat | 67 #define FSTAT_FUNC sys_fstat |
| 63 #endif | 68 #endif |
| 64 | 69 |
| 65 // Some versions of gcc are prone to warn about unused return values. In cases | 70 // Some versions of gcc are prone to warn about unused return values. In cases |
| 66 // where we either a) know the call cannot fail, or b) there is nothing we | 71 // where we either a) know the call cannot fail, or b) there is nothing we |
| 67 // can do when a call fails, we mark the return code as ignored. This avoids | 72 // can do when a call fails, we mark the return code as ignored. This avoids |
| 68 // spurious compiler warnings. | 73 // spurious compiler warnings. |
| 69 #define IGNORE_RET(x) do { if (x); } while (0) | 74 #define IGNORE_RET(x) do { if (x); } while (0) |
| 70 | 75 |
| 71 using google_breakpad::ExceptionHandler; | 76 using google_breakpad::ExceptionHandler; |
| 72 using google_breakpad::MinidumpDescriptor; | 77 using google_breakpad::MinidumpDescriptor; |
| 73 | 78 |
| 74 namespace { | 79 namespace { |
| 75 | 80 |
| 81 #if !defined(ADDRESS_SANITIZER) |
| 76 const char kUploadURL[] = "https://clients2.google.com/cr/report"; | 82 const char kUploadURL[] = "https://clients2.google.com/cr/report"; |
| 83 #else |
| 84 // AddressSanitizer should currently upload the crash reports to the staging |
| 85 // crash server. |
| 86 const char kUploadURL[] = "https://clients2.google.com/cr/staging_report"; |
| 87 #endif |
| 77 | 88 |
| 78 bool g_is_crash_reporter_enabled = false; | 89 bool g_is_crash_reporter_enabled = false; |
| 79 uint64_t g_process_start_time = 0; | 90 uint64_t g_process_start_time = 0; |
| 80 char* g_crash_log_path = NULL; | 91 char* g_crash_log_path = NULL; |
| 81 ExceptionHandler* g_breakpad = NULL; | 92 ExceptionHandler* g_breakpad = NULL; |
| 93 #if defined(ADDRESS_SANITIZER) |
| 94 const char* g_asan_report_str = NULL; |
| 95 #endif |
| 82 | 96 |
| 83 // Writes the value |v| as 16 hex characters to the memory pointed at by | 97 // Writes the value |v| as 16 hex characters to the memory pointed at by |
| 84 // |output|. | 98 // |output|. |
| 85 void write_uint64_hex(char* output, uint64_t v) { | 99 void write_uint64_hex(char* output, uint64_t v) { |
| 86 static const char hextable[] = "0123456789abcdef"; | 100 static const char hextable[] = "0123456789abcdef"; |
| 87 | 101 |
| 88 for (int i = 15; i >= 0; --i) { | 102 for (int i = 15; i >= 0; --i) { |
| 89 output[i] = hextable[v & 15]; | 103 output[i] = hextable[v & 15]; |
| 90 v >>= 4; | 104 v >>= 4; |
| 91 } | 105 } |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 return ret; | 178 return ret; |
| 165 } | 179 } |
| 166 #endif | 180 #endif |
| 167 | 181 |
| 168 // MIME substrings. | 182 // MIME substrings. |
| 169 const char g_rn[] = "\r\n"; | 183 const char g_rn[] = "\r\n"; |
| 170 const char g_form_data_msg[] = "Content-Disposition: form-data; name=\""; | 184 const char g_form_data_msg[] = "Content-Disposition: form-data; name=\""; |
| 171 const char g_quote_msg[] = "\""; | 185 const char g_quote_msg[] = "\""; |
| 172 const char g_dashdash_msg[] = "--"; | 186 const char g_dashdash_msg[] = "--"; |
| 173 const char g_dump_msg[] = "upload_file_minidump\"; filename=\"dump\""; | 187 const char g_dump_msg[] = "upload_file_minidump\"; filename=\"dump\""; |
| 188 #if defined(ADDRESS_SANITIZER) |
| 189 const char g_log_msg[] = "upload_file_log\"; filename=\"log\""; |
| 190 #endif |
| 174 const char g_content_type_msg[] = "Content-Type: application/octet-stream"; | 191 const char g_content_type_msg[] = "Content-Type: application/octet-stream"; |
| 175 | 192 |
| 176 // MimeWriter manages an iovec for writing MIMEs to a file. | 193 // MimeWriter manages an iovec for writing MIMEs to a file. |
| 177 class MimeWriter { | 194 class MimeWriter { |
| 178 public: | 195 public: |
| 179 static const int kIovCapacity = 30; | 196 static const int kIovCapacity = 30; |
| 180 static const size_t kMaxCrashChunkSize = 64; | 197 static const size_t kMaxCrashChunkSize = 64; |
| 181 | 198 |
| 182 MimeWriter(int fd, const char* const mime_boundary); | 199 MimeWriter(int fd, const char* const mime_boundary); |
| 183 ~MimeWriter(); | 200 ~MimeWriter(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 203 // Append key/value pair, splitting value into chunks no larger than | 220 // Append key/value pair, splitting value into chunks no larger than |
| 204 // |chunk_size|. |chunk_size| cannot be greater than |kMaxCrashChunkSize|. | 221 // |chunk_size|. |chunk_size| cannot be greater than |kMaxCrashChunkSize|. |
| 205 // The msg_type string will have a counter suffix to distinguish each chunk. | 222 // The msg_type string will have a counter suffix to distinguish each chunk. |
| 206 void AddPairDataInChunks(const char* msg_type, | 223 void AddPairDataInChunks(const char* msg_type, |
| 207 size_t msg_type_size, | 224 size_t msg_type_size, |
| 208 const char* msg_data, | 225 const char* msg_data, |
| 209 size_t msg_data_size, | 226 size_t msg_data_size, |
| 210 size_t chunk_size, | 227 size_t chunk_size, |
| 211 bool strip_trailing_spaces); | 228 bool strip_trailing_spaces); |
| 212 | 229 |
| 213 // Add binary file dump. Currently this is only done once, so the name is | 230 // Add binary file contents to be uploaded with the specified filename. |
| 214 // fixed. | 231 void AddFileContents(const char* filename_msg, |
| 215 void AddFileDump(uint8_t* file_data, | 232 uint8_t* file_data, |
| 216 size_t file_size); | 233 size_t file_size); |
| 217 | 234 |
| 218 // Flush any pending iovecs to the output file. | 235 // Flush any pending iovecs to the output file. |
| 219 void Flush() { | 236 void Flush() { |
| 220 IGNORE_RET(sys_writev(fd_, iov_, iov_index_)); | 237 IGNORE_RET(sys_writev(fd_, iov_, iov_index_)); |
| 221 iov_index_ = 0; | 238 iov_index_ = 0; |
| 222 } | 239 } |
| 223 | 240 |
| 224 private: | 241 private: |
| 225 void AddItem(const void* base, size_t size); | 242 void AddItem(const void* base, size_t size); |
| 226 // Minor performance trade-off for easier-to-maintain code. | 243 // Minor performance trade-off for easier-to-maintain code. |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 } | 322 } |
| 306 AddString(g_rn); | 323 AddString(g_rn); |
| 307 AddBoundary(); | 324 AddBoundary(); |
| 308 Flush(); | 325 Flush(); |
| 309 | 326 |
| 310 done += chunk_len; | 327 done += chunk_len; |
| 311 msg_length -= chunk_len; | 328 msg_length -= chunk_len; |
| 312 } | 329 } |
| 313 } | 330 } |
| 314 | 331 |
| 315 void MimeWriter::AddFileDump(uint8_t* file_data, | 332 void MimeWriter::AddFileContents(const char* filename_msg, uint8_t* file_data, |
| 316 size_t file_size) { | 333 size_t file_size) { |
| 317 AddString(g_form_data_msg); | 334 AddString(g_form_data_msg); |
| 318 AddString(g_dump_msg); | 335 AddString(filename_msg); |
| 319 AddString(g_rn); | 336 AddString(g_rn); |
| 320 AddString(g_content_type_msg); | 337 AddString(g_content_type_msg); |
| 321 AddString(g_rn); | 338 AddString(g_rn); |
| 322 AddString(g_rn); | 339 AddString(g_rn); |
| 323 AddItem(file_data, file_size); | 340 AddItem(file_data, file_size); |
| 324 AddString(g_rn); | 341 AddString(g_rn); |
| 325 } | 342 } |
| 326 | 343 |
| 327 void MimeWriter::AddItem(const void* base, size_t size) { | 344 void MimeWriter::AddItem(const void* base, size_t size) { |
| 328 // Check if the iovec is full and needs to be flushed to output file. | 345 // Check if the iovec is full and needs to be flushed to output file. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 const bool succeeded) { | 382 const bool succeeded) { |
| 366 // WARNING: this code runs in a compromised context. It may not call into | 383 // WARNING: this code runs in a compromised context. It may not call into |
| 367 // libc nor allocate memory normally. | 384 // libc nor allocate memory normally. |
| 368 if (!succeeded) | 385 if (!succeeded) |
| 369 return false; | 386 return false; |
| 370 | 387 |
| 371 DCHECK(!minidump.IsFD()); | 388 DCHECK(!minidump.IsFD()); |
| 372 | 389 |
| 373 BreakpadInfo info; | 390 BreakpadInfo info; |
| 374 info.filename = minidump.path(); | 391 info.filename = minidump.path(); |
| 392 #if defined(ADDRESS_SANITIZER) |
| 393 google_breakpad::PageAllocator allocator; |
| 394 const size_t log_path_len = my_strlen(minidump.path()); |
| 395 char* log_path = reinterpret_cast<char*>(allocator.Alloc(log_path_len + 1)); |
| 396 my_memcpy(log_path, minidump.path(), log_path_len); |
| 397 my_memcpy(log_path + log_path_len - 4, ".log", 4); |
| 398 log_path[log_path_len] = '\0'; |
| 399 info.log_filename = log_path; |
| 400 #endif |
| 375 info.process_type = "browser"; | 401 info.process_type = "browser"; |
| 376 info.process_type_length = 7; | 402 info.process_type_length = 7; |
| 377 info.crash_url = NULL; | 403 info.crash_url = NULL; |
| 378 info.crash_url_length = 0; | 404 info.crash_url_length = 0; |
| 379 info.guid = child_process_logging::g_client_id; | 405 info.guid = child_process_logging::g_client_id; |
| 380 info.guid_length = my_strlen(child_process_logging::g_client_id); | 406 info.guid_length = my_strlen(child_process_logging::g_client_id); |
| 381 info.distro = base::g_linux_distro; | 407 info.distro = base::g_linux_distro; |
| 382 info.distro_length = my_strlen(base::g_linux_distro); | 408 info.distro_length = my_strlen(base::g_linux_distro); |
| 383 info.upload = upload; | 409 info.upload = upload; |
| 384 info.process_start_time = g_process_start_time; | 410 info.process_start_time = g_process_start_time; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 397 | 423 |
| 398 #if !defined(OS_ANDROID) | 424 #if !defined(OS_ANDROID) |
| 399 // Wrapper function, do not add more code here. | 425 // Wrapper function, do not add more code here. |
| 400 bool CrashDoneUpload(const MinidumpDescriptor& minidump, | 426 bool CrashDoneUpload(const MinidumpDescriptor& minidump, |
| 401 void* context, | 427 void* context, |
| 402 bool succeeded) { | 428 bool succeeded) { |
| 403 return CrashDone(minidump, true, succeeded); | 429 return CrashDone(minidump, true, succeeded); |
| 404 } | 430 } |
| 405 #endif | 431 #endif |
| 406 | 432 |
| 433 #if defined(ADDRESS_SANITIZER) |
| 434 extern "C" |
| 435 void __asan_set_error_report_callback(void (*cb)(const char*)); |
| 436 |
| 437 extern "C" |
| 438 void AsanLinuxBreakpadCallback(const char* report) { |
| 439 g_asan_report_str = report; |
| 440 // Send minidump here. |
| 441 g_breakpad->SimulateSignalDelivery(SIGKILL); |
| 442 } |
| 443 #endif |
| 444 |
| 407 void EnableCrashDumping(bool unattended) { | 445 void EnableCrashDumping(bool unattended) { |
| 408 g_is_crash_reporter_enabled = true; | 446 g_is_crash_reporter_enabled = true; |
| 409 | 447 |
| 410 FilePath tmp_path("/tmp"); | 448 FilePath tmp_path("/tmp"); |
| 411 PathService::Get(base::DIR_TEMP, &tmp_path); | 449 PathService::Get(base::DIR_TEMP, &tmp_path); |
| 412 | 450 |
| 413 FilePath dumps_path(tmp_path); | 451 FilePath dumps_path(tmp_path); |
| 414 if (PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path)) { | 452 if (PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path)) { |
| 415 FilePath logfile = | 453 FilePath logfile = |
| 416 dumps_path.AppendASCII(CrashUploadList::kReporterLogFilename); | 454 dumps_path.AppendASCII(CrashUploadList::kReporterLogFilename); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 char b; // Dummy variable for sys_read below. | 514 char b; // Dummy variable for sys_read below. |
| 477 const char* b_addr = &b; // Get the address of |b| so we can create the | 515 const char* b_addr = &b; // Get the address of |b| so we can create the |
| 478 // expected /proc/[pid]/syscall content in the | 516 // expected /proc/[pid]/syscall content in the |
| 479 // browser to convert namespace tids. | 517 // browser to convert namespace tids. |
| 480 | 518 |
| 481 // The length of the control message: | 519 // The length of the control message: |
| 482 static const unsigned kControlMsgSize = sizeof(fds); | 520 static const unsigned kControlMsgSize = sizeof(fds); |
| 483 static const unsigned kControlMsgSpaceSize = CMSG_SPACE(kControlMsgSize); | 521 static const unsigned kControlMsgSpaceSize = CMSG_SPACE(kControlMsgSize); |
| 484 static const unsigned kControlMsgLenSize = CMSG_LEN(kControlMsgSize); | 522 static const unsigned kControlMsgLenSize = CMSG_LEN(kControlMsgSize); |
| 485 | 523 |
| 524 #if !defined(ADDRESS_SANITIZER) |
| 486 const size_t kIovSize = 8; | 525 const size_t kIovSize = 8; |
| 526 #else |
| 527 // Additional field to pass the AddressSanitizer log to the crash handler. |
| 528 const size_t kIovSize = 9; |
| 529 #endif |
| 487 struct kernel_msghdr msg; | 530 struct kernel_msghdr msg; |
| 488 my_memset(&msg, 0, sizeof(struct kernel_msghdr)); | 531 my_memset(&msg, 0, sizeof(struct kernel_msghdr)); |
| 489 struct kernel_iovec iov[kIovSize]; | 532 struct kernel_iovec iov[kIovSize]; |
| 490 iov[0].iov_base = const_cast<void*>(crash_context); | 533 iov[0].iov_base = const_cast<void*>(crash_context); |
| 491 iov[0].iov_len = crash_context_size; | 534 iov[0].iov_len = crash_context_size; |
| 492 iov[1].iov_base = guid; | 535 iov[1].iov_base = guid; |
| 493 iov[1].iov_len = kGuidSize + 1; | 536 iov[1].iov_len = kGuidSize + 1; |
| 494 iov[2].iov_base = crash_url; | 537 iov[2].iov_base = crash_url; |
| 495 iov[2].iov_len = kMaxActiveURLSize + 1; | 538 iov[2].iov_len = kMaxActiveURLSize + 1; |
| 496 iov[3].iov_base = distro; | 539 iov[3].iov_base = distro; |
| 497 iov[3].iov_len = kDistroSize + 1; | 540 iov[3].iov_len = kDistroSize + 1; |
| 498 iov[4].iov_base = &b_addr; | 541 iov[4].iov_base = &b_addr; |
| 499 iov[4].iov_len = sizeof(b_addr); | 542 iov[4].iov_len = sizeof(b_addr); |
| 500 iov[5].iov_base = &fds[0]; | 543 iov[5].iov_base = &fds[0]; |
| 501 iov[5].iov_len = sizeof(fds[0]); | 544 iov[5].iov_len = sizeof(fds[0]); |
| 502 iov[6].iov_base = &g_process_start_time; | 545 iov[6].iov_base = &g_process_start_time; |
| 503 iov[6].iov_len = sizeof(g_process_start_time); | 546 iov[6].iov_len = sizeof(g_process_start_time); |
| 504 iov[7].iov_base = &base::g_oom_size; | 547 iov[7].iov_base = &base::g_oom_size; |
| 505 iov[7].iov_len = sizeof(base::g_oom_size); | 548 iov[7].iov_len = sizeof(base::g_oom_size); |
| 549 #if defined(ADDRESS_SANITIZER) |
| 550 iov[8].iov_base = const_cast<char*>(g_asan_report_str); |
| 551 iov[8].iov_len = kMaxAsanReportSize + 1; |
| 552 #endif |
| 506 | 553 |
| 507 msg.msg_iov = iov; | 554 msg.msg_iov = iov; |
| 508 msg.msg_iovlen = kIovSize; | 555 msg.msg_iovlen = kIovSize; |
| 509 char cmsg[kControlMsgSpaceSize]; | 556 char cmsg[kControlMsgSpaceSize]; |
| 510 my_memset(cmsg, 0, kControlMsgSpaceSize); | 557 my_memset(cmsg, 0, kControlMsgSpaceSize); |
| 511 msg.msg_control = cmsg; | 558 msg.msg_control = cmsg; |
| 512 msg.msg_controllen = sizeof(cmsg); | 559 msg.msg_controllen = sizeof(cmsg); |
| 513 | 560 |
| 514 struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); | 561 struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); |
| 515 hdr->cmsg_level = SOL_SOCKET; | 562 hdr->cmsg_level = SOL_SOCKET; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 544 NULL, | 591 NULL, |
| 545 NULL, | 592 NULL, |
| 546 reinterpret_cast<void*>(fd), // Param passed to the crash handler. | 593 reinterpret_cast<void*>(fd), // Param passed to the crash handler. |
| 547 true, | 594 true, |
| 548 -1); | 595 -1); |
| 549 g_breakpad->set_crash_handler(NonBrowserCrashHandler); | 596 g_breakpad->set_crash_handler(NonBrowserCrashHandler); |
| 550 } | 597 } |
| 551 | 598 |
| 552 } // namespace | 599 } // namespace |
| 553 | 600 |
| 554 void HandleCrashDump(const BreakpadInfo& info) { | 601 void LoadDataFromFile(google_breakpad::PageAllocator& allocator, |
| 602 const BreakpadInfo& info, const char* filename, |
| 603 int* fd, uint8_t** file_data, size_t* size) { |
| 555 // WARNING: this code runs in a compromised context. It may not call into | 604 // WARNING: this code runs in a compromised context. It may not call into |
| 556 // libc nor allocate memory normally. | 605 // libc nor allocate memory normally. |
| 606 *fd = sys_open(filename, O_RDONLY, 0); |
| 607 *size = 0; |
| 557 | 608 |
| 558 const int dumpfd = sys_open(info.filename, O_RDONLY, 0); | 609 if (*fd < 0) { |
| 559 if (dumpfd < 0) { | |
| 560 static const char msg[] = "Cannot upload crash dump: failed to open\n"; | 610 static const char msg[] = "Cannot upload crash dump: failed to open\n"; |
| 561 WriteLog(msg, sizeof(msg)); | 611 WriteLog(msg, sizeof(msg)); |
| 562 return; | 612 return; |
| 563 } | 613 } |
| 564 STAT_STRUCT st; | 614 STAT_STRUCT st; |
| 565 if (FSTAT_FUNC(dumpfd, &st) != 0) { | 615 if (FSTAT_FUNC(*fd, &st) != 0) { |
| 566 static const char msg[] = "Cannot upload crash dump: stat failed\n"; | 616 static const char msg[] = "Cannot upload crash dump: stat failed\n"; |
| 567 WriteLog(msg, sizeof(msg)); | 617 WriteLog(msg, sizeof(msg)); |
| 568 IGNORE_RET(sys_close(dumpfd)); | 618 IGNORE_RET(sys_close(*fd)); |
| 569 return; | 619 return; |
| 570 } | 620 } |
| 571 | 621 |
| 572 google_breakpad::PageAllocator allocator; | 622 *file_data = reinterpret_cast<uint8_t*>(allocator.Alloc(st.st_size)); |
| 573 | 623 if (!(*file_data)) { |
| 574 uint8_t* dump_data = reinterpret_cast<uint8_t*>(allocator.Alloc(st.st_size)); | |
| 575 if (!dump_data) { | |
| 576 static const char msg[] = "Cannot upload crash dump: cannot alloc\n"; | 624 static const char msg[] = "Cannot upload crash dump: cannot alloc\n"; |
| 577 WriteLog(msg, sizeof(msg)); | 625 WriteLog(msg, sizeof(msg)); |
| 578 IGNORE_RET(sys_close(dumpfd)); | 626 IGNORE_RET(sys_close(*fd)); |
| 579 return; | 627 return; |
| 580 } | 628 } |
| 629 my_memset(*file_data, 0xf, st.st_size); |
| 581 | 630 |
| 582 sys_read(dumpfd, dump_data, st.st_size); | 631 *size = st.st_size; |
| 583 IGNORE_RET(sys_close(dumpfd)); | 632 sys_read(*fd, *file_data, *size); |
| 633 IGNORE_RET(sys_close(*fd)); |
| 634 } |
| 635 |
| 636 void HandleCrashDump(const BreakpadInfo& info) { |
| 637 int dumpfd; |
| 638 size_t dump_size; |
| 639 uint8_t *dump_data; |
| 640 google_breakpad::PageAllocator allocator; |
| 641 LoadDataFromFile(allocator, info, info.filename, |
| 642 &dumpfd, &dump_data, &dump_size); |
| 643 #if defined(ADDRESS_SANITIZER) |
| 644 int logfd; |
| 645 size_t log_size; |
| 646 uint8_t *log_data; |
| 647 // Load the AddressSanitizer log into log_data. |
| 648 LoadDataFromFile(allocator, info, info.log_filename, |
| 649 &logfd, &log_data, &log_size); |
| 650 #endif |
| 584 | 651 |
| 585 // We need to build a MIME block for uploading to the server. Since we are | 652 // We need to build a MIME block for uploading to the server. Since we are |
| 586 // going to fork and run wget, it needs to be written to a temp file. | 653 // going to fork and run wget, it needs to be written to a temp file. |
| 587 | |
| 588 const int ufd = sys_open("/dev/urandom", O_RDONLY, 0); | 654 const int ufd = sys_open("/dev/urandom", O_RDONLY, 0); |
| 589 if (ufd < 0) { | 655 if (ufd < 0) { |
| 590 static const char msg[] = "Cannot upload crash dump because /dev/urandom" | 656 static const char msg[] = "Cannot upload crash dump because /dev/urandom" |
| 591 " is missing\n"; | 657 " is missing\n"; |
| 592 WriteLog(msg, sizeof(msg) - 1); | 658 WriteLog(msg, sizeof(msg) - 1); |
| 593 return; | 659 return; |
| 594 } | 660 } |
| 595 | 661 |
| 596 static const char temp_file_template[] = | 662 static const char temp_file_template[] = |
| 597 "/tmp/chromium-upload-XXXXXXXXXXXXXXXX"; | 663 "/tmp/chromium-upload-XXXXXXXXXXXXXXXX"; |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 909 char oom_size_str[kUint64StringSize]; | 975 char oom_size_str[kUint64StringSize]; |
| 910 const unsigned oom_size_len = my_uint64_len(info.oom_size); | 976 const unsigned oom_size_len = my_uint64_len(info.oom_size); |
| 911 my_uint64tos(oom_size_str, info.oom_size, oom_size_len); | 977 my_uint64tos(oom_size_str, info.oom_size, oom_size_len); |
| 912 static const char oom_size_msg[] = "oom-size"; | 978 static const char oom_size_msg[] = "oom-size"; |
| 913 writer.AddPairData(oom_size_msg, sizeof(oom_size_msg) - 1, | 979 writer.AddPairData(oom_size_msg, sizeof(oom_size_msg) - 1, |
| 914 oom_size_str, oom_size_len); | 980 oom_size_str, oom_size_len); |
| 915 writer.AddBoundary(); | 981 writer.AddBoundary(); |
| 916 writer.Flush(); | 982 writer.Flush(); |
| 917 } | 983 } |
| 918 | 984 |
| 919 writer.AddFileDump(dump_data, st.st_size); | 985 writer.AddFileContents(g_dump_msg, dump_data, dump_size); |
| 986 #if defined(ADDRESS_SANITIZER) |
| 987 // Append a multipart boundary and the contents of the AddressSanitizer log. |
| 988 writer.AddBoundary(); |
| 989 writer.AddFileContents(g_log_msg, log_data, log_size); |
| 990 #endif |
| 920 writer.AddEnd(); | 991 writer.AddEnd(); |
| 921 writer.Flush(); | 992 writer.Flush(); |
| 922 | 993 |
| 923 IGNORE_RET(sys_close(temp_file_fd)); | 994 IGNORE_RET(sys_close(temp_file_fd)); |
| 924 | 995 |
| 925 #if defined(OS_ANDROID) | 996 #if defined(OS_ANDROID) |
| 926 __android_log_write(ANDROID_LOG_WARN, | 997 __android_log_write(ANDROID_LOG_WARN, |
| 927 kGoogleBreakpad, | 998 kGoogleBreakpad, |
| 928 "Output crash dump file:"); | 999 "Output crash dump file:"); |
| 929 __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad, info.filename); | 1000 __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad, info.filename); |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1090 } | 1161 } |
| 1091 if (sys_waitpid(wget_child, NULL, WNOHANG) == 0) { | 1162 if (sys_waitpid(wget_child, NULL, WNOHANG) == 0) { |
| 1092 // Wget process is still around, kill it. | 1163 // Wget process is still around, kill it. |
| 1093 sys_kill(wget_child, SIGKILL); | 1164 sys_kill(wget_child, SIGKILL); |
| 1094 } | 1165 } |
| 1095 } | 1166 } |
| 1096 } | 1167 } |
| 1097 | 1168 |
| 1098 // Helper process. | 1169 // Helper process. |
| 1099 IGNORE_RET(sys_unlink(info.filename)); | 1170 IGNORE_RET(sys_unlink(info.filename)); |
| 1171 #if defined(ADDRESS_SANITIZER) |
| 1172 IGNORE_RET(sys_unlink(info.log_filename)); |
| 1173 #endif |
| 1100 IGNORE_RET(sys_unlink(temp_file)); | 1174 IGNORE_RET(sys_unlink(temp_file)); |
| 1101 sys__exit(0); | 1175 sys__exit(0); |
| 1102 } | 1176 } |
| 1103 | 1177 |
| 1104 // Main browser process. | 1178 // Main browser process. |
| 1105 if (child <= 0) | 1179 if (child <= 0) |
| 1106 return; | 1180 return; |
| 1107 (void) HANDLE_EINTR(sys_waitpid(child, NULL, 0)); | 1181 (void) HANDLE_EINTR(sys_waitpid(child, NULL, 0)); |
| 1108 } | 1182 } |
| 1109 | 1183 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1151 } | 1225 } |
| 1152 | 1226 |
| 1153 // Set the base process start time value. | 1227 // Set the base process start time value. |
| 1154 struct timeval tv; | 1228 struct timeval tv; |
| 1155 if (!gettimeofday(&tv, NULL)) | 1229 if (!gettimeofday(&tv, NULL)) |
| 1156 g_process_start_time = timeval_to_ms(&tv); | 1230 g_process_start_time = timeval_to_ms(&tv); |
| 1157 else | 1231 else |
| 1158 g_process_start_time = 0; | 1232 g_process_start_time = 0; |
| 1159 | 1233 |
| 1160 logging::SetDumpWithoutCrashingFunction(&DumpProcess); | 1234 logging::SetDumpWithoutCrashingFunction(&DumpProcess); |
| 1235 #if defined(ADDRESS_SANITIZER) |
| 1236 // Register the callback for AddressSanitizer error reporting. |
| 1237 __asan_set_error_report_callback(AsanLinuxBreakpadCallback); |
| 1238 #endif |
| 1161 } | 1239 } |
| 1162 | 1240 |
| 1163 bool IsCrashReporterEnabled() { | 1241 bool IsCrashReporterEnabled() { |
| 1164 return g_is_crash_reporter_enabled; | 1242 return g_is_crash_reporter_enabled; |
| 1165 } | 1243 } |
| OLD | NEW |