| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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 "components/crash/app/breakpad_linux.h" | 8 #include "components/crash/app/breakpad_linux.h" |
| 9 | 9 |
| 10 #include <fcntl.h> | 10 #include <fcntl.h> |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 #include "base/path_service.h" | 31 #include "base/path_service.h" |
| 32 #include "base/posix/eintr_wrapper.h" | 32 #include "base/posix/eintr_wrapper.h" |
| 33 #include "base/posix/global_descriptors.h" | 33 #include "base/posix/global_descriptors.h" |
| 34 #include "base/process/memory.h" | 34 #include "base/process/memory.h" |
| 35 #include "base/strings/string_util.h" | 35 #include "base/strings/string_util.h" |
| 36 #include "breakpad/src/client/linux/crash_generation/crash_generation_client.h" | 36 #include "breakpad/src/client/linux/crash_generation/crash_generation_client.h" |
| 37 #include "breakpad/src/client/linux/handler/exception_handler.h" | 37 #include "breakpad/src/client/linux/handler/exception_handler.h" |
| 38 #include "breakpad/src/client/linux/minidump_writer/directory_reader.h" | 38 #include "breakpad/src/client/linux/minidump_writer/directory_reader.h" |
| 39 #include "breakpad/src/common/linux/linux_libc_support.h" | 39 #include "breakpad/src/common/linux/linux_libc_support.h" |
| 40 #include "breakpad/src/common/memory.h" | 40 #include "breakpad/src/common/memory.h" |
| 41 #include "components/crash/app/breakpad_client.h" | |
| 42 #include "components/crash/app/breakpad_linux_impl.h" | 41 #include "components/crash/app/breakpad_linux_impl.h" |
| 42 #include "components/crash/app/crash_reporter_client.h" |
| 43 #include "content/public/common/content_descriptors.h" | 43 #include "content/public/common/content_descriptors.h" |
| 44 | 44 |
| 45 #if defined(OS_ANDROID) | 45 #if defined(OS_ANDROID) |
| 46 #include <android/log.h> | 46 #include <android/log.h> |
| 47 #include <sys/stat.h> | 47 #include <sys/stat.h> |
| 48 | 48 |
| 49 #include "base/android/build_info.h" | 49 #include "base/android/build_info.h" |
| 50 #include "base/android/path_utils.h" | 50 #include "base/android/path_utils.h" |
| 51 #endif | 51 #endif |
| 52 #include "third_party/lss/linux_syscall_support.h" | 52 #include "third_party/lss/linux_syscall_support.h" |
| 53 | 53 |
| 54 #if defined(ADDRESS_SANITIZER) | 54 #if defined(ADDRESS_SANITIZER) |
| 55 #include <ucontext.h> // for getcontext(). | 55 #include <ucontext.h> // for getcontext(). |
| 56 #endif | 56 #endif |
| 57 | 57 |
| 58 #if defined(OS_ANDROID) | 58 #if defined(OS_ANDROID) |
| 59 #define STAT_STRUCT struct stat | 59 #define STAT_STRUCT struct stat |
| 60 #define FSTAT_FUNC fstat | 60 #define FSTAT_FUNC fstat |
| 61 #else | 61 #else |
| 62 #define STAT_STRUCT struct kernel_stat | 62 #define STAT_STRUCT struct kernel_stat |
| 63 #define FSTAT_FUNC sys_fstat | 63 #define FSTAT_FUNC sys_fstat |
| 64 #endif | 64 #endif |
| 65 | 65 |
| 66 // Some versions of gcc are prone to warn about unused return values. In cases | 66 // Some versions of gcc are prone to warn about unused return values. In cases |
| 67 // where we either a) know the call cannot fail, or b) there is nothing we | 67 // where we either a) know the call cannot fail, or b) there is nothing we |
| 68 // can do when a call fails, we mark the return code as ignored. This avoids | 68 // can do when a call fails, we mark the return code as ignored. This avoids |
| 69 // spurious compiler warnings. | 69 // spurious compiler warnings. |
| 70 #define IGNORE_RET(x) do { if (x); } while (0) | 70 #define IGNORE_RET(x) do { if (x); } while (0) |
| 71 | 71 |
| 72 using crash_reporter::GetCrashReporterClient; |
| 72 using google_breakpad::ExceptionHandler; | 73 using google_breakpad::ExceptionHandler; |
| 73 using google_breakpad::MinidumpDescriptor; | 74 using google_breakpad::MinidumpDescriptor; |
| 74 | 75 |
| 75 namespace breakpad { | 76 namespace breakpad { |
| 76 | 77 |
| 77 namespace { | 78 namespace { |
| 78 | 79 |
| 79 #if !defined(OS_CHROMEOS) | 80 #if !defined(OS_CHROMEOS) |
| 80 const char kUploadURL[] = "https://clients2.google.com/cr/report"; | 81 const char kUploadURL[] = "https://clients2.google.com/cr/report"; |
| 81 #endif | 82 #endif |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 while (len > 0 && str[len - 1] == ' ') { | 200 while (len > 0 && str[len - 1] == ' ') { |
| 200 len--; | 201 len--; |
| 201 } | 202 } |
| 202 return len; | 203 return len; |
| 203 } | 204 } |
| 204 | 205 |
| 205 void SetClientIdFromCommandLine(const CommandLine& command_line) { | 206 void SetClientIdFromCommandLine(const CommandLine& command_line) { |
| 206 // Get the guid from the command line switch. | 207 // Get the guid from the command line switch. |
| 207 std::string switch_value = | 208 std::string switch_value = |
| 208 command_line.GetSwitchValueASCII(switches::kEnableCrashReporter); | 209 command_line.GetSwitchValueASCII(switches::kEnableCrashReporter); |
| 209 GetBreakpadClient()->SetBreakpadClientIdFromGUID(switch_value); | 210 GetCrashReporterClient()->SetCrashReporterClientIdFromGUID(switch_value); |
| 210 } | 211 } |
| 211 | 212 |
| 212 // MIME substrings. | 213 // MIME substrings. |
| 213 #if defined(OS_CHROMEOS) | 214 #if defined(OS_CHROMEOS) |
| 214 const char g_sep[] = ":"; | 215 const char g_sep[] = ":"; |
| 215 #endif | 216 #endif |
| 216 const char g_rn[] = "\r\n"; | 217 const char g_rn[] = "\r\n"; |
| 217 const char g_form_data_msg[] = "Content-Disposition: form-data; name=\""; | 218 const char g_form_data_msg[] = "Content-Disposition: form-data; name=\""; |
| 218 const char g_quote_msg[] = "\""; | 219 const char g_quote_msg[] = "\""; |
| 219 const char g_dashdash_msg[] = "--"; | 220 const char g_dashdash_msg[] = "--"; |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 623 } | 624 } |
| 624 #endif | 625 #endif |
| 625 | 626 |
| 626 void EnableCrashDumping(bool unattended) { | 627 void EnableCrashDumping(bool unattended) { |
| 627 g_is_crash_reporter_enabled = true; | 628 g_is_crash_reporter_enabled = true; |
| 628 | 629 |
| 629 base::FilePath tmp_path("/tmp"); | 630 base::FilePath tmp_path("/tmp"); |
| 630 PathService::Get(base::DIR_TEMP, &tmp_path); | 631 PathService::Get(base::DIR_TEMP, &tmp_path); |
| 631 | 632 |
| 632 base::FilePath dumps_path(tmp_path); | 633 base::FilePath dumps_path(tmp_path); |
| 633 if (GetBreakpadClient()->GetCrashDumpLocation(&dumps_path)) { | 634 if (GetCrashReporterClient()->GetCrashDumpLocation(&dumps_path)) { |
| 634 base::FilePath logfile = | 635 base::FilePath logfile = |
| 635 dumps_path.Append(GetBreakpadClient()->GetReporterLogFilename()); | 636 dumps_path.Append(GetCrashReporterClient()->GetReporterLogFilename()); |
| 636 std::string logfile_str = logfile.value(); | 637 std::string logfile_str = logfile.value(); |
| 637 const size_t crash_log_path_len = logfile_str.size() + 1; | 638 const size_t crash_log_path_len = logfile_str.size() + 1; |
| 638 g_crash_log_path = new char[crash_log_path_len]; | 639 g_crash_log_path = new char[crash_log_path_len]; |
| 639 strncpy(g_crash_log_path, logfile_str.c_str(), crash_log_path_len); | 640 strncpy(g_crash_log_path, logfile_str.c_str(), crash_log_path_len); |
| 640 } | 641 } |
| 641 DCHECK(!g_breakpad); | 642 DCHECK(!g_breakpad); |
| 642 MinidumpDescriptor minidump_descriptor(dumps_path.value()); | 643 MinidumpDescriptor minidump_descriptor(dumps_path.value()); |
| 643 minidump_descriptor.set_size_limit(kMaxMinidumpFileSize); | 644 minidump_descriptor.set_size_limit(kMaxMinidumpFileSize); |
| 644 #if defined(OS_ANDROID) | 645 #if defined(OS_ANDROID) |
| 645 unattended = true; // Android never uploads directly. | 646 unattended = true; // Android never uploads directly. |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 860 | 861 |
| 861 void SetCrashKeyValue(const base::StringPiece& key, | 862 void SetCrashKeyValue(const base::StringPiece& key, |
| 862 const base::StringPiece& value) { | 863 const base::StringPiece& value) { |
| 863 g_crash_keys->SetKeyValue(key.data(), value.data()); | 864 g_crash_keys->SetKeyValue(key.data(), value.data()); |
| 864 } | 865 } |
| 865 | 866 |
| 866 void ClearCrashKey(const base::StringPiece& key) { | 867 void ClearCrashKey(const base::StringPiece& key) { |
| 867 g_crash_keys->RemoveKey(key.data()); | 868 g_crash_keys->RemoveKey(key.data()); |
| 868 } | 869 } |
| 869 | 870 |
| 870 // GetBreakpadClient() cannot call any Set methods until after InitCrashKeys(). | 871 // GetCrashReporterClient() cannot call any Set methods until after |
| 872 // InitCrashKeys(). |
| 871 void InitCrashKeys() { | 873 void InitCrashKeys() { |
| 872 g_crash_keys = new CrashKeyStorage; | 874 g_crash_keys = new CrashKeyStorage; |
| 873 GetBreakpadClient()->RegisterCrashKeys(); | 875 GetCrashReporterClient()->RegisterCrashKeys(); |
| 874 base::debug::SetCrashKeyReportingFunctions(&SetCrashKeyValue, &ClearCrashKey); | 876 base::debug::SetCrashKeyReportingFunctions(&SetCrashKeyValue, &ClearCrashKey); |
| 875 } | 877 } |
| 876 | 878 |
| 877 // Miscellaneous initialization functions to call after Breakpad has been | 879 // Miscellaneous initialization functions to call after Breakpad has been |
| 878 // enabled. | 880 // enabled. |
| 879 void PostEnableBreakpadInitialization() { | 881 void PostEnableBreakpadInitialization() { |
| 880 SetProcessStartTime(); | 882 SetProcessStartTime(); |
| 881 g_pid = getpid(); | 883 g_pid = getpid(); |
| 882 | 884 |
| 883 base::debug::SetDumpWithoutCrashingFunction(&DumpProcess); | 885 base::debug::SetDumpWithoutCrashingFunction(&DumpProcess); |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1302 #if defined(OS_CHROMEOS) | 1304 #if defined(OS_CHROMEOS) |
| 1303 CrashReporterWriter writer(temp_file_fd); | 1305 CrashReporterWriter writer(temp_file_fd); |
| 1304 #else | 1306 #else |
| 1305 MimeWriter writer(temp_file_fd, mime_boundary); | 1307 MimeWriter writer(temp_file_fd, mime_boundary); |
| 1306 #endif | 1308 #endif |
| 1307 { | 1309 { |
| 1308 // TODO(thestig) Do not use this inside a compromised context. | 1310 // TODO(thestig) Do not use this inside a compromised context. |
| 1309 std::string product_name; | 1311 std::string product_name; |
| 1310 std::string version; | 1312 std::string version; |
| 1311 | 1313 |
| 1312 GetBreakpadClient()->GetProductNameAndVersion(&product_name, &version); | 1314 GetCrashReporterClient()->GetProductNameAndVersion(&product_name, &version); |
| 1313 | 1315 |
| 1314 writer.AddBoundary(); | 1316 writer.AddBoundary(); |
| 1315 writer.AddPairString("prod", product_name.c_str()); | 1317 writer.AddPairString("prod", product_name.c_str()); |
| 1316 writer.AddBoundary(); | 1318 writer.AddBoundary(); |
| 1317 writer.AddPairString("ver", version.c_str()); | 1319 writer.AddPairString("ver", version.c_str()); |
| 1318 writer.AddBoundary(); | 1320 writer.AddBoundary(); |
| 1319 if (info.pid > 0) { | 1321 if (info.pid > 0) { |
| 1320 char pid_value_buf[kUint64StringSize]; | 1322 char pid_value_buf[kUint64StringSize]; |
| 1321 uint64_t pid_value_len = my_uint64_len(info.pid); | 1323 uint64_t pid_value_len = my_uint64_len(info.pid); |
| 1322 my_uint64tos(pid_value_buf, info.pid, pid_value_len); | 1324 my_uint64tos(pid_value_buf, info.pid, pid_value_len); |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1545 // This will guarantee that the BuildInfo has been initialized and subsequent | 1547 // This will guarantee that the BuildInfo has been initialized and subsequent |
| 1546 // calls will not require memory allocation. | 1548 // calls will not require memory allocation. |
| 1547 base::android::BuildInfo::GetInstance(); | 1549 base::android::BuildInfo::GetInstance(); |
| 1548 #endif | 1550 #endif |
| 1549 // Determine the process type and take appropriate action. | 1551 // Determine the process type and take appropriate action. |
| 1550 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); | 1552 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); |
| 1551 if (parsed_command_line.HasSwitch(switches::kDisableBreakpad)) | 1553 if (parsed_command_line.HasSwitch(switches::kDisableBreakpad)) |
| 1552 return; | 1554 return; |
| 1553 | 1555 |
| 1554 if (process_type.empty()) { | 1556 if (process_type.empty()) { |
| 1555 bool enable_breakpad = GetBreakpadClient()->GetCollectStatsConsent() || | 1557 bool enable_breakpad = GetCrashReporterClient()->GetCollectStatsConsent() || |
| 1556 GetBreakpadClient()->IsRunningUnattended(); | 1558 GetCrashReporterClient()->IsRunningUnattended(); |
| 1557 enable_breakpad &= | 1559 enable_breakpad &= |
| 1558 !parsed_command_line.HasSwitch(switches::kDisableBreakpad); | 1560 !parsed_command_line.HasSwitch(switches::kDisableBreakpad); |
| 1559 if (!enable_breakpad) { | 1561 if (!enable_breakpad) { |
| 1560 enable_breakpad = parsed_command_line.HasSwitch( | 1562 enable_breakpad = parsed_command_line.HasSwitch( |
| 1561 switches::kEnableCrashReporterForTesting); | 1563 switches::kEnableCrashReporterForTesting); |
| 1562 } | 1564 } |
| 1563 if (!enable_breakpad) { | 1565 if (!enable_breakpad) { |
| 1564 VLOG(1) << "Breakpad disabled"; | 1566 VLOG(1) << "Breakpad disabled"; |
| 1565 return; | 1567 return; |
| 1566 } | 1568 } |
| 1567 | 1569 |
| 1568 InitCrashKeys(); | 1570 InitCrashKeys(); |
| 1569 EnableCrashDumping(GetBreakpadClient()->IsRunningUnattended()); | 1571 EnableCrashDumping(GetCrashReporterClient()->IsRunningUnattended()); |
| 1570 } else if (GetBreakpadClient()->EnableBreakpadForProcess(process_type)) { | 1572 } else if (GetCrashReporterClient()->EnableBreakpadForProcess(process_type)) { |
| 1571 #if defined(OS_ANDROID) | 1573 #if defined(OS_ANDROID) |
| 1572 NOTREACHED() << "Breakpad initialized with InitCrashReporter() instead of " | 1574 NOTREACHED() << "Breakpad initialized with InitCrashReporter() instead of " |
| 1573 "InitNonBrowserCrashReporter in " << process_type << " process."; | 1575 "InitNonBrowserCrashReporter in " << process_type << " process."; |
| 1574 return; | 1576 return; |
| 1575 #else | 1577 #else |
| 1576 // We might be chrooted in a zygote or renderer process so we cannot call | 1578 // We might be chrooted in a zygote or renderer process so we cannot call |
| 1577 // GetCollectStatsConsent because that needs access the the user's home | 1579 // GetCollectStatsConsent because that needs access the the user's home |
| 1578 // dir. Instead, we set a command line flag for these processes. | 1580 // dir. Instead, we set a command line flag for these processes. |
| 1579 // Even though plugins are not chrooted, we share the same code path for | 1581 // Even though plugins are not chrooted, we share the same code path for |
| 1580 // simplicity. | 1582 // simplicity. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1591 } | 1593 } |
| 1592 | 1594 |
| 1593 #if defined(OS_ANDROID) | 1595 #if defined(OS_ANDROID) |
| 1594 void InitNonBrowserCrashReporterForAndroid(const std::string& process_type) { | 1596 void InitNonBrowserCrashReporterForAndroid(const std::string& process_type) { |
| 1595 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | 1597 const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 1596 if (command_line->HasSwitch(switches::kEnableCrashReporter)) { | 1598 if (command_line->HasSwitch(switches::kEnableCrashReporter)) { |
| 1597 // On Android we need to provide a FD to the file where the minidump is | 1599 // On Android we need to provide a FD to the file where the minidump is |
| 1598 // generated as the renderer and browser run with different UIDs | 1600 // generated as the renderer and browser run with different UIDs |
| 1599 // (preventing the browser from inspecting the renderer process). | 1601 // (preventing the browser from inspecting the renderer process). |
| 1600 int minidump_fd = base::GlobalDescriptors::GetInstance()->MaybeGet( | 1602 int minidump_fd = base::GlobalDescriptors::GetInstance()->MaybeGet( |
| 1601 GetBreakpadClient()->GetAndroidMinidumpDescriptor()); | 1603 GetCrashReporterClient()->GetAndroidMinidumpDescriptor()); |
| 1602 if (minidump_fd < 0) { | 1604 if (minidump_fd < 0) { |
| 1603 NOTREACHED() << "Could not find minidump FD, crash reporting disabled."; | 1605 NOTREACHED() << "Could not find minidump FD, crash reporting disabled."; |
| 1604 } else { | 1606 } else { |
| 1605 EnableNonBrowserCrashDumping(process_type, minidump_fd); | 1607 EnableNonBrowserCrashDumping(process_type, minidump_fd); |
| 1606 } | 1608 } |
| 1607 } | 1609 } |
| 1608 } | 1610 } |
| 1609 #endif // OS_ANDROID | 1611 #endif // OS_ANDROID |
| 1610 | 1612 |
| 1611 bool IsCrashReporterEnabled() { | 1613 bool IsCrashReporterEnabled() { |
| 1612 return g_is_crash_reporter_enabled; | 1614 return g_is_crash_reporter_enabled; |
| 1613 } | 1615 } |
| 1614 | 1616 |
| 1615 } // namespace breakpad | 1617 } // namespace breakpad |
| OLD | NEW |