1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <fcntl.h> // for open 18 19 #include <string> 20 #include <vector> 21 22 #include <base/files/file_util.h> 23 #include <base/guid.h> 24 #include <base/logging.h> 25 #include <base/strings/string_split.h> 26 #include <base/strings/string_util.h> 27 #include <base/strings/stringprintf.h> 28 #include <binder/IServiceManager.h> 29 #include <brillo/flag_helper.h> 30 #include <brillo/syslog_logging.h> 31 #include <metrics/metrics_collector_service_client.h> 32 #include <metrics/metrics_library.h> 33 #include <utils/String16.h> 34 35 36 #include "kernel_collector.h" 37 #include "kernel_warning_collector.h" 38 #include "unclean_shutdown_collector.h" 39 #include "user_collector.h" 40 41 #if !defined(__ANDROID__) 42 #include "udev_collector.h" 43 #endif 44 45 static const char kCrashCounterHistogram[] = "Logging.CrashCounter"; 46 static const char kKernelCrashDetected[] = 47 "/data/misc/crash_reporter/run/kernel-crash-detected"; 48 static const char kUncleanShutdownDetected[] = 49 "/var/run/unclean-shutdown-detected"; 50 static const char kGUIDFileName[] = "/data/misc/crash_reporter/guid"; 51 52 // Enumeration of kinds of crashes to be used in the CrashCounter histogram. 53 enum CrashKinds { 54 kCrashKindUncleanShutdown = 1, 55 kCrashKindUser = 2, 56 kCrashKindKernel = 3, 57 kCrashKindUdev = 4, 58 kCrashKindKernelWarning = 5, 59 kCrashKindMax 60 }; 61 62 static MetricsLibrary s_metrics_lib; 63 64 using android::brillo::metrics::IMetricsCollectorService; 65 using base::FilePath; 66 using base::StringPrintf; 67 68 static bool IsFeedbackAllowed() { 69 return s_metrics_lib.AreMetricsEnabled(); 70 } 71 72 static bool TouchFile(const FilePath &file_path) { 73 return base::WriteFile(file_path, "", 0) == 0; 74 } 75 76 static void SendCrashMetrics(CrashKinds type, const char* name) { 77 // TODO(kmixter): We can remove this histogram as part of 78 // crosbug.com/11163. 79 s_metrics_lib.SendEnumToUMA(kCrashCounterHistogram, type, kCrashKindMax); 80 s_metrics_lib.SendCrashToUMA(name); 81 } 82 83 static void CountKernelCrash() { 84 SendCrashMetrics(kCrashKindKernel, "kernel"); 85 } 86 87 static void CountUdevCrash() { 88 SendCrashMetrics(kCrashKindUdev, "udevcrash"); 89 } 90 91 static void CountUncleanShutdown() { 92 SendCrashMetrics(kCrashKindUncleanShutdown, "uncleanshutdown"); 93 } 94 95 static void CountUserCrash() { 96 SendCrashMetrics(kCrashKindUser, "user"); 97 // Tell the metrics collector about the user crash, in order to log active 98 // use time between crashes. 99 MetricsCollectorServiceClient metrics_collector_service; 100 101 if (metrics_collector_service.Init()) 102 metrics_collector_service.notifyUserCrash(); 103 else 104 LOG(ERROR) << "Failed to send user crash notification to metrics_collector"; 105 } 106 107 108 static int Initialize(KernelCollector *kernel_collector, 109 UserCollector *user_collector, 110 UncleanShutdownCollector *unclean_shutdown_collector, 111 const bool unclean_check, 112 const bool clean_shutdown) { 113 CHECK(!clean_shutdown) << "Incompatible options"; 114 115 // Try to read the GUID from kGUIDFileName. If the file doesn't exist, is 116 // blank, or the read fails, generate a new GUID and write it to the file. 117 std::string guid; 118 base::FilePath filepath(kGUIDFileName); 119 if (!base::ReadFileToString(filepath, &guid) || guid.empty()) { 120 guid = base::GenerateGUID(); 121 // If we can't read or write the file, log an error. However it is not 122 // a fatal error, as the crash server will assign a random GUID based 123 // on a hash of the IP address if one is not provided in the report. 124 if (base::WriteFile(filepath, guid.c_str(), guid.size()) <= 0) { 125 LOG(ERROR) << "Could not write guid " << guid << " to file " 126 << filepath.value(); 127 } 128 } 129 130 bool was_kernel_crash = false; 131 bool was_unclean_shutdown = false; 132 kernel_collector->Enable(); 133 if (kernel_collector->is_enabled()) { 134 was_kernel_crash = kernel_collector->Collect(); 135 } 136 137 if (unclean_check) { 138 was_unclean_shutdown = unclean_shutdown_collector->Collect(); 139 } 140 141 // Touch a file to notify the metrics daemon that a kernel 142 // crash has been detected so that it can log the time since 143 // the last kernel crash. 144 if (IsFeedbackAllowed()) { 145 if (was_kernel_crash) { 146 TouchFile(FilePath(kKernelCrashDetected)); 147 } else if (was_unclean_shutdown) { 148 // We only count an unclean shutdown if it did not come with 149 // an associated kernel crash. 150 TouchFile(FilePath(kUncleanShutdownDetected)); 151 } 152 } 153 154 // Must enable the unclean shutdown collector *after* collecting. 155 unclean_shutdown_collector->Enable(); 156 user_collector->Enable(); 157 158 return 0; 159 } 160 161 static int HandleUserCrash(UserCollector *user_collector, 162 const std::string& user, const bool crash_test) { 163 // Handle a specific user space crash. 164 CHECK(!user.empty()) << "--user= must be set"; 165 166 // Make it possible to test what happens when we crash while 167 // handling a crash. 168 if (crash_test) { 169 *(volatile char *)0 = 0; 170 return 0; 171 } 172 173 // Accumulate logs to help in diagnosing failures during user collection. 174 brillo::LogToString(true); 175 // Handle the crash, get the name of the process from procfs. 176 bool handled = user_collector->HandleCrash(user, nullptr); 177 brillo::LogToString(false); 178 if (!handled) 179 return 1; 180 return 0; 181 } 182 183 #if !defined(__ANDROID__) 184 static int HandleUdevCrash(UdevCollector *udev_collector, 185 const std::string& udev_event) { 186 // Handle a crash indicated by a udev event. 187 CHECK(!udev_event.empty()) << "--udev= must be set"; 188 189 // Accumulate logs to help in diagnosing failures during user collection. 190 brillo::LogToString(true); 191 bool handled = udev_collector->HandleCrash(udev_event); 192 brillo::LogToString(false); 193 if (!handled) 194 return 1; 195 return 0; 196 } 197 #endif 198 199 static int HandleKernelWarning(KernelWarningCollector 200 *kernel_warning_collector) { 201 // Accumulate logs to help in diagnosing failures during collection. 202 brillo::LogToString(true); 203 bool handled = kernel_warning_collector->Collect(); 204 brillo::LogToString(false); 205 if (!handled) 206 return 1; 207 return 0; 208 } 209 210 // Interactive/diagnostics mode for generating kernel crash signatures. 211 static int GenerateKernelSignature(KernelCollector *kernel_collector, 212 const std::string& kernel_signature_file) { 213 std::string kcrash_contents; 214 std::string signature; 215 if (!base::ReadFileToString(FilePath(kernel_signature_file), 216 &kcrash_contents)) { 217 fprintf(stderr, "Could not read file.\n"); 218 return 1; 219 } 220 if (!kernel_collector->ComputeKernelStackSignature( 221 kcrash_contents, 222 &signature, 223 true)) { 224 fprintf(stderr, "Signature could not be generated.\n"); 225 return 1; 226 } 227 printf("Kernel crash signature is \"%s\".\n", signature.c_str()); 228 return 0; 229 } 230 231 // Ensure stdout, stdin, and stderr are open file descriptors. If 232 // they are not, any code which writes to stderr/stdout may write out 233 // to files opened during execution. In particular, when 234 // crash_reporter is run by the kernel coredump pipe handler (via 235 // kthread_create/kernel_execve), it will not have file table entries 236 // 1 and 2 (stdout and stderr) populated. We populate them here. 237 static void OpenStandardFileDescriptors() { 238 int new_fd = -1; 239 // We open /dev/null to fill in any of the standard [0, 2] file 240 // descriptors. We leave these open for the duration of the 241 // process. This works because open returns the lowest numbered 242 // invalid fd. 243 do { 244 new_fd = open("/dev/null", 0); 245 CHECK_GE(new_fd, 0) << "Unable to open /dev/null"; 246 } while (new_fd >= 0 && new_fd <= 2); 247 close(new_fd); 248 } 249 250 int main(int argc, char *argv[]) { 251 DEFINE_bool(init, false, "Initialize crash logging"); 252 DEFINE_bool(clean_shutdown, false, "Signal clean shutdown"); 253 DEFINE_string(generate_kernel_signature, "", 254 "Generate signature from given kcrash file"); 255 DEFINE_bool(crash_test, false, "Crash test"); 256 DEFINE_string(user, "", "User crash info (pid:signal:exec_name)"); 257 DEFINE_bool(unclean_check, true, "Check for unclean shutdown"); 258 259 #if !defined(__ANDROID__) 260 DEFINE_string(udev, "", "Udev event description (type:device:subsystem)"); 261 #endif 262 263 DEFINE_bool(kernel_warning, false, "Report collected kernel warning"); 264 DEFINE_string(pid, "", "PID of crashing process"); 265 DEFINE_string(uid, "", "UID of crashing process"); 266 DEFINE_string(exe, "", "Executable name of crashing process"); 267 DEFINE_bool(core2md_failure, false, "Core2md failure test"); 268 DEFINE_bool(directory_failure, false, "Spool directory failure test"); 269 DEFINE_string(filter_in, "", 270 "Ignore all crashes but this for testing"); 271 272 OpenStandardFileDescriptors(); 273 FilePath my_path = base::MakeAbsoluteFilePath(FilePath(argv[0])); 274 s_metrics_lib.Init(); 275 brillo::FlagHelper::Init(argc, argv, "Chromium OS Crash Reporter"); 276 brillo::OpenLog(my_path.BaseName().value().c_str(), true); 277 brillo::InitLog(brillo::kLogToSyslog); 278 279 KernelCollector kernel_collector; 280 kernel_collector.Initialize(CountKernelCrash, IsFeedbackAllowed); 281 UserCollector user_collector; 282 user_collector.Initialize(CountUserCrash, 283 my_path.value(), 284 IsFeedbackAllowed, 285 true, // generate_diagnostics 286 FLAGS_core2md_failure, 287 FLAGS_directory_failure, 288 FLAGS_filter_in); 289 UncleanShutdownCollector unclean_shutdown_collector; 290 unclean_shutdown_collector.Initialize(CountUncleanShutdown, 291 IsFeedbackAllowed); 292 293 #if !defined(__ANDROID__) 294 UdevCollector udev_collector; 295 udev_collector.Initialize(CountUdevCrash, IsFeedbackAllowed); 296 #endif 297 298 KernelWarningCollector kernel_warning_collector; 299 kernel_warning_collector.Initialize(CountUdevCrash, IsFeedbackAllowed); 300 301 if (FLAGS_init) { 302 return Initialize(&kernel_collector, 303 &user_collector, 304 &unclean_shutdown_collector, 305 FLAGS_unclean_check, 306 FLAGS_clean_shutdown); 307 } 308 309 if (FLAGS_clean_shutdown) { 310 unclean_shutdown_collector.Disable(); 311 user_collector.Disable(); 312 return 0; 313 } 314 315 if (!FLAGS_generate_kernel_signature.empty()) { 316 return GenerateKernelSignature(&kernel_collector, 317 FLAGS_generate_kernel_signature); 318 } 319 320 #if !defined(__ANDROID__) 321 if (!FLAGS_udev.empty()) { 322 return HandleUdevCrash(&udev_collector, FLAGS_udev); 323 } 324 #endif 325 326 if (FLAGS_kernel_warning) { 327 return HandleKernelWarning(&kernel_warning_collector); 328 } 329 330 return HandleUserCrash(&user_collector, FLAGS_user, FLAGS_crash_test); 331 } 332