blob: b69492a0c475b69e31dd4acf88cb34c8fe7812c2 [file] [log] [blame]
Steve Fung6c34c252015-08-20 00:27:30 -07001/*
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 */
Chris Sosae4a86032010-06-16 17:08:34 -070016
Ken Mixtera3249322011-03-03 08:47:38 -080017#include <fcntl.h> // for open
18
Chris Sosae4a86032010-06-16 17:08:34 -070019#include <string>
Simon Quef70060c2012-04-09 19:07:07 -070020#include <vector>
Chris Sosae4a86032010-06-16 17:08:34 -070021
Ben Chanab6cc902014-09-05 08:21:06 -070022#include <base/files/file_util.h>
Steve Fung12e61ca2015-09-15 16:36:33 -070023#include <base/guid.h>
Albert Chaulk426fcc02013-05-02 15:38:31 -070024#include <base/logging.h>
Mike Frysingera557c112014-02-05 22:55:39 -050025#include <base/strings/string_split.h>
26#include <base/strings/string_util.h>
27#include <base/strings/stringprintf.h>
Todd Poynor83619352015-12-02 14:38:43 -080028#include <binder/IServiceManager.h>
Alex Vakulenko74dc6242015-10-13 09:23:34 -070029#include <brillo/flag_helper.h>
Alex Vakulenko74dc6242015-10-13 09:23:34 -070030#include <brillo/syslog_logging.h>
Todd Poynor83619352015-12-02 14:38:43 -080031#include <metrics/metrics_collector_service_client.h>
Ben Chan7e776902014-06-18 13:19:51 -070032#include <metrics/metrics_library.h>
Todd Poynor83619352015-12-02 14:38:43 -080033#include <utils/String16.h>
34
Ben Chan7e776902014-06-18 13:19:51 -070035
Steve Fung129bea52015-07-23 13:11:15 -070036#include "kernel_collector.h"
37#include "kernel_warning_collector.h"
Steve Fung129bea52015-07-23 13:11:15 -070038#include "unclean_shutdown_collector.h"
39#include "user_collector.h"
Chris Sosae4a86032010-06-16 17:08:34 -070040
Steve Fungc490e0f2016-01-04 14:26:15 -080041#if !defined(__ANDROID__)
42#include "udev_collector.h"
43#endif
44
Chris Sosae4a86032010-06-16 17:08:34 -070045static const char kCrashCounterHistogram[] = "Logging.CrashCounter";
Chris Masoned3ac7962012-02-24 14:38:57 -080046static const char kKernelCrashDetected[] = "/var/run/kernel-crash-detected";
47static const char kUncleanShutdownDetected[] =
48 "/var/run/unclean-shutdown-detected";
Steve Fung12e61ca2015-09-15 16:36:33 -070049static const char kGUIDFileName[] = "/data/misc/crash_reporter/guid";
Ken Mixter777484c2010-07-23 16:22:44 -070050
Chris Sosae4a86032010-06-16 17:08:34 -070051// Enumeration of kinds of crashes to be used in the CrashCounter histogram.
52enum CrashKinds {
Ken Mixter03403162010-08-18 15:23:16 -070053 kCrashKindUncleanShutdown = 1,
54 kCrashKindUser = 2,
55 kCrashKindKernel = 3,
Simon Queacc79382012-05-04 18:10:09 -070056 kCrashKindUdev = 4,
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -070057 kCrashKindKernelWarning = 5,
Ken Mixter777484c2010-07-23 16:22:44 -070058 kCrashKindMax
Chris Sosae4a86032010-06-16 17:08:34 -070059};
60
61static MetricsLibrary s_metrics_lib;
Chris Sosae4a86032010-06-16 17:08:34 -070062
Todd Poynor83619352015-12-02 14:38:43 -080063using android::brillo::metrics::IMetricsCollectorService;
Simon Que9f90aca2013-02-19 17:19:52 -080064using base::FilePath;
Mike Frysingera557c112014-02-05 22:55:39 -050065using base::StringPrintf;
Simon Que9f90aca2013-02-19 17:19:52 -080066
Ken Mixter03403162010-08-18 15:23:16 -070067static bool IsFeedbackAllowed() {
Ken Mixteree849c52010-09-30 15:30:10 -070068 return s_metrics_lib.AreMetricsEnabled();
Chris Sosae4a86032010-06-16 17:08:34 -070069}
70
Ken Mixter03403162010-08-18 15:23:16 -070071static bool TouchFile(const FilePath &file_path) {
Ben Chanf30c6412014-05-22 23:09:01 -070072 return base::WriteFile(file_path, "", 0) == 0;
Chris Sosae4a86032010-06-16 17:08:34 -070073}
74
Simon Que6f035492012-06-27 17:28:14 -070075static void SendCrashMetrics(CrashKinds type, const char* name) {
Ken Mixter1d3c3042011-01-22 06:16:40 -080076 // TODO(kmixter): We can remove this histogram as part of
77 // crosbug.com/11163.
Simon Que6f035492012-06-27 17:28:14 -070078 s_metrics_lib.SendEnumToUMA(kCrashCounterHistogram, type, kCrashKindMax);
79 s_metrics_lib.SendCrashToUMA(name);
80}
81
82static void CountKernelCrash() {
83 SendCrashMetrics(kCrashKindKernel, "kernel");
Chris Sosae4a86032010-06-16 17:08:34 -070084}
85
Simon Queacc79382012-05-04 18:10:09 -070086static void CountUdevCrash() {
87 SendCrashMetrics(kCrashKindUdev, "udevcrash");
88}
89
Ken Mixter03403162010-08-18 15:23:16 -070090static void CountUncleanShutdown() {
Simon Que6f035492012-06-27 17:28:14 -070091 SendCrashMetrics(kCrashKindUncleanShutdown, "uncleanshutdown");
Chris Sosae4a86032010-06-16 17:08:34 -070092}
93
94static void CountUserCrash() {
Simon Que6f035492012-06-27 17:28:14 -070095 SendCrashMetrics(kCrashKindUser, "user");
Todd Poynor83619352015-12-02 14:38:43 -080096 // Tell the metrics collector about the user crash, in order to log active
97 // use time between crashes.
98 MetricsCollectorServiceClient metrics_collector_service;
Ken Mixter03403162010-08-18 15:23:16 -070099
Todd Poynor83619352015-12-02 14:38:43 -0800100 if (metrics_collector_service.Init())
101 metrics_collector_service.notifyUserCrash();
102 else
103 LOG(ERROR) << "Failed to send user crash notification to metrics_collector";
Chris Sosae4a86032010-06-16 17:08:34 -0700104}
105
Albert Chaulk426fcc02013-05-02 15:38:31 -0700106
Ken Mixter03403162010-08-18 15:23:16 -0700107static int Initialize(KernelCollector *kernel_collector,
108 UserCollector *user_collector,
Steve Fungd6169a22014-08-11 15:52:23 -0700109 UncleanShutdownCollector *unclean_shutdown_collector,
110 const bool unclean_check,
111 const bool clean_shutdown) {
112 CHECK(!clean_shutdown) << "Incompatible options";
Chris Sosae4a86032010-06-16 17:08:34 -0700113
Steve Fung12e61ca2015-09-15 16:36:33 -0700114 // Try to read the GUID from kGUIDFileName. If the file doesn't exist, is
115 // blank, or the read fails, generate a new GUID and write it to the file.
116 std::string guid;
117 base::FilePath filepath(kGUIDFileName);
118 if (!base::ReadFileToString(filepath, &guid) || guid.empty()) {
119 guid = base::GenerateGUID();
120 // If we can't read or write the file, log an error. However it is not
121 // a fatal error, as the crash server will assign a random GUID based
122 // on a hash of the IP address if one is not provided in the report.
123 if (base::WriteFile(filepath, guid.c_str(), guid.size()) <= 0) {
124 LOG(ERROR) << "Could not write guid " << guid << " to file "
125 << filepath.value();
126 }
127 }
128
Ken Mixter03403162010-08-18 15:23:16 -0700129 bool was_kernel_crash = false;
130 bool was_unclean_shutdown = false;
Hugh Dickinsf174fc02010-09-08 20:55:26 -0700131 kernel_collector->Enable();
Ben Chan3c6b82c2014-07-23 14:52:14 -0700132 if (kernel_collector->is_enabled()) {
Ken Mixter03403162010-08-18 15:23:16 -0700133 was_kernel_crash = kernel_collector->Collect();
134 }
135
Steve Fungd6169a22014-08-11 15:52:23 -0700136 if (unclean_check) {
Ken Mixter03403162010-08-18 15:23:16 -0700137 was_unclean_shutdown = unclean_shutdown_collector->Collect();
138 }
139
140 // Touch a file to notify the metrics daemon that a kernel
141 // crash has been detected so that it can log the time since
142 // the last kernel crash.
143 if (IsFeedbackAllowed()) {
144 if (was_kernel_crash) {
Chris Masoned3ac7962012-02-24 14:38:57 -0800145 TouchFile(FilePath(kKernelCrashDetected));
Ken Mixter03403162010-08-18 15:23:16 -0700146 } else if (was_unclean_shutdown) {
147 // We only count an unclean shutdown if it did not come with
148 // an associated kernel crash.
Chris Masoned3ac7962012-02-24 14:38:57 -0800149 TouchFile(FilePath(kUncleanShutdownDetected));
Chris Sosae4a86032010-06-16 17:08:34 -0700150 }
Chris Sosae4a86032010-06-16 17:08:34 -0700151 }
152
Ken Mixter03403162010-08-18 15:23:16 -0700153 // Must enable the unclean shutdown collector *after* collecting.
Ken Mixter03403162010-08-18 15:23:16 -0700154 unclean_shutdown_collector->Enable();
155 user_collector->Enable();
Chris Sosae4a86032010-06-16 17:08:34 -0700156
Ken Mixter03403162010-08-18 15:23:16 -0700157 return 0;
158}
159
Steve Fungd6169a22014-08-11 15:52:23 -0700160static int HandleUserCrash(UserCollector *user_collector,
161 const std::string& user, const bool crash_test) {
Chris Sosae4a86032010-06-16 17:08:34 -0700162 // Handle a specific user space crash.
Steve Fungd6169a22014-08-11 15:52:23 -0700163 CHECK(!user.empty()) << "--user= must be set";
Chris Sosae4a86032010-06-16 17:08:34 -0700164
165 // Make it possible to test what happens when we crash while
166 // handling a crash.
Steve Fungd6169a22014-08-11 15:52:23 -0700167 if (crash_test) {
Mike Frysinger9a7ce9f2013-01-19 11:03:37 -0500168 *(volatile char *)0 = 0;
Chris Sosae4a86032010-06-16 17:08:34 -0700169 return 0;
170 }
171
Ken Mixterd49d3622011-02-09 18:23:00 -0800172 // Accumulate logs to help in diagnosing failures during user collection.
Alex Vakulenko74dc6242015-10-13 09:23:34 -0700173 brillo::LogToString(true);
Ken Mixter777484c2010-07-23 16:22:44 -0700174 // Handle the crash, get the name of the process from procfs.
Steve Fungd6169a22014-08-11 15:52:23 -0700175 bool handled = user_collector->HandleCrash(user, nullptr);
Alex Vakulenko74dc6242015-10-13 09:23:34 -0700176 brillo::LogToString(false);
Ken Mixterd49d3622011-02-09 18:23:00 -0800177 if (!handled)
Ken Mixter777484c2010-07-23 16:22:44 -0700178 return 1;
Chris Sosae4a86032010-06-16 17:08:34 -0700179 return 0;
180}
Ken Mixter03403162010-08-18 15:23:16 -0700181
Steve Fungc490e0f2016-01-04 14:26:15 -0800182#if !defined(__ANDROID__)
Steve Fungd6169a22014-08-11 15:52:23 -0700183static int HandleUdevCrash(UdevCollector *udev_collector,
184 const std::string& udev_event) {
Simon Quef70060c2012-04-09 19:07:07 -0700185 // Handle a crash indicated by a udev event.
Steve Fungd6169a22014-08-11 15:52:23 -0700186 CHECK(!udev_event.empty()) << "--udev= must be set";
Simon Quef70060c2012-04-09 19:07:07 -0700187
188 // Accumulate logs to help in diagnosing failures during user collection.
Alex Vakulenko74dc6242015-10-13 09:23:34 -0700189 brillo::LogToString(true);
Steve Fungd6169a22014-08-11 15:52:23 -0700190 bool handled = udev_collector->HandleCrash(udev_event);
Alex Vakulenko74dc6242015-10-13 09:23:34 -0700191 brillo::LogToString(false);
Simon Quef70060c2012-04-09 19:07:07 -0700192 if (!handled)
193 return 1;
194 return 0;
195}
Steve Fungc490e0f2016-01-04 14:26:15 -0800196#endif
Simon Quef70060c2012-04-09 19:07:07 -0700197
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -0700198static int HandleKernelWarning(KernelWarningCollector
199 *kernel_warning_collector) {
200 // Accumulate logs to help in diagnosing failures during collection.
Alex Vakulenko74dc6242015-10-13 09:23:34 -0700201 brillo::LogToString(true);
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -0700202 bool handled = kernel_warning_collector->Collect();
Alex Vakulenko74dc6242015-10-13 09:23:34 -0700203 brillo::LogToString(false);
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -0700204 if (!handled)
205 return 1;
206 return 0;
207}
208
Ken Mixterafcf8082010-10-26 14:45:01 -0700209// Interactive/diagnostics mode for generating kernel crash signatures.
Steve Fungd6169a22014-08-11 15:52:23 -0700210static int GenerateKernelSignature(KernelCollector *kernel_collector,
211 const std::string& kernel_signature_file) {
Ken Mixterafcf8082010-10-26 14:45:01 -0700212 std::string kcrash_contents;
213 std::string signature;
Steve Fungd6169a22014-08-11 15:52:23 -0700214 if (!base::ReadFileToString(FilePath(kernel_signature_file),
Mike Frysingera557c112014-02-05 22:55:39 -0500215 &kcrash_contents)) {
Ken Mixterafcf8082010-10-26 14:45:01 -0700216 fprintf(stderr, "Could not read file.\n");
217 return 1;
218 }
219 if (!kernel_collector->ComputeKernelStackSignature(
220 kcrash_contents,
221 &signature,
222 true)) {
223 fprintf(stderr, "Signature could not be generated.\n");
224 return 1;
225 }
226 printf("Kernel crash signature is \"%s\".\n", signature.c_str());
227 return 0;
228}
Ken Mixter03403162010-08-18 15:23:16 -0700229
Ken Mixtera3249322011-03-03 08:47:38 -0800230// Ensure stdout, stdin, and stderr are open file descriptors. If
231// they are not, any code which writes to stderr/stdout may write out
232// to files opened during execution. In particular, when
233// crash_reporter is run by the kernel coredump pipe handler (via
234// kthread_create/kernel_execve), it will not have file table entries
235// 1 and 2 (stdout and stderr) populated. We populate them here.
236static void OpenStandardFileDescriptors() {
237 int new_fd = -1;
238 // We open /dev/null to fill in any of the standard [0, 2] file
239 // descriptors. We leave these open for the duration of the
240 // process. This works because open returns the lowest numbered
241 // invalid fd.
242 do {
243 new_fd = open("/dev/null", 0);
Ben Chan7e776902014-06-18 13:19:51 -0700244 CHECK_GE(new_fd, 0) << "Unable to open /dev/null";
Ken Mixtera3249322011-03-03 08:47:38 -0800245 } while (new_fd >= 0 && new_fd <= 2);
246 close(new_fd);
247}
248
Ken Mixter03403162010-08-18 15:23:16 -0700249int main(int argc, char *argv[]) {
Steve Fungd6169a22014-08-11 15:52:23 -0700250 DEFINE_bool(init, false, "Initialize crash logging");
251 DEFINE_bool(clean_shutdown, false, "Signal clean shutdown");
252 DEFINE_string(generate_kernel_signature, "",
253 "Generate signature from given kcrash file");
254 DEFINE_bool(crash_test, false, "Crash test");
255 DEFINE_string(user, "", "User crash info (pid:signal:exec_name)");
256 DEFINE_bool(unclean_check, true, "Check for unclean shutdown");
Steve Fungc490e0f2016-01-04 14:26:15 -0800257
258#if !defined(__ANDROID__)
Steve Fungd6169a22014-08-11 15:52:23 -0700259 DEFINE_string(udev, "", "Udev event description (type:device:subsystem)");
Steve Fungc490e0f2016-01-04 14:26:15 -0800260#endif
261
Steve Fungd6169a22014-08-11 15:52:23 -0700262 DEFINE_bool(kernel_warning, false, "Report collected kernel warning");
Steve Fungd6169a22014-08-11 15:52:23 -0700263 DEFINE_string(pid, "", "PID of crashing process");
264 DEFINE_string(uid, "", "UID of crashing process");
265 DEFINE_string(exe, "", "Executable name of crashing process");
266 DEFINE_bool(core2md_failure, false, "Core2md failure test");
267 DEFINE_bool(directory_failure, false, "Spool directory failure test");
268 DEFINE_string(filter_in, "",
269 "Ignore all crashes but this for testing");
270
Ken Mixtera3249322011-03-03 08:47:38 -0800271 OpenStandardFileDescriptors();
Mike Frysingera557c112014-02-05 22:55:39 -0500272 FilePath my_path = base::MakeAbsoluteFilePath(FilePath(argv[0]));
Ken Mixter03403162010-08-18 15:23:16 -0700273 s_metrics_lib.Init();
Alex Vakulenko74dc6242015-10-13 09:23:34 -0700274 brillo::FlagHelper::Init(argc, argv, "Chromium OS Crash Reporter");
275 brillo::OpenLog(my_path.BaseName().value().c_str(), true);
276 brillo::InitLog(brillo::kLogToSyslog);
Mike Frysingerf19b5182013-05-17 19:36:47 -0400277
Ken Mixter03403162010-08-18 15:23:16 -0700278 KernelCollector kernel_collector;
Lei Zhang9b1f3002014-04-24 02:10:57 -0700279 kernel_collector.Initialize(CountKernelCrash, IsFeedbackAllowed);
Ken Mixter03403162010-08-18 15:23:16 -0700280 UserCollector user_collector;
281 user_collector.Initialize(CountUserCrash,
282 my_path.value(),
283 IsFeedbackAllowed,
Steve Fungd6169a22014-08-11 15:52:23 -0700284 true, // generate_diagnostics
285 FLAGS_core2md_failure,
286 FLAGS_directory_failure,
287 FLAGS_filter_in);
Ken Mixter03403162010-08-18 15:23:16 -0700288 UncleanShutdownCollector unclean_shutdown_collector;
289 unclean_shutdown_collector.Initialize(CountUncleanShutdown,
Ken Mixtera3249322011-03-03 08:47:38 -0800290 IsFeedbackAllowed);
Steve Fungc490e0f2016-01-04 14:26:15 -0800291
292#if !defined(__ANDROID__)
Simon Queacc79382012-05-04 18:10:09 -0700293 UdevCollector udev_collector;
294 udev_collector.Initialize(CountUdevCrash, IsFeedbackAllowed);
Steve Fungc490e0f2016-01-04 14:26:15 -0800295#endif
Ken Mixter03403162010-08-18 15:23:16 -0700296
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -0700297 KernelWarningCollector kernel_warning_collector;
Luigi Semenzato20980d72013-05-28 14:29:43 -0700298 kernel_warning_collector.Initialize(CountUdevCrash, IsFeedbackAllowed);
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -0700299
Ken Mixter03403162010-08-18 15:23:16 -0700300 if (FLAGS_init) {
301 return Initialize(&kernel_collector,
302 &user_collector,
Steve Fungd6169a22014-08-11 15:52:23 -0700303 &unclean_shutdown_collector,
304 FLAGS_unclean_check,
305 FLAGS_clean_shutdown);
Ken Mixter03403162010-08-18 15:23:16 -0700306 }
307
308 if (FLAGS_clean_shutdown) {
309 unclean_shutdown_collector.Disable();
310 user_collector.Disable();
311 return 0;
312 }
313
Ken Mixterafcf8082010-10-26 14:45:01 -0700314 if (!FLAGS_generate_kernel_signature.empty()) {
Steve Fungd6169a22014-08-11 15:52:23 -0700315 return GenerateKernelSignature(&kernel_collector,
316 FLAGS_generate_kernel_signature);
Ken Mixterafcf8082010-10-26 14:45:01 -0700317 }
318
Steve Fungc490e0f2016-01-04 14:26:15 -0800319#if !defined(__ANDROID__)
Simon Quef70060c2012-04-09 19:07:07 -0700320 if (!FLAGS_udev.empty()) {
Steve Fungd6169a22014-08-11 15:52:23 -0700321 return HandleUdevCrash(&udev_collector, FLAGS_udev);
Simon Quef70060c2012-04-09 19:07:07 -0700322 }
Steve Fungc490e0f2016-01-04 14:26:15 -0800323#endif
Simon Quef70060c2012-04-09 19:07:07 -0700324
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -0700325 if (FLAGS_kernel_warning) {
326 return HandleKernelWarning(&kernel_warning_collector);
327 }
328
Steve Fungd6169a22014-08-11 15:52:23 -0700329 return HandleUserCrash(&user_collector, FLAGS_user, FLAGS_crash_test);
Ken Mixter03403162010-08-18 15:23:16 -0700330}