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 | 7 |
8 #include "chrome/app/breakpad_linux.h" | 8 #include "chrome/app/breakpad_linux.h" |
9 | 9 |
10 #include <fcntl.h> | 10 #include <fcntl.h> |
11 #include <poll.h> | 11 #include <poll.h> |
12 #include <signal.h> | 12 #include <signal.h> |
13 #include <stdlib.h> | 13 #include <stdlib.h> |
14 #include <sys/socket.h> | 14 #include <sys/socket.h> |
15 #include <sys/time.h> | 15 #include <sys/time.h> |
16 #include <sys/types.h> | 16 #include <sys/types.h> |
17 #include <sys/uio.h> | 17 #include <sys/uio.h> |
18 #include <sys/wait.h> | 18 #include <sys/wait.h> |
19 #include <time.h> | 19 #include <time.h> |
20 #include <unistd.h> | 20 #include <unistd.h> |
21 | 21 |
22 #include <algorithm> | 22 #include <algorithm> |
23 #include <string> | 23 #include <string> |
24 | 24 |
25 #include "base/command_line.h" | 25 #include "base/command_line.h" |
| 26 #include "base/debug/crash_logging.h" |
26 #include "base/files/file_path.h" | 27 #include "base/files/file_path.h" |
27 #include "base/linux_util.h" | 28 #include "base/linux_util.h" |
28 #include "base/path_service.h" | 29 #include "base/path_service.h" |
29 #include "base/platform_file.h" | 30 #include "base/platform_file.h" |
30 #include "base/posix/eintr_wrapper.h" | 31 #include "base/posix/eintr_wrapper.h" |
31 #include "base/posix/global_descriptors.h" | 32 #include "base/posix/global_descriptors.h" |
32 #include "base/process_util.h" | 33 #include "base/process_util.h" |
33 #include "base/string_util.h" | 34 #include "base/string_util.h" |
34 #include "breakpad/src/client/linux/handler/exception_handler.h" | 35 #include "breakpad/src/client/linux/handler/exception_handler.h" |
35 #include "breakpad/src/client/linux/minidump_writer/directory_reader.h" | 36 #include "breakpad/src/client/linux/minidump_writer/directory_reader.h" |
36 #include "breakpad/src/common/linux/linux_libc_support.h" | 37 #include "breakpad/src/common/linux/linux_libc_support.h" |
37 #include "breakpad/src/common/memory.h" | 38 #include "breakpad/src/common/memory.h" |
| 39 #include "chrome/app/breakpad_linux_impl.h" |
38 #include "chrome/browser/crash_upload_list.h" | 40 #include "chrome/browser/crash_upload_list.h" |
39 #include "chrome/common/child_process_logging.h" | 41 #include "chrome/common/child_process_logging.h" |
40 #include "chrome/common/chrome_paths.h" | 42 #include "chrome/common/chrome_paths.h" |
41 #include "chrome/common/chrome_switches.h" | 43 #include "chrome/common/chrome_switches.h" |
42 #include "chrome/common/chrome_version_info_posix.h" | 44 #include "chrome/common/chrome_version_info_posix.h" |
| 45 #include "chrome/common/crash_keys.h" |
43 #include "chrome/common/dump_without_crashing.h" | 46 #include "chrome/common/dump_without_crashing.h" |
44 #include "chrome/common/env_vars.h" | 47 #include "chrome/common/env_vars.h" |
45 #include "chrome/common/logging_chrome.h" | 48 #include "chrome/common/logging_chrome.h" |
46 #include "content/public/common/content_descriptors.h" | 49 #include "content/public/common/content_descriptors.h" |
47 | 50 |
48 #if defined(OS_ANDROID) | 51 #if defined(OS_ANDROID) |
49 #include <android/log.h> | 52 #include <android/log.h> |
50 #include <sys/stat.h> | 53 #include <sys/stat.h> |
51 | 54 |
52 #include "base/android/build_info.h" | 55 #include "base/android/build_info.h" |
(...skipping 24 matching lines...) Expand all Loading... |
77 using google_breakpad::MinidumpDescriptor; | 80 using google_breakpad::MinidumpDescriptor; |
78 | 81 |
79 namespace { | 82 namespace { |
80 | 83 |
81 const char kUploadURL[] = "https://clients2.google.com/cr/report"; | 84 const char kUploadURL[] = "https://clients2.google.com/cr/report"; |
82 | 85 |
83 bool g_is_crash_reporter_enabled = false; | 86 bool g_is_crash_reporter_enabled = false; |
84 uint64_t g_process_start_time = 0; | 87 uint64_t g_process_start_time = 0; |
85 char* g_crash_log_path = NULL; | 88 char* g_crash_log_path = NULL; |
86 ExceptionHandler* g_breakpad = NULL; | 89 ExceptionHandler* g_breakpad = NULL; |
| 90 |
87 #if defined(ADDRESS_SANITIZER) | 91 #if defined(ADDRESS_SANITIZER) |
88 const char* g_asan_report_str = NULL; | 92 const char* g_asan_report_str = NULL; |
89 #endif | 93 #endif |
90 #if defined(OS_ANDROID) | 94 #if defined(OS_ANDROID) |
91 char* g_process_type = NULL; | 95 char* g_process_type = NULL; |
92 #endif | 96 #endif |
93 | 97 |
| 98 CrashKeyStorage* g_crash_keys = NULL; |
| 99 |
94 // Writes the value |v| as 16 hex characters to the memory pointed at by | 100 // Writes the value |v| as 16 hex characters to the memory pointed at by |
95 // |output|. | 101 // |output|. |
96 void write_uint64_hex(char* output, uint64_t v) { | 102 void write_uint64_hex(char* output, uint64_t v) { |
97 static const char hextable[] = "0123456789abcdef"; | 103 static const char hextable[] = "0123456789abcdef"; |
98 | 104 |
99 for (int i = 15; i >= 0; --i) { | 105 for (int i = 15; i >= 0; --i) { |
100 output[i] = hextable[v & 15]; | 106 output[i] = hextable[v & 15]; |
101 v >>= 4; | 107 v >>= 4; |
102 } | 108 } |
103 } | 109 } |
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
476 info.crash_url = NULL; | 482 info.crash_url = NULL; |
477 info.crash_url_length = 0; | 483 info.crash_url_length = 0; |
478 info.guid = child_process_logging::g_client_id; | 484 info.guid = child_process_logging::g_client_id; |
479 info.guid_length = my_strlen(child_process_logging::g_client_id); | 485 info.guid_length = my_strlen(child_process_logging::g_client_id); |
480 info.distro = base::g_linux_distro; | 486 info.distro = base::g_linux_distro; |
481 info.distro_length = my_strlen(base::g_linux_distro); | 487 info.distro_length = my_strlen(base::g_linux_distro); |
482 info.upload = upload; | 488 info.upload = upload; |
483 info.process_start_time = g_process_start_time; | 489 info.process_start_time = g_process_start_time; |
484 info.oom_size = base::g_oom_size; | 490 info.oom_size = base::g_oom_size; |
485 info.pid = 0; | 491 info.pid = 0; |
| 492 info.crash_keys = g_crash_keys; |
486 HandleCrashDump(info); | 493 HandleCrashDump(info); |
487 #if defined(OS_ANDROID) | 494 #if defined(OS_ANDROID) |
488 return FinalizeCrashDoneAndroid(); | 495 return FinalizeCrashDoneAndroid(); |
489 #else | 496 #else |
490 return true; | 497 return true; |
491 #endif | 498 #endif |
492 } | 499 } |
493 | 500 |
494 // Wrapper function, do not add more code here. | 501 // Wrapper function, do not add more code here. |
495 bool CrashDoneNoUpload(const MinidumpDescriptor& minidump, | 502 bool CrashDoneNoUpload(const MinidumpDescriptor& minidump, |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
656 char b; // Dummy variable for sys_read below. | 663 char b; // Dummy variable for sys_read below. |
657 const char* b_addr = &b; // Get the address of |b| so we can create the | 664 const char* b_addr = &b; // Get the address of |b| so we can create the |
658 // expected /proc/[pid]/syscall content in the | 665 // expected /proc/[pid]/syscall content in the |
659 // browser to convert namespace tids. | 666 // browser to convert namespace tids. |
660 | 667 |
661 // The length of the control message: | 668 // The length of the control message: |
662 static const unsigned kControlMsgSize = sizeof(fds); | 669 static const unsigned kControlMsgSize = sizeof(fds); |
663 static const unsigned kControlMsgSpaceSize = CMSG_SPACE(kControlMsgSize); | 670 static const unsigned kControlMsgSpaceSize = CMSG_SPACE(kControlMsgSize); |
664 static const unsigned kControlMsgLenSize = CMSG_LEN(kControlMsgSize); | 671 static const unsigned kControlMsgLenSize = CMSG_LEN(kControlMsgSize); |
665 | 672 |
666 #if !defined(ADDRESS_SANITIZER) | |
667 const size_t kIovSize = 8; | |
668 #else | |
669 // Additional field to pass the AddressSanitizer log to the crash handler. | |
670 const size_t kIovSize = 9; | |
671 #endif | |
672 struct kernel_msghdr msg; | 673 struct kernel_msghdr msg; |
673 my_memset(&msg, 0, sizeof(struct kernel_msghdr)); | 674 my_memset(&msg, 0, sizeof(struct kernel_msghdr)); |
674 struct kernel_iovec iov[kIovSize]; | 675 struct kernel_iovec iov[kCrashIovSize]; |
675 iov[0].iov_base = const_cast<void*>(crash_context); | 676 iov[0].iov_base = const_cast<void*>(crash_context); |
676 iov[0].iov_len = crash_context_size; | 677 iov[0].iov_len = crash_context_size; |
677 iov[1].iov_base = guid; | 678 iov[1].iov_base = guid; |
678 iov[1].iov_len = kGuidSize + 1; | 679 iov[1].iov_len = kGuidSize + 1; |
679 iov[2].iov_base = crash_url; | 680 iov[2].iov_base = crash_url; |
680 iov[2].iov_len = kMaxActiveURLSize + 1; | 681 iov[2].iov_len = kMaxActiveURLSize + 1; |
681 iov[3].iov_base = distro; | 682 iov[3].iov_base = distro; |
682 iov[3].iov_len = kDistroSize + 1; | 683 iov[3].iov_len = kDistroSize + 1; |
683 iov[4].iov_base = &b_addr; | 684 iov[4].iov_base = &b_addr; |
684 iov[4].iov_len = sizeof(b_addr); | 685 iov[4].iov_len = sizeof(b_addr); |
685 iov[5].iov_base = &fds[0]; | 686 iov[5].iov_base = &fds[0]; |
686 iov[5].iov_len = sizeof(fds[0]); | 687 iov[5].iov_len = sizeof(fds[0]); |
687 iov[6].iov_base = &g_process_start_time; | 688 iov[6].iov_base = &g_process_start_time; |
688 iov[6].iov_len = sizeof(g_process_start_time); | 689 iov[6].iov_len = sizeof(g_process_start_time); |
689 iov[7].iov_base = &base::g_oom_size; | 690 iov[7].iov_base = &base::g_oom_size; |
690 iov[7].iov_len = sizeof(base::g_oom_size); | 691 iov[7].iov_len = sizeof(base::g_oom_size); |
| 692 google_breakpad::SerializedNonAllocatingMap* serialized_map; |
| 693 iov[8].iov_len = g_crash_keys->Serialize( |
| 694 const_cast<const google_breakpad::SerializedNonAllocatingMap**>( |
| 695 &serialized_map)); |
| 696 iov[8].iov_base = serialized_map; |
691 #if defined(ADDRESS_SANITIZER) | 697 #if defined(ADDRESS_SANITIZER) |
692 iov[8].iov_base = const_cast<char*>(g_asan_report_str); | 698 iov[9].iov_base = const_cast<char*>(g_asan_report_str); |
693 iov[8].iov_len = kMaxAsanReportSize + 1; | 699 iov[9].iov_len = kMaxAsanReportSize + 1; |
694 #endif | 700 #endif |
695 | 701 |
696 msg.msg_iov = iov; | 702 msg.msg_iov = iov; |
697 msg.msg_iovlen = kIovSize; | 703 msg.msg_iovlen = kCrashIovSize; |
698 char cmsg[kControlMsgSpaceSize]; | 704 char cmsg[kControlMsgSpaceSize]; |
699 my_memset(cmsg, 0, kControlMsgSpaceSize); | 705 my_memset(cmsg, 0, kControlMsgSpaceSize); |
700 msg.msg_control = cmsg; | 706 msg.msg_control = cmsg; |
701 msg.msg_controllen = sizeof(cmsg); | 707 msg.msg_controllen = sizeof(cmsg); |
702 | 708 |
703 struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); | 709 struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); |
704 hdr->cmsg_level = SOL_SOCKET; | 710 hdr->cmsg_level = SOL_SOCKET; |
705 hdr->cmsg_type = SCM_RIGHTS; | 711 hdr->cmsg_type = SCM_RIGHTS; |
706 hdr->cmsg_len = kControlMsgLenSize; | 712 hdr->cmsg_len = kControlMsgLenSize; |
707 ((int*) CMSG_DATA(hdr))[0] = fds[0]; | 713 ((int*) CMSG_DATA(hdr))[0] = fds[0]; |
(...skipping 25 matching lines...) Expand all Loading... |
733 MinidumpDescriptor("/tmp"), // Unused but needed or Breakpad will assert. | 739 MinidumpDescriptor("/tmp"), // Unused but needed or Breakpad will assert. |
734 NULL, | 740 NULL, |
735 NULL, | 741 NULL, |
736 reinterpret_cast<void*>(fd), // Param passed to the crash handler. | 742 reinterpret_cast<void*>(fd), // Param passed to the crash handler. |
737 true, | 743 true, |
738 -1); | 744 -1); |
739 g_breakpad->set_crash_handler(NonBrowserCrashHandler); | 745 g_breakpad->set_crash_handler(NonBrowserCrashHandler); |
740 } | 746 } |
741 #endif // defined(OS_ANDROID) | 747 #endif // defined(OS_ANDROID) |
742 | 748 |
| 749 void SetCrashKeyValue(const base::StringPiece& key, |
| 750 const base::StringPiece& value) { |
| 751 g_crash_keys->SetKeyValue(key.data(), value.data()); |
| 752 } |
| 753 |
| 754 void ClearCrashKey(const base::StringPiece& key) { |
| 755 g_crash_keys->RemoveKey(key.data()); |
| 756 } |
| 757 |
743 } // namespace | 758 } // namespace |
744 | 759 |
745 void LoadDataFromFD(google_breakpad::PageAllocator& allocator, | 760 void LoadDataFromFD(google_breakpad::PageAllocator& allocator, |
746 int fd, bool close_fd, uint8_t** file_data, size_t* size) { | 761 int fd, bool close_fd, uint8_t** file_data, size_t* size) { |
747 STAT_STRUCT st; | 762 STAT_STRUCT st; |
748 if (FSTAT_FUNC(fd, &st) != 0) { | 763 if (FSTAT_FUNC(fd, &st) != 0) { |
749 static const char msg[] = "Cannot upload crash dump: stat failed\n"; | 764 static const char msg[] = "Cannot upload crash dump: stat failed\n"; |
750 WriteLog(msg, sizeof(msg) - 1); | 765 WriteLog(msg, sizeof(msg) - 1); |
751 if (close_fd) | 766 if (close_fd) |
752 IGNORE_RET(sys_close(fd)); | 767 IGNORE_RET(sys_close(fd)); |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
966 // zero to 15: | 981 // zero to 15: |
967 // Content-Disposition: form-data; name="switch-1" \r\n \r\n | 982 // Content-Disposition: form-data; name="switch-1" \r\n \r\n |
968 // --foo \r\n | 983 // --foo \r\n |
969 // BOUNDARY \r\n | 984 // BOUNDARY \r\n |
970 // | 985 // |
971 // zero or one: | 986 // zero or one: |
972 // Content-Disposition: form-data; name="oom-size" \r\n \r\n | 987 // Content-Disposition: form-data; name="oom-size" \r\n \r\n |
973 // 1234567890 \r\n | 988 // 1234567890 \r\n |
974 // BOUNDARY \r\n | 989 // BOUNDARY \r\n |
975 // | 990 // |
| 991 // zero or more (up to CrashKeyStorage::num_entries = 64): |
| 992 // Content-Disposition: form-data; name=crash-key-name \r\n |
| 993 // crash-key-value \r\n |
| 994 // BOUNDARY \r\n |
| 995 // |
976 // Content-Disposition: form-data; name="dump"; filename="dump" \r\n | 996 // Content-Disposition: form-data; name="dump"; filename="dump" \r\n |
977 // Content-Type: application/octet-stream \r\n \r\n | 997 // Content-Type: application/octet-stream \r\n \r\n |
978 // <dump contents> | 998 // <dump contents> |
979 // \r\n BOUNDARY -- \r\n | 999 // \r\n BOUNDARY -- \r\n |
980 | 1000 |
981 MimeWriter writer(temp_file_fd, mime_boundary); | 1001 MimeWriter writer(temp_file_fd, mime_boundary); |
982 { | 1002 { |
983 #if defined(OS_ANDROID) | 1003 #if defined(OS_ANDROID) |
984 static const char chrome_product_msg[] = "Chrome_Android"; | 1004 static const char chrome_product_msg[] = "Chrome_Android"; |
985 #elif defined(OS_CHROMEOS) | 1005 #elif defined(OS_CHROMEOS) |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1204 char oom_size_str[kUint64StringSize]; | 1224 char oom_size_str[kUint64StringSize]; |
1205 const unsigned oom_size_len = my_uint64_len(info.oom_size); | 1225 const unsigned oom_size_len = my_uint64_len(info.oom_size); |
1206 my_uint64tos(oom_size_str, info.oom_size, oom_size_len); | 1226 my_uint64tos(oom_size_str, info.oom_size, oom_size_len); |
1207 static const char oom_size_msg[] = "oom-size"; | 1227 static const char oom_size_msg[] = "oom-size"; |
1208 writer.AddPairData(oom_size_msg, sizeof(oom_size_msg) - 1, | 1228 writer.AddPairData(oom_size_msg, sizeof(oom_size_msg) - 1, |
1209 oom_size_str, oom_size_len); | 1229 oom_size_str, oom_size_len); |
1210 writer.AddBoundary(); | 1230 writer.AddBoundary(); |
1211 writer.Flush(); | 1231 writer.Flush(); |
1212 } | 1232 } |
1213 | 1233 |
| 1234 if (info.crash_keys) { |
| 1235 CrashKeyStorage::Iterator crash_key_iterator(*info.crash_keys); |
| 1236 const CrashKeyStorage::Entry* entry; |
| 1237 while ((entry = crash_key_iterator.Next())) { |
| 1238 writer.AddPairString(entry->key, entry->value); |
| 1239 writer.AddBoundary(); |
| 1240 writer.Flush(); |
| 1241 } |
| 1242 } |
| 1243 |
1214 writer.AddFileContents(g_dump_msg, dump_data, dump_size); | 1244 writer.AddFileContents(g_dump_msg, dump_data, dump_size); |
1215 #if defined(ADDRESS_SANITIZER) | 1245 #if defined(ADDRESS_SANITIZER) |
1216 // Append a multipart boundary and the contents of the AddressSanitizer log. | 1246 // Append a multipart boundary and the contents of the AddressSanitizer log. |
1217 writer.AddBoundary(); | 1247 writer.AddBoundary(); |
1218 writer.AddFileContents(g_log_msg, log_data, log_size); | 1248 writer.AddFileContents(g_log_msg, log_data, log_size); |
1219 #endif | 1249 #endif |
1220 writer.AddEnd(); | 1250 writer.AddEnd(); |
1221 writer.Flush(); | 1251 writer.Flush(); |
1222 | 1252 |
1223 IGNORE_RET(sys_close(temp_file_fd)); | 1253 IGNORE_RET(sys_close(temp_file_fd)); |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1466 #endif // #if defined(OS_ANDROID) | 1496 #endif // #if defined(OS_ANDROID) |
1467 } | 1497 } |
1468 | 1498 |
1469 SetProcessStartTime(); | 1499 SetProcessStartTime(); |
1470 | 1500 |
1471 logging::SetDumpWithoutCrashingFunction(&DumpProcess); | 1501 logging::SetDumpWithoutCrashingFunction(&DumpProcess); |
1472 #if defined(ADDRESS_SANITIZER) | 1502 #if defined(ADDRESS_SANITIZER) |
1473 // Register the callback for AddressSanitizer error reporting. | 1503 // Register the callback for AddressSanitizer error reporting. |
1474 __asan_set_error_report_callback(AsanLinuxBreakpadCallback); | 1504 __asan_set_error_report_callback(AsanLinuxBreakpadCallback); |
1475 #endif | 1505 #endif |
| 1506 |
| 1507 g_crash_keys = new CrashKeyStorage; |
| 1508 crash_keys::RegisterChromeCrashKeys(); |
| 1509 base::debug::SetCrashKeyReportingFunctions( |
| 1510 &SetCrashKeyValue, &ClearCrashKey); |
1476 } | 1511 } |
1477 | 1512 |
1478 #if defined(OS_ANDROID) | 1513 #if defined(OS_ANDROID) |
1479 void InitNonBrowserCrashReporterForAndroid() { | 1514 void InitNonBrowserCrashReporterForAndroid() { |
1480 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | 1515 const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
1481 if (command_line->HasSwitch(switches::kEnableCrashReporter)) { | 1516 if (command_line->HasSwitch(switches::kEnableCrashReporter)) { |
1482 // On Android we need to provide a FD to the file where the minidump is | 1517 // On Android we need to provide a FD to the file where the minidump is |
1483 // generated as the renderer and browser run with different UIDs | 1518 // generated as the renderer and browser run with different UIDs |
1484 // (preventing the browser from inspecting the renderer process). | 1519 // (preventing the browser from inspecting the renderer process). |
1485 int minidump_fd = base::GlobalDescriptors::GetInstance()-> | 1520 int minidump_fd = base::GlobalDescriptors::GetInstance()-> |
1486 MaybeGet(kAndroidMinidumpDescriptor); | 1521 MaybeGet(kAndroidMinidumpDescriptor); |
1487 if (minidump_fd == base::kInvalidPlatformFileValue) { | 1522 if (minidump_fd == base::kInvalidPlatformFileValue) { |
1488 NOTREACHED() << "Could not find minidump FD, crash reporting disabled."; | 1523 NOTREACHED() << "Could not find minidump FD, crash reporting disabled."; |
1489 } else { | 1524 } else { |
1490 EnableNonBrowserCrashDumping(minidump_fd); | 1525 EnableNonBrowserCrashDumping(minidump_fd); |
1491 } | 1526 } |
1492 } | 1527 } |
1493 } | 1528 } |
1494 #endif // OS_ANDROID | 1529 #endif // OS_ANDROID |
1495 | 1530 |
1496 bool IsCrashReporterEnabled() { | 1531 bool IsCrashReporterEnabled() { |
1497 return g_is_crash_reporter_enabled; | 1532 return g_is_crash_reporter_enabled; |
1498 } | 1533 } |
OLD | NEW |