| 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/content/app/breakpad_linux.h" | 8 #include "components/crash/content/app/breakpad_linux.h" |
| 9 | 9 |
| 10 #include <fcntl.h> | 10 #include <fcntl.h> |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 uint32_t g_dumps_suppressed = 0; | 106 uint32_t g_dumps_suppressed = 0; |
| 107 char* g_process_type = nullptr; | 107 char* g_process_type = nullptr; |
| 108 ExceptionHandler* g_microdump = nullptr; | 108 ExceptionHandler* g_microdump = nullptr; |
| 109 int g_signal_code_pipe_fd = -1; | 109 int g_signal_code_pipe_fd = -1; |
| 110 | 110 |
| 111 class MicrodumpInfo { | 111 class MicrodumpInfo { |
| 112 public: | 112 public: |
| 113 MicrodumpInfo() | 113 MicrodumpInfo() |
| 114 : microdump_build_fingerprint_(nullptr), | 114 : microdump_build_fingerprint_(nullptr), |
| 115 microdump_product_info_(nullptr), | 115 microdump_product_info_(nullptr), |
| 116 microdump_gpu_fingerprint_(nullptr) {} | 116 microdump_gpu_fingerprint_(nullptr), |
| 117 microdump_process_type_(nullptr), |
| 118 skip_dump_if_principal_mapping_not_referenced_(false), |
| 119 address_within_principal_mapping_(0ul), |
| 120 should_sanitize_dumps_(false) {} |
| 117 | 121 |
| 118 // The order in which SetGpuFingerprint and Initialize are called | 122 // The order in which SetGpuFingerprint and Initialize are called |
| 119 // may be dependent on the timing of the availability of GPU | 123 // may be dependent on the timing of the availability of GPU |
| 120 // information. For this reason, they can be called in either order, | 124 // information. For this reason, they can be called in either order, |
| 121 // resulting in the same effect. | 125 // resulting in the same effect. |
| 122 // | 126 // |
| 123 // The following restrictions apply, however: | 127 // The following restrictions apply, however: |
| 124 // * Both methods must be called from the same thread. | 128 // * Both methods must be called from the same thread. |
| 125 // * Both methods must be called at most once. | 129 // * Both methods must be called at most once. |
| 126 // | 130 // |
| 127 // Microdumps will only be generated if Initialize is called. If | 131 // Microdumps will only be generated if Initialize is called. If |
| 128 // SetGpuFingerprint has not been called called at the point at | 132 // SetGpuFingerprint has not been called called at the point at |
| 129 // which a microdump is generated, then the GPU fingerprint will be | 133 // which a microdump is generated, then the GPU fingerprint will be |
| 130 // UNKNOWN. | 134 // UNKNOWN. |
| 131 void SetGpuFingerprint(const std::string& gpu_fingerprint); | 135 void SetGpuFingerprint(const std::string& gpu_fingerprint); |
| 136 void SetSkipDumpIfPrincipalMappingNotReferenced( |
| 137 uintptr_t address_within_principal_mapping); |
| 138 void SetShouldSanitizeDumps(bool should_sanitize_dumps); |
| 139 void UpdateMinidumpDescriptor(MinidumpDescriptor* minidump_descriptor); |
| 140 void UpdateExceptionHandlers(); |
| 132 void Initialize(const std::string& process_type, | 141 void Initialize(const std::string& process_type, |
| 133 const char* product_name, | 142 const char* product_name, |
| 134 const char* product_version, | 143 const char* product_version, |
| 135 const char* android_build_fp); | 144 const char* android_build_fp); |
| 136 | 145 |
| 137 private: | 146 private: |
| 138 base::ThreadChecker thread_checker_; | 147 base::ThreadChecker thread_checker_; |
| 139 const char* microdump_build_fingerprint_; | 148 const char* microdump_build_fingerprint_; |
| 140 const char* microdump_product_info_; | 149 const char* microdump_product_info_; |
| 141 const char* microdump_gpu_fingerprint_; | 150 const char* microdump_gpu_fingerprint_; |
| 142 const char* microdump_process_type_; | 151 const char* microdump_process_type_; |
| 152 bool skip_dump_if_principal_mapping_not_referenced_; |
| 153 uintptr_t address_within_principal_mapping_; |
| 154 bool should_sanitize_dumps_; |
| 143 }; | 155 }; |
| 144 | 156 |
| 145 base::LazyInstance<MicrodumpInfo> g_microdump_info = | 157 base::LazyInstance<MicrodumpInfo> g_microdump_info = |
| 146 LAZY_INSTANCE_INITIALIZER; | 158 LAZY_INSTANCE_INITIALIZER; |
| 147 | 159 |
| 148 #endif | 160 #endif |
| 149 | 161 |
| 150 CrashKeyStorage* g_crash_keys = nullptr; | 162 CrashKeyStorage* g_crash_keys = nullptr; |
| 151 | 163 |
| 152 // Writes the value |v| as 16 hex characters to the memory pointed at by | 164 // Writes the value |v| as 16 hex characters to the memory pointed at by |
| (...skipping 570 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 723 void* context, | 735 void* context, |
| 724 bool succeeded) { | 736 bool succeeded) { |
| 725 return CrashDone(minidump, true, true, succeeded); | 737 return CrashDone(minidump, true, true, succeeded); |
| 726 } | 738 } |
| 727 #endif | 739 #endif |
| 728 | 740 |
| 729 void DumpProcess() { | 741 void DumpProcess() { |
| 730 #if defined(OS_ANDROID) | 742 #if defined(OS_ANDROID) |
| 731 // Don't use g_breakpad and g_microdump directly here, because their | 743 // Don't use g_breakpad and g_microdump directly here, because their |
| 732 // output might currently be suppressed. | 744 // output might currently be suppressed. |
| 733 if (g_breakpad) { | 745 |
| 746 // If a breakpad handler is installed, but its target is a file |
| 747 // descriptor, we can't generate a dump because we can't risk |
| 748 // writing multiple minidumps to the FD, so it can only be used for |
| 749 // dumps that are associated with a crash. |
| 750 if (g_breakpad && !g_breakpad->minidump_descriptor().IsFD()) { |
| 734 ExceptionHandler(g_breakpad->minidump_descriptor(), | 751 ExceptionHandler(g_breakpad->minidump_descriptor(), |
| 735 nullptr, | 752 nullptr, |
| 736 CrashDoneNoUpload, | 753 CrashDoneNoUpload, |
| 737 nullptr, | 754 nullptr, |
| 738 false, -1).WriteMinidump(); | 755 false, -1).WriteMinidump(); |
| 739 } | 756 } |
| 740 // If microdumps are enabled write also a microdump on the system log. | 757 // If microdumps are enabled write also a microdump on the system log. |
| 741 if (g_microdump) { | 758 if (g_microdump) { |
| 742 ExceptionHandler(g_microdump->minidump_descriptor(), | 759 ExceptionHandler(g_microdump->minidump_descriptor(), |
| 743 nullptr, | 760 nullptr, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 781 DCHECK(!g_breakpad); | 798 DCHECK(!g_breakpad); |
| 782 MinidumpDescriptor minidump_descriptor(dumps_path.value()); | 799 MinidumpDescriptor minidump_descriptor(dumps_path.value()); |
| 783 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 800 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 784 switches::kFullMemoryCrashReport)) { | 801 switches::kFullMemoryCrashReport)) { |
| 785 minidump_descriptor.set_size_limit(-1); // unlimited. | 802 minidump_descriptor.set_size_limit(-1); // unlimited. |
| 786 } else { | 803 } else { |
| 787 minidump_descriptor.set_size_limit(kMaxMinidumpFileSize); | 804 minidump_descriptor.set_size_limit(kMaxMinidumpFileSize); |
| 788 } | 805 } |
| 789 #if defined(OS_ANDROID) | 806 #if defined(OS_ANDROID) |
| 790 unattended = true; // Android never uploads directly. | 807 unattended = true; // Android never uploads directly. |
| 808 g_microdump_info.Get().UpdateMinidumpDescriptor(&minidump_descriptor); |
| 791 #endif | 809 #endif |
| 792 if (unattended) { | 810 if (unattended) { |
| 793 g_breakpad = new ExceptionHandler( | 811 g_breakpad = new ExceptionHandler( |
| 794 minidump_descriptor, | 812 minidump_descriptor, |
| 795 #if defined(OS_ANDROID) | 813 #if defined(OS_ANDROID) |
| 796 ShouldGenerateDump, | 814 ShouldGenerateDump, |
| 797 #else | 815 #else |
| 798 nullptr, | 816 nullptr, |
| 799 #endif | 817 #endif |
| 800 CrashDoneNoUpload, | 818 CrashDoneNoUpload, |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 834 return false; | 852 return false; |
| 835 } | 853 } |
| 836 | 854 |
| 837 bool CrashDoneInProcessNoUpload( | 855 bool CrashDoneInProcessNoUpload( |
| 838 const google_breakpad::MinidumpDescriptor& descriptor, | 856 const google_breakpad::MinidumpDescriptor& descriptor, |
| 839 void* context, | 857 void* context, |
| 840 const bool succeeded) { | 858 const bool succeeded) { |
| 841 // WARNING: this code runs in a compromised context. It may not call into | 859 // WARNING: this code runs in a compromised context. It may not call into |
| 842 // libc nor allocate memory normally. | 860 // libc nor allocate memory normally. |
| 843 if (!succeeded) { | 861 if (!succeeded) { |
| 844 static const char msg[] = "Crash dump generation failed.\n"; | 862 if (ShouldGenerateDump(nullptr)) { |
| 845 WriteLog(msg, sizeof(msg) - 1); | 863 static const char msg[] = "Crash dump generation failed.\n"; |
| 864 WriteLog(msg, sizeof(msg) - 1); |
| 865 } |
| 846 return false; | 866 return false; |
| 847 } | 867 } |
| 848 | 868 |
| 849 // Start constructing the message to send to the browser. | 869 // Start constructing the message to send to the browser. |
| 850 BreakpadInfo info = {0}; | 870 BreakpadInfo info = {0}; |
| 851 info.filename = nullptr; | 871 info.filename = nullptr; |
| 852 info.fd = descriptor.fd(); | 872 info.fd = descriptor.fd(); |
| 853 info.process_type = g_process_type; | 873 info.process_type = g_process_type; |
| 854 info.process_type_length = my_strlen(g_process_type); | 874 info.process_type_length = my_strlen(g_process_type); |
| 855 info.distro = nullptr; | 875 info.distro = nullptr; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 883 return; | 903 return; |
| 884 } | 904 } |
| 885 SetProcessStartTime(); | 905 SetProcessStartTime(); |
| 886 g_pid = getpid(); | 906 g_pid = getpid(); |
| 887 | 907 |
| 888 g_is_crash_reporter_enabled = true; | 908 g_is_crash_reporter_enabled = true; |
| 889 // Save the process type (it is leaked). | 909 // Save the process type (it is leaked). |
| 890 const size_t process_type_len = process_type.size() + 1; | 910 const size_t process_type_len = process_type.size() + 1; |
| 891 g_process_type = new char[process_type_len]; | 911 g_process_type = new char[process_type_len]; |
| 892 strncpy(g_process_type, process_type.c_str(), process_type_len); | 912 strncpy(g_process_type, process_type.c_str(), process_type_len); |
| 893 new ExceptionHandler(MinidumpDescriptor(minidump_fd), ShouldGenerateDump, | 913 |
| 894 CrashDoneInProcessNoUpload, nullptr, true, -1); | 914 MinidumpDescriptor descriptor(minidump_fd); |
| 915 g_microdump_info.Get().UpdateMinidumpDescriptor(&descriptor); |
| 916 g_breakpad = |
| 917 new ExceptionHandler(descriptor, ShouldGenerateDump, |
| 918 CrashDoneInProcessNoUpload, nullptr, true, -1); |
| 895 } | 919 } |
| 896 | 920 |
| 897 void MicrodumpInfo::SetGpuFingerprint(const std::string& gpu_fingerprint) { | 921 void MicrodumpInfo::SetGpuFingerprint(const std::string& gpu_fingerprint) { |
| 898 DCHECK(thread_checker_.CalledOnValidThread()); | 922 DCHECK(thread_checker_.CalledOnValidThread()); |
| 899 DCHECK(!microdump_gpu_fingerprint_); | 923 DCHECK(!microdump_gpu_fingerprint_); |
| 900 microdump_gpu_fingerprint_ = strdup(gpu_fingerprint.c_str()); | 924 microdump_gpu_fingerprint_ = strdup(gpu_fingerprint.c_str()); |
| 901 ANNOTATE_LEAKING_OBJECT_PTR(microdump_gpu_fingerprint_); | 925 ANNOTATE_LEAKING_OBJECT_PTR(microdump_gpu_fingerprint_); |
| 902 | 926 |
| 927 UpdateExceptionHandlers(); |
| 928 } |
| 929 |
| 930 void MicrodumpInfo::SetSkipDumpIfPrincipalMappingNotReferenced( |
| 931 uintptr_t address_within_principal_mapping) { |
| 932 DCHECK(thread_checker_.CalledOnValidThread()); |
| 933 skip_dump_if_principal_mapping_not_referenced_ = true; |
| 934 address_within_principal_mapping_ = address_within_principal_mapping; |
| 935 |
| 936 UpdateExceptionHandlers(); |
| 937 } |
| 938 |
| 939 void MicrodumpInfo::SetShouldSanitizeDumps(bool should_sanitize_dumps) { |
| 940 DCHECK(thread_checker_.CalledOnValidThread()); |
| 941 should_sanitize_dumps_ = should_sanitize_dumps; |
| 942 |
| 943 UpdateExceptionHandlers(); |
| 944 } |
| 945 |
| 946 void MicrodumpInfo::UpdateMinidumpDescriptor( |
| 947 MinidumpDescriptor* minidump_descriptor) { |
| 948 google_breakpad::MicrodumpExtraInfo* microdump_extra_info = |
| 949 minidump_descriptor->microdump_extra_info(); |
| 950 |
| 951 minidump_descriptor->set_skip_dump_if_principal_mapping_not_referenced( |
| 952 skip_dump_if_principal_mapping_not_referenced_); |
| 953 minidump_descriptor->set_address_within_principal_mapping( |
| 954 address_within_principal_mapping_); |
| 955 minidump_descriptor->set_sanitize_stacks(should_sanitize_dumps_); |
| 956 |
| 957 microdump_extra_info->gpu_fingerprint = microdump_gpu_fingerprint_; |
| 958 microdump_extra_info->product_info = microdump_product_info_; |
| 959 microdump_extra_info->process_type = microdump_process_type_; |
| 960 microdump_extra_info->build_fingerprint = microdump_build_fingerprint_; |
| 961 } |
| 962 |
| 963 void MicrodumpInfo::UpdateExceptionHandlers() { |
| 964 if (g_breakpad) { |
| 965 MinidumpDescriptor descriptor(g_breakpad->minidump_descriptor()); |
| 966 UpdateMinidumpDescriptor(&descriptor); |
| 967 g_breakpad->set_minidump_descriptor(descriptor); |
| 968 } |
| 903 if (g_microdump) { | 969 if (g_microdump) { |
| 904 MinidumpDescriptor minidump_descriptor(g_microdump->minidump_descriptor()); | 970 MinidumpDescriptor descriptor(g_microdump->minidump_descriptor()); |
| 905 minidump_descriptor.microdump_extra_info()->gpu_fingerprint = | 971 UpdateMinidumpDescriptor(&descriptor); |
| 906 microdump_gpu_fingerprint_; | 972 g_microdump->set_minidump_descriptor(descriptor); |
| 907 g_microdump->set_minidump_descriptor(minidump_descriptor); | |
| 908 } | 973 } |
| 909 } | 974 } |
| 910 | 975 |
| 911 void MicrodumpInfo::Initialize(const std::string& process_type, | 976 void MicrodumpInfo::Initialize(const std::string& process_type, |
| 912 const char* product_name, | 977 const char* product_name, |
| 913 const char* product_version, | 978 const char* product_version, |
| 914 const char* android_build_fp) { | 979 const char* android_build_fp) { |
| 915 DCHECK(thread_checker_.CalledOnValidThread()); | 980 DCHECK(thread_checker_.CalledOnValidThread()); |
| 916 DCHECK(!g_microdump); | 981 DCHECK(!g_microdump); |
| 917 // |process_type| for webview's browser process is kBrowserProcessType or | 982 // |process_type| for webview's browser process is kBrowserProcessType or |
| 918 // kWebViewSingleProcessType. |process_type| for chrome's browser process is | 983 // kWebViewSingleProcessType. |process_type| for chrome's browser process is |
| 919 // an empty string. | 984 // an empty string. |
| 920 bool is_browser_process = process_type.empty() || | 985 bool is_browser_process = process_type.empty() || |
| 921 process_type == kWebViewSingleProcessType || | 986 process_type == kWebViewSingleProcessType || |
| 922 process_type == kBrowserProcessType; | 987 process_type == kBrowserProcessType; |
| 923 | 988 |
| 924 MinidumpDescriptor descriptor(MinidumpDescriptor::kMicrodumpOnConsole); | 989 MinidumpDescriptor descriptor(MinidumpDescriptor::kMicrodumpOnConsole); |
| 925 | 990 |
| 926 if (product_name && product_version) { | 991 if (product_name && product_version) { |
| 927 microdump_product_info_ = | 992 microdump_product_info_ = |
| 928 strdup((product_name + std::string(":") + product_version).c_str()); | 993 strdup((product_name + std::string(":") + product_version).c_str()); |
| 929 ANNOTATE_LEAKING_OBJECT_PTR(microdump_product_info_); | 994 ANNOTATE_LEAKING_OBJECT_PTR(microdump_product_info_); |
| 930 descriptor.microdump_extra_info()->product_info = microdump_product_info_; | |
| 931 } | 995 } |
| 932 | 996 |
| 933 microdump_process_type_ = | 997 microdump_process_type_ = |
| 934 strdup(process_type.empty() ? kBrowserProcessType : process_type.c_str()); | 998 strdup(process_type.empty() ? kBrowserProcessType : process_type.c_str()); |
| 935 ANNOTATE_LEAKING_OBJECT_PTR(microdump_process_type_); | 999 ANNOTATE_LEAKING_OBJECT_PTR(microdump_process_type_); |
| 936 descriptor.microdump_extra_info()->process_type = microdump_process_type_; | |
| 937 | 1000 |
| 938 if (android_build_fp) { | 1001 if (android_build_fp) { |
| 939 microdump_build_fingerprint_ = strdup(android_build_fp); | 1002 microdump_build_fingerprint_ = strdup(android_build_fp); |
| 940 ANNOTATE_LEAKING_OBJECT_PTR(microdump_build_fingerprint_); | 1003 ANNOTATE_LEAKING_OBJECT_PTR(microdump_build_fingerprint_); |
| 941 descriptor.microdump_extra_info()->build_fingerprint = | |
| 942 microdump_build_fingerprint_; | |
| 943 } | 1004 } |
| 944 | 1005 |
| 945 if (microdump_gpu_fingerprint_) { | 1006 UpdateMinidumpDescriptor(&descriptor); |
| 946 descriptor.microdump_extra_info()->gpu_fingerprint = | |
| 947 microdump_gpu_fingerprint_; | |
| 948 } | |
| 949 | 1007 |
| 950 g_microdump = | 1008 g_microdump = |
| 951 new ExceptionHandler(descriptor, ShouldGenerateDump, MicrodumpCrashDone, | 1009 new ExceptionHandler(descriptor, ShouldGenerateDump, MicrodumpCrashDone, |
| 952 reinterpret_cast<void*>(is_browser_process), | 1010 reinterpret_cast<void*>(is_browser_process), |
| 953 true, // Install handlers. | 1011 true, // Install handlers. |
| 954 -1); // Server file descriptor. -1 for in-process. | 1012 -1); // Server file descriptor. -1 for in-process. |
| 955 | 1013 |
| 956 if (process_type != kWebViewSingleProcessType && | 1014 if (process_type != kWebViewSingleProcessType && |
| 957 process_type != kBrowserProcessType && | 1015 process_type != kBrowserProcessType && |
| 958 !process_type.empty()) { | 1016 !process_type.empty()) { |
| (...skipping 1037 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1996 minidump_descriptor.set_size_limit(-1); | 2054 minidump_descriptor.set_size_limit(-1); |
| 1997 ExceptionHandler(minidump_descriptor, nullptr, MinidumpGenerated, nullptr, | 2055 ExceptionHandler(minidump_descriptor, nullptr, MinidumpGenerated, nullptr, |
| 1998 false, -1) | 2056 false, -1) |
| 1999 .WriteMinidump(); | 2057 .WriteMinidump(); |
| 2000 } | 2058 } |
| 2001 } | 2059 } |
| 2002 | 2060 |
| 2003 void SuppressDumpGeneration() { | 2061 void SuppressDumpGeneration() { |
| 2004 g_dumps_suppressed = G_DUMPS_SUPPRESSED_MAGIC; | 2062 g_dumps_suppressed = G_DUMPS_SUPPRESSED_MAGIC; |
| 2005 } | 2063 } |
| 2064 |
| 2065 void SetSkipDumpIfPrincipalMappingNotReferenced( |
| 2066 uintptr_t address_within_principal_mapping) { |
| 2067 g_microdump_info.Get().SetSkipDumpIfPrincipalMappingNotReferenced( |
| 2068 address_within_principal_mapping); |
| 2069 } |
| 2070 |
| 2071 void SetShouldSanitizeDumps(bool should_sanitize_dumps) { |
| 2072 g_microdump_info.Get().SetShouldSanitizeDumps(should_sanitize_dumps); |
| 2073 } |
| 2006 #endif // OS_ANDROID | 2074 #endif // OS_ANDROID |
| 2007 | 2075 |
| 2008 bool IsCrashReporterEnabled() { | 2076 bool IsCrashReporterEnabled() { |
| 2009 return g_is_crash_reporter_enabled; | 2077 return g_is_crash_reporter_enabled; |
| 2010 } | 2078 } |
| 2011 | 2079 |
| 2012 } // namespace breakpad | 2080 } // namespace breakpad |
| OLD | NEW |