16c34c2576eb241f134431b2cc847a6c7d70ef012Steve Fung/*
26c34c2576eb241f134431b2cc847a6c7d70ef012Steve Fung * Copyright (C) 2012 The Android Open Source Project
36c34c2576eb241f134431b2cc847a6c7d70ef012Steve Fung *
46c34c2576eb241f134431b2cc847a6c7d70ef012Steve Fung * Licensed under the Apache License, Version 2.0 (the "License");
56c34c2576eb241f134431b2cc847a6c7d70ef012Steve Fung * you may not use this file except in compliance with the License.
66c34c2576eb241f134431b2cc847a6c7d70ef012Steve Fung * You may obtain a copy of the License at
76c34c2576eb241f134431b2cc847a6c7d70ef012Steve Fung *
86c34c2576eb241f134431b2cc847a6c7d70ef012Steve Fung *      http://www.apache.org/licenses/LICENSE-2.0
96c34c2576eb241f134431b2cc847a6c7d70ef012Steve Fung *
106c34c2576eb241f134431b2cc847a6c7d70ef012Steve Fung * Unless required by applicable law or agreed to in writing, software
116c34c2576eb241f134431b2cc847a6c7d70ef012Steve Fung * distributed under the License is distributed on an "AS IS" BASIS,
126c34c2576eb241f134431b2cc847a6c7d70ef012Steve Fung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136c34c2576eb241f134431b2cc847a6c7d70ef012Steve Fung * See the License for the specific language governing permissions and
146c34c2576eb241f134431b2cc847a6c7d70ef012Steve Fung * limitations under the License.
156c34c2576eb241f134431b2cc847a6c7d70ef012Steve Fung */
16e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa
17a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter#include <fcntl.h>  // for open
18a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter
19e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa#include <string>
20f70060c5e610ed0aa648dcb6aaea5d859834b8baSimon Que#include <vector>
21e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa
22ab6cc90503ca2db976a3cb9c9382a9da85c4b5a2Ben Chan#include <base/files/file_util.h>
2312e61caae7f516aaa1feafdca3c7f999b856a964Steve Fung#include <base/guid.h>
24426fcc0bd579a87102ea50fb570dbf9834fa2962Albert Chaulk#include <base/logging.h>
25a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger#include <base/strings/string_split.h>
26a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger#include <base/strings/string_util.h>
27a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger#include <base/strings/stringprintf.h>
288361935de89a5092cfb54245e55e454981f99f11Todd Poynor#include <binder/IServiceManager.h>
2974dc62460b8cdd5bfeac47bfe8e759fc04b55ef8Alex Vakulenko#include <brillo/flag_helper.h>
3074dc62460b8cdd5bfeac47bfe8e759fc04b55ef8Alex Vakulenko#include <brillo/syslog_logging.h>
318361935de89a5092cfb54245e55e454981f99f11Todd Poynor#include <metrics/metrics_collector_service_client.h>
327e77690375bc8a896a8de318d69d515e67c7aefeBen Chan#include <metrics/metrics_library.h>
338361935de89a5092cfb54245e55e454981f99f11Todd Poynor#include <utils/String16.h>
348361935de89a5092cfb54245e55e454981f99f11Todd Poynor
357e77690375bc8a896a8de318d69d515e67c7aefeBen Chan
36129bea543b7572bfdf09c6a7b3cebbe3b57ce723Steve Fung#include "kernel_collector.h"
37129bea543b7572bfdf09c6a7b3cebbe3b57ce723Steve Fung#include "kernel_warning_collector.h"
38129bea543b7572bfdf09c6a7b3cebbe3b57ce723Steve Fung#include "unclean_shutdown_collector.h"
39129bea543b7572bfdf09c6a7b3cebbe3b57ce723Steve Fung#include "user_collector.h"
40e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa
41c490e0fe987a2cb84787c19be2a516d43010ca2cSteve Fung#if !defined(__ANDROID__)
42c490e0fe987a2cb84787c19be2a516d43010ca2cSteve Fung#include "udev_collector.h"
43c490e0fe987a2cb84787c19be2a516d43010ca2cSteve Fung#endif
44c490e0fe987a2cb84787c19be2a516d43010ca2cSteve Fung
45e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosastatic const char kCrashCounterHistogram[] = "Logging.CrashCounter";
462bedc7455318e35b2a6ac77031b673d59893877dSteve Fungstatic const char kKernelCrashDetected[] =
472bedc7455318e35b2a6ac77031b673d59893877dSteve Fung    "/data/misc/crash_reporter/run/kernel-crash-detected";
48d3ac79663fdba1e4c31a3227def22b8555c5ff6fChris Masonestatic const char kUncleanShutdownDetected[] =
49d3ac79663fdba1e4c31a3227def22b8555c5ff6fChris Masone    "/var/run/unclean-shutdown-detected";
5012e61caae7f516aaa1feafdca3c7f999b856a964Steve Fungstatic const char kGUIDFileName[] = "/data/misc/crash_reporter/guid";
51777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter
52e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa// Enumeration of kinds of crashes to be used in the CrashCounter histogram.
53e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosaenum CrashKinds {
540340316050044e0995b98fea87ed41ea77abb28bKen Mixter  kCrashKindUncleanShutdown = 1,
550340316050044e0995b98fea87ed41ea77abb28bKen Mixter  kCrashKindUser = 2,
560340316050044e0995b98fea87ed41ea77abb28bKen Mixter  kCrashKindKernel = 3,
57acc7938ede0e3c07a2d1809f82b174b51f7ab7c5Simon Que  kCrashKindUdev = 4,
586fdc0b48cb5e262083c06a6b1c7595c01b4b2e74Luigi Semenzato  kCrashKindKernelWarning = 5,
59777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter  kCrashKindMax
60e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa};
61e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa
62e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosastatic MetricsLibrary s_metrics_lib;
63e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa
648361935de89a5092cfb54245e55e454981f99f11Todd Poynorusing android::brillo::metrics::IMetricsCollectorService;
659f90acaa4d420530d7b4ddd37112518df68e373aSimon Queusing base::FilePath;
66a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysingerusing base::StringPrintf;
679f90acaa4d420530d7b4ddd37112518df68e373aSimon Que
680340316050044e0995b98fea87ed41ea77abb28bKen Mixterstatic bool IsFeedbackAllowed() {
69ee849c5ef4c416cb0321483fa10c92f8aada3179Ken Mixter  return s_metrics_lib.AreMetricsEnabled();
70e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa}
71e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa
720340316050044e0995b98fea87ed41ea77abb28bKen Mixterstatic bool TouchFile(const FilePath &file_path) {
73f30c641225e55055641ffe3fd679a96e44f34af6Ben Chan  return base::WriteFile(file_path, "", 0) == 0;
74e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa}
75e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa
766f03549d97555810c8e190af3439b4e7c7bad10fSimon Questatic void SendCrashMetrics(CrashKinds type, const char* name) {
771d3c3040836f7072bd005177291a0c29590b1e77Ken Mixter  // TODO(kmixter): We can remove this histogram as part of
781d3c3040836f7072bd005177291a0c29590b1e77Ken Mixter  // crosbug.com/11163.
796f03549d97555810c8e190af3439b4e7c7bad10fSimon Que  s_metrics_lib.SendEnumToUMA(kCrashCounterHistogram, type, kCrashKindMax);
806f03549d97555810c8e190af3439b4e7c7bad10fSimon Que  s_metrics_lib.SendCrashToUMA(name);
816f03549d97555810c8e190af3439b4e7c7bad10fSimon Que}
826f03549d97555810c8e190af3439b4e7c7bad10fSimon Que
836f03549d97555810c8e190af3439b4e7c7bad10fSimon Questatic void CountKernelCrash() {
846f03549d97555810c8e190af3439b4e7c7bad10fSimon Que  SendCrashMetrics(kCrashKindKernel, "kernel");
85e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa}
86e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa
87acc7938ede0e3c07a2d1809f82b174b51f7ab7c5Simon Questatic void CountUdevCrash() {
88acc7938ede0e3c07a2d1809f82b174b51f7ab7c5Simon Que  SendCrashMetrics(kCrashKindUdev, "udevcrash");
89acc7938ede0e3c07a2d1809f82b174b51f7ab7c5Simon Que}
90acc7938ede0e3c07a2d1809f82b174b51f7ab7c5Simon Que
910340316050044e0995b98fea87ed41ea77abb28bKen Mixterstatic void CountUncleanShutdown() {
926f03549d97555810c8e190af3439b4e7c7bad10fSimon Que  SendCrashMetrics(kCrashKindUncleanShutdown, "uncleanshutdown");
93e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa}
94e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa
95e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosastatic void CountUserCrash() {
966f03549d97555810c8e190af3439b4e7c7bad10fSimon Que  SendCrashMetrics(kCrashKindUser, "user");
978361935de89a5092cfb54245e55e454981f99f11Todd Poynor  // Tell the metrics collector about the user crash, in order to log active
988361935de89a5092cfb54245e55e454981f99f11Todd Poynor  // use time between crashes.
998361935de89a5092cfb54245e55e454981f99f11Todd Poynor  MetricsCollectorServiceClient metrics_collector_service;
1008361935de89a5092cfb54245e55e454981f99f11Todd Poynor
1018361935de89a5092cfb54245e55e454981f99f11Todd Poynor  if (metrics_collector_service.Init())
1028361935de89a5092cfb54245e55e454981f99f11Todd Poynor    metrics_collector_service.notifyUserCrash();
1038361935de89a5092cfb54245e55e454981f99f11Todd Poynor  else
1048361935de89a5092cfb54245e55e454981f99f11Todd Poynor    LOG(ERROR) << "Failed to send user crash notification to metrics_collector";
105e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa}
106e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa
107426fcc0bd579a87102ea50fb570dbf9834fa2962Albert Chaulk
1080340316050044e0995b98fea87ed41ea77abb28bKen Mixterstatic int Initialize(KernelCollector *kernel_collector,
1090340316050044e0995b98fea87ed41ea77abb28bKen Mixter                      UserCollector *user_collector,
110d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung                      UncleanShutdownCollector *unclean_shutdown_collector,
111d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung                      const bool unclean_check,
112d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung                      const bool clean_shutdown) {
113d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  CHECK(!clean_shutdown) << "Incompatible options";
114e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa
11512e61caae7f516aaa1feafdca3c7f999b856a964Steve Fung  // Try to read the GUID from kGUIDFileName.  If the file doesn't exist, is
11612e61caae7f516aaa1feafdca3c7f999b856a964Steve Fung  // blank, or the read fails, generate a new GUID and write it to the file.
11712e61caae7f516aaa1feafdca3c7f999b856a964Steve Fung  std::string guid;
11812e61caae7f516aaa1feafdca3c7f999b856a964Steve Fung  base::FilePath filepath(kGUIDFileName);
11912e61caae7f516aaa1feafdca3c7f999b856a964Steve Fung  if (!base::ReadFileToString(filepath, &guid) || guid.empty()) {
12012e61caae7f516aaa1feafdca3c7f999b856a964Steve Fung    guid = base::GenerateGUID();
12112e61caae7f516aaa1feafdca3c7f999b856a964Steve Fung    // If we can't read or write the file, log an error.  However it is not
12212e61caae7f516aaa1feafdca3c7f999b856a964Steve Fung    // a fatal error, as the crash server will assign a random GUID based
12312e61caae7f516aaa1feafdca3c7f999b856a964Steve Fung    // on a hash of the IP address if one is not provided in the report.
12412e61caae7f516aaa1feafdca3c7f999b856a964Steve Fung    if (base::WriteFile(filepath, guid.c_str(), guid.size()) <= 0) {
12512e61caae7f516aaa1feafdca3c7f999b856a964Steve Fung      LOG(ERROR) << "Could not write guid " << guid << " to file "
12612e61caae7f516aaa1feafdca3c7f999b856a964Steve Fung                 << filepath.value();
12712e61caae7f516aaa1feafdca3c7f999b856a964Steve Fung    }
12812e61caae7f516aaa1feafdca3c7f999b856a964Steve Fung  }
12912e61caae7f516aaa1feafdca3c7f999b856a964Steve Fung
1300340316050044e0995b98fea87ed41ea77abb28bKen Mixter  bool was_kernel_crash = false;
1310340316050044e0995b98fea87ed41ea77abb28bKen Mixter  bool was_unclean_shutdown = false;
132f174fc08dca7201b493be4187c450d925e113689Hugh Dickins  kernel_collector->Enable();
1333c6b82c4c73f9ac39a71809f01af6f3b75339606Ben Chan  if (kernel_collector->is_enabled()) {
1340340316050044e0995b98fea87ed41ea77abb28bKen Mixter    was_kernel_crash = kernel_collector->Collect();
135e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa  }
136e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa
137d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  if (unclean_check) {
1380340316050044e0995b98fea87ed41ea77abb28bKen Mixter    was_unclean_shutdown = unclean_shutdown_collector->Collect();
1390340316050044e0995b98fea87ed41ea77abb28bKen Mixter  }
1400340316050044e0995b98fea87ed41ea77abb28bKen Mixter
1410340316050044e0995b98fea87ed41ea77abb28bKen Mixter  // Touch a file to notify the metrics daemon that a kernel
1420340316050044e0995b98fea87ed41ea77abb28bKen Mixter  // crash has been detected so that it can log the time since
1430340316050044e0995b98fea87ed41ea77abb28bKen Mixter  // the last kernel crash.
1440340316050044e0995b98fea87ed41ea77abb28bKen Mixter  if (IsFeedbackAllowed()) {
1450340316050044e0995b98fea87ed41ea77abb28bKen Mixter    if (was_kernel_crash) {
146d3ac79663fdba1e4c31a3227def22b8555c5ff6fChris Masone      TouchFile(FilePath(kKernelCrashDetected));
1470340316050044e0995b98fea87ed41ea77abb28bKen Mixter    } else if (was_unclean_shutdown) {
1480340316050044e0995b98fea87ed41ea77abb28bKen Mixter      // We only count an unclean shutdown if it did not come with
1490340316050044e0995b98fea87ed41ea77abb28bKen Mixter      // an associated kernel crash.
150d3ac79663fdba1e4c31a3227def22b8555c5ff6fChris Masone      TouchFile(FilePath(kUncleanShutdownDetected));
1510340316050044e0995b98fea87ed41ea77abb28bKen Mixter    }
152e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa  }
153e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa
1540340316050044e0995b98fea87ed41ea77abb28bKen Mixter  // Must enable the unclean shutdown collector *after* collecting.
1550340316050044e0995b98fea87ed41ea77abb28bKen Mixter  unclean_shutdown_collector->Enable();
1560340316050044e0995b98fea87ed41ea77abb28bKen Mixter  user_collector->Enable();
1570340316050044e0995b98fea87ed41ea77abb28bKen Mixter
1580340316050044e0995b98fea87ed41ea77abb28bKen Mixter  return 0;
1590340316050044e0995b98fea87ed41ea77abb28bKen Mixter}
1600340316050044e0995b98fea87ed41ea77abb28bKen Mixter
161d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fungstatic int HandleUserCrash(UserCollector *user_collector,
162d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung                           const std::string& user, const bool crash_test) {
163e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa  // Handle a specific user space crash.
164d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  CHECK(!user.empty()) << "--user= must be set";
165e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa
166e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa  // Make it possible to test what happens when we crash while
167e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa  // handling a crash.
168d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  if (crash_test) {
1699a7ce9fbef026610c86af15c76af2d8b92654412Mike Frysinger    *(volatile char *)0 = 0;
170e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa    return 0;
171e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa  }
172e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa
173d49d362f61c7e702d557e563055b1c541ead5b67Ken Mixter  // Accumulate logs to help in diagnosing failures during user collection.
17474dc62460b8cdd5bfeac47bfe8e759fc04b55ef8Alex Vakulenko  brillo::LogToString(true);
175777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter  // Handle the crash, get the name of the process from procfs.
176d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  bool handled = user_collector->HandleCrash(user, nullptr);
17774dc62460b8cdd5bfeac47bfe8e759fc04b55ef8Alex Vakulenko  brillo::LogToString(false);
178d49d362f61c7e702d557e563055b1c541ead5b67Ken Mixter  if (!handled)
179777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter    return 1;
180e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa  return 0;
181e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa}
1820340316050044e0995b98fea87ed41ea77abb28bKen Mixter
183c490e0fe987a2cb84787c19be2a516d43010ca2cSteve Fung#if !defined(__ANDROID__)
184d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fungstatic int HandleUdevCrash(UdevCollector *udev_collector,
185d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung                           const std::string& udev_event) {
186f70060c5e610ed0aa648dcb6aaea5d859834b8baSimon Que  // Handle a crash indicated by a udev event.
187d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  CHECK(!udev_event.empty()) << "--udev= must be set";
188f70060c5e610ed0aa648dcb6aaea5d859834b8baSimon Que
189f70060c5e610ed0aa648dcb6aaea5d859834b8baSimon Que  // Accumulate logs to help in diagnosing failures during user collection.
19074dc62460b8cdd5bfeac47bfe8e759fc04b55ef8Alex Vakulenko  brillo::LogToString(true);
191d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  bool handled = udev_collector->HandleCrash(udev_event);
19274dc62460b8cdd5bfeac47bfe8e759fc04b55ef8Alex Vakulenko  brillo::LogToString(false);
193f70060c5e610ed0aa648dcb6aaea5d859834b8baSimon Que  if (!handled)
194f70060c5e610ed0aa648dcb6aaea5d859834b8baSimon Que    return 1;
195f70060c5e610ed0aa648dcb6aaea5d859834b8baSimon Que  return 0;
196f70060c5e610ed0aa648dcb6aaea5d859834b8baSimon Que}
197c490e0fe987a2cb84787c19be2a516d43010ca2cSteve Fung#endif
198f70060c5e610ed0aa648dcb6aaea5d859834b8baSimon Que
1996fdc0b48cb5e262083c06a6b1c7595c01b4b2e74Luigi Semenzatostatic int HandleKernelWarning(KernelWarningCollector
2006fdc0b48cb5e262083c06a6b1c7595c01b4b2e74Luigi Semenzato                               *kernel_warning_collector) {
2016fdc0b48cb5e262083c06a6b1c7595c01b4b2e74Luigi Semenzato  // Accumulate logs to help in diagnosing failures during collection.
20274dc62460b8cdd5bfeac47bfe8e759fc04b55ef8Alex Vakulenko  brillo::LogToString(true);
2036fdc0b48cb5e262083c06a6b1c7595c01b4b2e74Luigi Semenzato  bool handled = kernel_warning_collector->Collect();
20474dc62460b8cdd5bfeac47bfe8e759fc04b55ef8Alex Vakulenko  brillo::LogToString(false);
2056fdc0b48cb5e262083c06a6b1c7595c01b4b2e74Luigi Semenzato  if (!handled)
2066fdc0b48cb5e262083c06a6b1c7595c01b4b2e74Luigi Semenzato    return 1;
2076fdc0b48cb5e262083c06a6b1c7595c01b4b2e74Luigi Semenzato  return 0;
2086fdc0b48cb5e262083c06a6b1c7595c01b4b2e74Luigi Semenzato}
2096fdc0b48cb5e262083c06a6b1c7595c01b4b2e74Luigi Semenzato
210afcf80821c57a189b53b7a66f76d13855d63821eKen Mixter// Interactive/diagnostics mode for generating kernel crash signatures.
211d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fungstatic int GenerateKernelSignature(KernelCollector *kernel_collector,
212d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung                                   const std::string& kernel_signature_file) {
213afcf80821c57a189b53b7a66f76d13855d63821eKen Mixter  std::string kcrash_contents;
214afcf80821c57a189b53b7a66f76d13855d63821eKen Mixter  std::string signature;
215d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  if (!base::ReadFileToString(FilePath(kernel_signature_file),
216a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger                              &kcrash_contents)) {
217afcf80821c57a189b53b7a66f76d13855d63821eKen Mixter    fprintf(stderr, "Could not read file.\n");
218afcf80821c57a189b53b7a66f76d13855d63821eKen Mixter    return 1;
219afcf80821c57a189b53b7a66f76d13855d63821eKen Mixter  }
220afcf80821c57a189b53b7a66f76d13855d63821eKen Mixter  if (!kernel_collector->ComputeKernelStackSignature(
221afcf80821c57a189b53b7a66f76d13855d63821eKen Mixter          kcrash_contents,
222afcf80821c57a189b53b7a66f76d13855d63821eKen Mixter          &signature,
223afcf80821c57a189b53b7a66f76d13855d63821eKen Mixter          true)) {
224afcf80821c57a189b53b7a66f76d13855d63821eKen Mixter    fprintf(stderr, "Signature could not be generated.\n");
225afcf80821c57a189b53b7a66f76d13855d63821eKen Mixter    return 1;
226afcf80821c57a189b53b7a66f76d13855d63821eKen Mixter  }
227afcf80821c57a189b53b7a66f76d13855d63821eKen Mixter  printf("Kernel crash signature is \"%s\".\n", signature.c_str());
228afcf80821c57a189b53b7a66f76d13855d63821eKen Mixter  return 0;
229afcf80821c57a189b53b7a66f76d13855d63821eKen Mixter}
2300340316050044e0995b98fea87ed41ea77abb28bKen Mixter
231a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter// Ensure stdout, stdin, and stderr are open file descriptors.  If
232a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter// they are not, any code which writes to stderr/stdout may write out
233a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter// to files opened during execution.  In particular, when
234a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter// crash_reporter is run by the kernel coredump pipe handler (via
235a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter// kthread_create/kernel_execve), it will not have file table entries
236a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter// 1 and 2 (stdout and stderr) populated.  We populate them here.
237a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixterstatic void OpenStandardFileDescriptors() {
238a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter  int new_fd = -1;
239a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter  // We open /dev/null to fill in any of the standard [0, 2] file
240a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter  // descriptors.  We leave these open for the duration of the
241a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter  // process.  This works because open returns the lowest numbered
242a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter  // invalid fd.
243a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter  do {
244a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter    new_fd = open("/dev/null", 0);
2457e77690375bc8a896a8de318d69d515e67c7aefeBen Chan    CHECK_GE(new_fd, 0) << "Unable to open /dev/null";
246a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter  } while (new_fd >= 0 && new_fd <= 2);
247a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter  close(new_fd);
248a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter}
249a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter
2500340316050044e0995b98fea87ed41ea77abb28bKen Mixterint main(int argc, char *argv[]) {
251d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  DEFINE_bool(init, false, "Initialize crash logging");
252d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  DEFINE_bool(clean_shutdown, false, "Signal clean shutdown");
253d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  DEFINE_string(generate_kernel_signature, "",
254d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung                "Generate signature from given kcrash file");
255d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  DEFINE_bool(crash_test, false, "Crash test");
256d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  DEFINE_string(user, "", "User crash info (pid:signal:exec_name)");
257d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  DEFINE_bool(unclean_check, true, "Check for unclean shutdown");
258c490e0fe987a2cb84787c19be2a516d43010ca2cSteve Fung
259c490e0fe987a2cb84787c19be2a516d43010ca2cSteve Fung#if !defined(__ANDROID__)
260d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  DEFINE_string(udev, "", "Udev event description (type:device:subsystem)");
261c490e0fe987a2cb84787c19be2a516d43010ca2cSteve Fung#endif
262c490e0fe987a2cb84787c19be2a516d43010ca2cSteve Fung
263d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  DEFINE_bool(kernel_warning, false, "Report collected kernel warning");
264d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  DEFINE_string(pid, "", "PID of crashing process");
265d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  DEFINE_string(uid, "", "UID of crashing process");
266d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  DEFINE_string(exe, "", "Executable name of crashing process");
267d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  DEFINE_bool(core2md_failure, false, "Core2md failure test");
268d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  DEFINE_bool(directory_failure, false, "Spool directory failure test");
269d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  DEFINE_string(filter_in, "",
270d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung                "Ignore all crashes but this for testing");
271d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung
272a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter  OpenStandardFileDescriptors();
273a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger  FilePath my_path = base::MakeAbsoluteFilePath(FilePath(argv[0]));
2740340316050044e0995b98fea87ed41ea77abb28bKen Mixter  s_metrics_lib.Init();
27574dc62460b8cdd5bfeac47bfe8e759fc04b55ef8Alex Vakulenko  brillo::FlagHelper::Init(argc, argv, "Chromium OS Crash Reporter");
27674dc62460b8cdd5bfeac47bfe8e759fc04b55ef8Alex Vakulenko  brillo::OpenLog(my_path.BaseName().value().c_str(), true);
27774dc62460b8cdd5bfeac47bfe8e759fc04b55ef8Alex Vakulenko  brillo::InitLog(brillo::kLogToSyslog);
278f19b518532cb2ab8fc1ed77381809f24a30ac4caMike Frysinger
2790340316050044e0995b98fea87ed41ea77abb28bKen Mixter  KernelCollector kernel_collector;
2809b1f300139689eb9c7b7a35e91a4fbc1eab93b4eLei Zhang  kernel_collector.Initialize(CountKernelCrash, IsFeedbackAllowed);
2810340316050044e0995b98fea87ed41ea77abb28bKen Mixter  UserCollector user_collector;
2820340316050044e0995b98fea87ed41ea77abb28bKen Mixter  user_collector.Initialize(CountUserCrash,
2830340316050044e0995b98fea87ed41ea77abb28bKen Mixter                            my_path.value(),
2840340316050044e0995b98fea87ed41ea77abb28bKen Mixter                            IsFeedbackAllowed,
285d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung                            true,  // generate_diagnostics
286d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung                            FLAGS_core2md_failure,
287d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung                            FLAGS_directory_failure,
288d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung                            FLAGS_filter_in);
2890340316050044e0995b98fea87ed41ea77abb28bKen Mixter  UncleanShutdownCollector unclean_shutdown_collector;
2900340316050044e0995b98fea87ed41ea77abb28bKen Mixter  unclean_shutdown_collector.Initialize(CountUncleanShutdown,
291a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter                                        IsFeedbackAllowed);
292c490e0fe987a2cb84787c19be2a516d43010ca2cSteve Fung
293c490e0fe987a2cb84787c19be2a516d43010ca2cSteve Fung#if !defined(__ANDROID__)
294acc7938ede0e3c07a2d1809f82b174b51f7ab7c5Simon Que  UdevCollector udev_collector;
295acc7938ede0e3c07a2d1809f82b174b51f7ab7c5Simon Que  udev_collector.Initialize(CountUdevCrash, IsFeedbackAllowed);
296c490e0fe987a2cb84787c19be2a516d43010ca2cSteve Fung#endif
2970340316050044e0995b98fea87ed41ea77abb28bKen Mixter
2986fdc0b48cb5e262083c06a6b1c7595c01b4b2e74Luigi Semenzato  KernelWarningCollector kernel_warning_collector;
29920980d71ee3c6639f8ba928b0c660da3989dc9aaLuigi Semenzato  kernel_warning_collector.Initialize(CountUdevCrash, IsFeedbackAllowed);
3006fdc0b48cb5e262083c06a6b1c7595c01b4b2e74Luigi Semenzato
3010340316050044e0995b98fea87ed41ea77abb28bKen Mixter  if (FLAGS_init) {
3020340316050044e0995b98fea87ed41ea77abb28bKen Mixter    return Initialize(&kernel_collector,
3030340316050044e0995b98fea87ed41ea77abb28bKen Mixter                      &user_collector,
304d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung                      &unclean_shutdown_collector,
305d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung                      FLAGS_unclean_check,
306d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung                      FLAGS_clean_shutdown);
3070340316050044e0995b98fea87ed41ea77abb28bKen Mixter  }
3080340316050044e0995b98fea87ed41ea77abb28bKen Mixter
3090340316050044e0995b98fea87ed41ea77abb28bKen Mixter  if (FLAGS_clean_shutdown) {
3100340316050044e0995b98fea87ed41ea77abb28bKen Mixter    unclean_shutdown_collector.Disable();
3110340316050044e0995b98fea87ed41ea77abb28bKen Mixter    user_collector.Disable();
3120340316050044e0995b98fea87ed41ea77abb28bKen Mixter    return 0;
3130340316050044e0995b98fea87ed41ea77abb28bKen Mixter  }
3140340316050044e0995b98fea87ed41ea77abb28bKen Mixter
315afcf80821c57a189b53b7a66f76d13855d63821eKen Mixter  if (!FLAGS_generate_kernel_signature.empty()) {
316d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung    return GenerateKernelSignature(&kernel_collector,
317d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung                                   FLAGS_generate_kernel_signature);
318afcf80821c57a189b53b7a66f76d13855d63821eKen Mixter  }
319afcf80821c57a189b53b7a66f76d13855d63821eKen Mixter
320c490e0fe987a2cb84787c19be2a516d43010ca2cSteve Fung#if !defined(__ANDROID__)
321f70060c5e610ed0aa648dcb6aaea5d859834b8baSimon Que  if (!FLAGS_udev.empty()) {
322d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung    return HandleUdevCrash(&udev_collector, FLAGS_udev);
323f70060c5e610ed0aa648dcb6aaea5d859834b8baSimon Que  }
324c490e0fe987a2cb84787c19be2a516d43010ca2cSteve Fung#endif
325f70060c5e610ed0aa648dcb6aaea5d859834b8baSimon Que
3266fdc0b48cb5e262083c06a6b1c7595c01b4b2e74Luigi Semenzato  if (FLAGS_kernel_warning) {
3276fdc0b48cb5e262083c06a6b1c7595c01b4b2e74Luigi Semenzato    return HandleKernelWarning(&kernel_warning_collector);
3286fdc0b48cb5e262083c06a6b1c7595c01b4b2e74Luigi Semenzato  }
3296fdc0b48cb5e262083c06a6b1c7595c01b4b2e74Luigi Semenzato
330d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung  return HandleUserCrash(&user_collector, FLAGS_user, FLAGS_crash_test);
3310340316050044e0995b98fea87ed41ea77abb28bKen Mixter}
332