crash_reporter: Enable core dumps
Fix various path/directory locations to their Android equivalents
to enable collection of core dumps and generation of mini dumps
to work correctly. Also add the init script to initialize
crash_reporter.
Bug: 22874832
Change-Id: Iffb1529e5259c5da5ba7f6977b2787e738f68a78
diff --git a/crash_reporter/crash_collector.cc b/crash_reporter/crash_collector.cc
index 69fe939..5406160 100644
--- a/crash_reporter/crash_collector.cc
+++ b/crash_reporter/crash_collector.cc
@@ -36,7 +36,7 @@
const char kLeaveCoreFile[] = "/root/.leave_core";
const char kLsbRelease[] = "/etc/lsb-release";
const char kShellPath[] = "/bin/sh";
-const char kSystemCrashPath[] = "/var/spool/crash";
+const char kSystemCrashPath[] = "/data/misc/crash_reporter/crash";
const char kUploadVarPrefix[] = "upload_var_";
const char kUploadFilePrefix[] = "upload_file_";
@@ -148,23 +148,13 @@
}
FilePath CrashCollector::GetCrashDirectoryInfo(
- uid_t process_euid,
- uid_t default_user_id,
- gid_t default_user_group,
mode_t *mode,
uid_t *directory_owner,
gid_t *directory_group) {
- if (process_euid == default_user_id) {
- *mode = kUserCrashPathMode;
- *directory_owner = default_user_id;
- *directory_group = default_user_group;
- return FilePath(kFallbackUserCrashPath);
- } else {
- *mode = kSystemCrashPathMode;
- *directory_owner = kRootOwner;
- *directory_group = kRootGroup;
- return FilePath(kSystemCrashPath);
- }
+ *mode = kSystemCrashPathMode;
+ *directory_owner = kRootOwner;
+ *directory_group = kRootGroup;
+ return FilePath(kSystemCrashPath);
}
bool CrashCollector::GetUserInfoFromName(const std::string &name,
@@ -188,9 +178,6 @@
bool CrashCollector::GetCreatedCrashDirectoryByEuid(uid_t euid,
FilePath *crash_directory,
bool *out_of_capacity) {
- uid_t default_user_id;
- gid_t default_user_group;
-
if (out_of_capacity) *out_of_capacity = false;
// For testing.
@@ -199,20 +186,11 @@
return true;
}
- if (!GetUserInfoFromName(kDefaultUserName,
- &default_user_id,
- &default_user_group)) {
- LOG(ERROR) << "Could not find default user info";
- return false;
- }
mode_t directory_mode;
uid_t directory_owner;
gid_t directory_group;
*crash_directory =
- GetCrashDirectoryInfo(euid,
- default_user_id,
- default_user_group,
- &directory_mode,
+ GetCrashDirectoryInfo(&directory_mode,
&directory_owner,
&directory_group);
@@ -238,6 +216,8 @@
if (!CheckHasCapacity(*crash_directory)) {
if (out_of_capacity) *out_of_capacity = true;
+ LOG(ERROR) << "Directory " << crash_directory->value()
+ << " is out of capacity.";
return false;
}
@@ -309,6 +289,8 @@
bool CrashCollector::CheckHasCapacity(const FilePath &crash_directory) {
DIR* dir = opendir(crash_directory.value().c_str());
if (!dir) {
+ LOG(WARNING) << "Unable to open crash directory "
+ << crash_directory.value();
return false;
}
struct dirent ent_buf;
diff --git a/crash_reporter/crash_collector.h b/crash_reporter/crash_collector.h
index 0d335cd..0c28048 100644
--- a/crash_reporter/crash_collector.h
+++ b/crash_reporter/crash_collector.h
@@ -72,12 +72,9 @@
forced_crash_directory_ = forced_directory;
}
- base::FilePath GetCrashDirectoryInfo(uid_t process_euid,
- uid_t default_user_id,
- gid_t default_user_group,
- mode_t *mode,
- uid_t *directory_owner,
- gid_t *directory_group);
+ base::FilePath GetCrashDirectoryInfo(mode_t *mode,
+ uid_t *directory_owner,
+ gid_t *directory_group);
bool GetUserInfoFromName(const std::string &name,
uid_t *uid,
gid_t *gid);
diff --git a/crash_reporter/crash_collector_test.cc b/crash_reporter/crash_collector_test.cc
index 13fb76a..28c4462 100644
--- a/crash_reporter/crash_collector_test.cc
+++ b/crash_reporter/crash_collector_test.cc
@@ -83,54 +83,6 @@
EXPECT_EQ("_", collector_.Sanitize(" "));
}
-TEST_F(CrashCollectorTest, GetCrashDirectoryInfo) {
- FilePath path;
- const int kRootUid = 0;
- const int kRootGid = 0;
- const int kNtpUid = 5;
- const int kChronosUid = 1000;
- const int kChronosGid = 1001;
- const mode_t kExpectedSystemMode = 01755;
- const mode_t kExpectedUserMode = 0755;
-
- mode_t directory_mode;
- uid_t directory_owner;
- gid_t directory_group;
-
- path = collector_.GetCrashDirectoryInfo(kRootUid,
- kChronosUid,
- kChronosGid,
- &directory_mode,
- &directory_owner,
- &directory_group);
- EXPECT_EQ("/var/spool/crash", path.value());
- EXPECT_EQ(kExpectedSystemMode, directory_mode);
- EXPECT_EQ(kRootUid, directory_owner);
- EXPECT_EQ(kRootGid, directory_group);
-
- path = collector_.GetCrashDirectoryInfo(kNtpUid,
- kChronosUid,
- kChronosGid,
- &directory_mode,
- &directory_owner,
- &directory_group);
- EXPECT_EQ("/var/spool/crash", path.value());
- EXPECT_EQ(kExpectedSystemMode, directory_mode);
- EXPECT_EQ(kRootUid, directory_owner);
- EXPECT_EQ(kRootGid, directory_group);
-
- path = collector_.GetCrashDirectoryInfo(kChronosUid,
- kChronosUid,
- kChronosGid,
- &directory_mode,
- &directory_owner,
- &directory_group);
- EXPECT_EQ("/var/spool/crash", path.value());
- EXPECT_EQ(kExpectedUserMode, directory_mode);
- EXPECT_EQ(kChronosUid, directory_owner);
- EXPECT_EQ(kChronosGid, directory_group);
-}
-
TEST_F(CrashCollectorTest, FormatDumpBasename) {
struct tm tm = {0};
tm.tm_sec = 15;
diff --git a/crash_reporter/init.crash_reporter.rc b/crash_reporter/init.crash_reporter.rc
new file mode 100644
index 0000000..f65371a
--- /dev/null
+++ b/crash_reporter/init.crash_reporter.rc
@@ -0,0 +1,19 @@
+on property:crash_reporter.coredump.enabled=1
+ write /proc/sys/kernel/core_pattern \
+ "|/system/bin/crash_reporter --user=%P:%s:%u:%e"
+
+on property:crash_reporter.coredump.enabled=0
+ write /proc/sys/kernel/core_pattern "core"
+
+on boot
+ # Allow catching multiple unrelated concurrent crashes, but use a finite
+ # number to prevent infinitely recursing on crash handling.
+ write /proc/sys/kernel/core_pipe_limit 4
+
+ # Create crash directories.
+ mkdir /data/misc/crash_reporter 0700 root root
+ mkdir /data/local/tmp/crash_reporter 0700 root root
+
+service crash_reporter /system/bin/crash_reporter --init
+ class late_start
+ oneshot
diff --git a/crash_reporter/user_collector.cc b/crash_reporter/user_collector.cc
index 069b581..6bf9120 100644
--- a/crash_reporter/user_collector.cc
+++ b/crash_reporter/user_collector.cc
@@ -24,21 +24,17 @@
#include <base/strings/stringprintf.h>
#include <chromeos/process.h>
#include <chromeos/syslog_logging.h>
+#include <cutils/properties.h>
static const char kCollectionErrorSignature[] =
"crash_reporter-user-collection";
-// This procfs file is used to cause kernel core file writing to
-// instead pipe the core file into a user space process. See
-// core(5) man page.
-static const char kCorePatternFile[] = "/proc/sys/kernel/core_pattern";
-static const char kCorePipeLimitFile[] = "/proc/sys/kernel/core_pipe_limit";
-// Set core_pipe_limit to 4 so that we can catch a few unrelated concurrent
-// crashes, but finite to avoid infinitely recursing on crash handling.
-static const char kCorePipeLimit[] = "4";
-static const char kCoreToMinidumpConverterPath[] = "/usr/bin/core2md";
+static const char kCorePatternProperty[] = "crash_reporter.coredump.enabled";
+static const char kCoreToMinidumpConverterPath[] = "/system/bin/core2md";
static const char kStatePrefix[] = "State:\t";
+static const char kCoreTempFolder[] = "/data/local/tmp/crash_reporter";
+
// Define an otherwise invalid value that represents an unknown UID.
static const uid_t kUnknownUid = -1;
@@ -50,8 +46,6 @@
UserCollector::UserCollector()
: generate_diagnostics_(false),
- core_pattern_file_(kCorePatternFile),
- core_pipe_limit_file_(kCorePipeLimitFile),
initialized_(false) {
}
@@ -115,18 +109,8 @@
CHECK(initialized_);
LOG(INFO) << (enabled ? "Enabling" : "Disabling") << " user crash handling";
- if (base::WriteFile(FilePath(core_pipe_limit_file_), kCorePipeLimit,
- strlen(kCorePipeLimit)) !=
- static_cast<int>(strlen(kCorePipeLimit))) {
- PLOG(ERROR) << "Unable to write " << core_pipe_limit_file_;
- return false;
- }
- std::string pattern = GetPattern(enabled);
- if (base::WriteFile(FilePath(core_pattern_file_), pattern.c_str(),
- pattern.length()) != static_cast<int>(pattern.length())) {
- PLOG(ERROR) << "Unable to write " << core_pattern_file_;
- return false;
- }
+ property_set(kCorePatternProperty, enabled ? "1" : "0");
+
return true;
}
@@ -342,7 +326,7 @@
bool UserCollector::CopyStdinToCoreFile(const FilePath &core_path) {
// Copy off all stdin to a core file.
- FilePath stdin_path("/dev/fd/0");
+ FilePath stdin_path("/proc/self/fd/0");
if (base::CopyFile(stdin_path, core_path)) {
return true;
}
@@ -438,7 +422,7 @@
// Directory like /tmp/crash_reporter/1234 which contains the
// procfs entries and other temporary files used during conversion.
- FilePath container_dir(StringPrintf("/tmp/crash_reporter/%d", pid));
+ FilePath container_dir(StringPrintf("%s/%d", kCoreTempFolder, pid));
// Delete a pre-existing directory from crash reporter that may have
// been left around for diagnostics from a failed conversion attempt.
// If we don't, existing files can cause forking to fail.
diff --git a/crash_reporter/user_collector.h b/crash_reporter/user_collector.h
index 7b356ee..dd42457 100644
--- a/crash_reporter/user_collector.h
+++ b/crash_reporter/user_collector.h
@@ -47,16 +47,6 @@
bool HandleCrash(const std::string &crash_attributes,
const char *force_exec);
- // Set (override the default) core file pattern.
- void set_core_pattern_file(const std::string &pattern) {
- core_pattern_file_ = pattern;
- }
-
- // Set (override the default) core pipe limit file.
- void set_core_pipe_limit_file(const std::string &path) {
- core_pipe_limit_file_ = path;
- }
-
private:
friend class UserCollectorTest;
FRIEND_TEST(UserCollectorTest, CopyOffProcFilesBadPath);
@@ -172,8 +162,6 @@
std::string *reason);
bool generate_diagnostics_;
- std::string core_pattern_file_;
- std::string core_pipe_limit_file_;
std::string our_path_;
bool initialized_;
diff --git a/crash_reporter/user_collector_test.cc b/crash_reporter/user_collector_test.cc
index ee3ca12..3c59521 100644
--- a/crash_reporter/user_collector_test.cc
+++ b/crash_reporter/user_collector_test.cc
@@ -60,8 +60,6 @@
"");
base::DeleteFile(FilePath("test"), true);
mkdir("test", 0777);
- collector_.set_core_pattern_file("test/core_pattern");
- collector_.set_core_pipe_limit_file("test/core_pipe_limit");
pid_ = getpid();
chromeos::ClearLog();
}
@@ -84,49 +82,6 @@
pid_t pid_;
};
-TEST_F(UserCollectorTest, EnableOK) {
- ASSERT_TRUE(collector_.Enable());
- ExpectFileEquals("|/my/path --user=%P:%s:%u:%e",
- FilePath("test/core_pattern"));
- ExpectFileEquals("4", FilePath("test/core_pipe_limit"));
- ASSERT_EQ(s_crashes, 0);
- EXPECT_TRUE(FindLog("Enabling user crash handling"));
-}
-
-TEST_F(UserCollectorTest, EnableNoPatternFileAccess) {
- collector_.set_core_pattern_file("/does_not_exist");
- ASSERT_FALSE(collector_.Enable());
- ASSERT_EQ(s_crashes, 0);
- EXPECT_TRUE(FindLog("Enabling user crash handling"));
- EXPECT_TRUE(FindLog("Unable to write /does_not_exist"));
-}
-
-TEST_F(UserCollectorTest, EnableNoPipeLimitFileAccess) {
- collector_.set_core_pipe_limit_file("/does_not_exist");
- ASSERT_FALSE(collector_.Enable());
- ASSERT_EQ(s_crashes, 0);
- // Core pattern should not be written if we cannot access the pipe limit
- // or otherwise we may set a pattern that results in infinite recursion.
- ASSERT_FALSE(base::PathExists(FilePath("test/core_pattern")));
- EXPECT_TRUE(FindLog("Enabling user crash handling"));
- EXPECT_TRUE(FindLog("Unable to write /does_not_exist"));
-}
-
-TEST_F(UserCollectorTest, DisableOK) {
- ASSERT_TRUE(collector_.Disable());
- ExpectFileEquals("core", FilePath("test/core_pattern"));
- ASSERT_EQ(s_crashes, 0);
- EXPECT_TRUE(FindLog("Disabling user crash handling"));
-}
-
-TEST_F(UserCollectorTest, DisableNoFileAccess) {
- collector_.set_core_pattern_file("/does_not_exist");
- ASSERT_FALSE(collector_.Disable());
- ASSERT_EQ(s_crashes, 0);
- EXPECT_TRUE(FindLog("Disabling user crash handling"));
- EXPECT_TRUE(FindLog("Unable to write /does_not_exist"));
-}
-
TEST_F(UserCollectorTest, ParseCrashAttributes) {
pid_t pid;
int signal;