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