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 17129bea543b7572bfdf09c6a7b3cebbe3b57ce723Steve Fung#include "user_collector.h" 180340316050044e0995b98fea87ed41ea77abb28bKen Mixter 196e709a11031c80c96f47da50b3231074334f462cBen Chan#include <elf.h> 206e709a11031c80c96f47da50b3231074334f462cBen Chan#include <fcntl.h> 21777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter#include <grp.h> // For struct group. 221b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter#include <pcrecpp.h> 23777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter#include <pwd.h> // For struct passwd. 24f84ea21aab3c1c6ef1f358534e5c437878675d74Ben Chan#include <stdint.h> 258bafb3da8fe46993f995054ec84c75f82e6bb2d8Steve Fung#include <sys/cdefs.h> // For __WORDSIZE 266db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung#include <sys/fsuid.h> 272953c3a87a7b201bbf08555129f0640ede1d0cdbKen Mixter#include <sys/types.h> // For getpwuid_r, getgrnam_r, WEXITSTATUS. 28b440e50b6f4af0f7c3c5bc01d975d48f93ae3741Steve Fung#include <unistd.h> // For setgroups 29777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter 306db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung#include <iostream> // For std::oct 31e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa#include <string> 322953c3a87a7b201bbf08555129f0640ede1d0cdbKen Mixter#include <vector> 33e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa 34ab6cc90503ca2db976a3cb9c9382a9da85c4b5a2Ben Chan#include <base/files/file_util.h> 357e77690375bc8a896a8de318d69d515e67c7aefeBen Chan#include <base/logging.h> 367e77690375bc8a896a8de318d69d515e67c7aefeBen Chan#include <base/posix/eintr_wrapper.h> 377e77690375bc8a896a8de318d69d515e67c7aefeBen Chan#include <base/strings/string_split.h> 387e77690375bc8a896a8de318d69d515e67c7aefeBen Chan#include <base/strings/string_util.h> 397e77690375bc8a896a8de318d69d515e67c7aefeBen Chan#include <base/strings/stringprintf.h> 4074dc62460b8cdd5bfeac47bfe8e759fc04b55ef8Alex Vakulenko#include <brillo/osrelease_reader.h> 4174dc62460b8cdd5bfeac47bfe8e759fc04b55ef8Alex Vakulenko#include <brillo/process.h> 4274dc62460b8cdd5bfeac47bfe8e759fc04b55ef8Alex Vakulenko#include <brillo/syslog_logging.h> 43ab2ac7d11442975f700bbde5702a96d020d82254Steve Fung#include <cutils/properties.h> 44b440e50b6f4af0f7c3c5bc01d975d48f93ae3741Steve Fung#include <private/android_filesystem_config.h> 45207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter 46207694d3f491ef602a859c30cc1379584f2d61cfKen Mixterstatic const char kCollectionErrorSignature[] = 47207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter "crash_reporter-user-collection"; 48ab2ac7d11442975f700bbde5702a96d020d82254Steve Fungstatic const char kCorePatternProperty[] = "crash_reporter.coredump.enabled"; 49ab2ac7d11442975f700bbde5702a96d020d82254Steve Fungstatic const char kCoreToMinidumpConverterPath[] = "/system/bin/core2md"; 50777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter 51f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chanstatic const char kStatePrefix[] = "State:\t"; 52c49dbd4775986f32b2f09659595f9f28ef7f6b44Ken Mixter 53da98133cc0b88e5a545c5f588ff5a7e6a6f75befSteve Fungstatic const char kCoreTempFolder[] = "/data/misc/crash_reporter/tmp"; 54ab2ac7d11442975f700bbde5702a96d020d82254Steve Fung 55773fd3c42883b17b5918c71aead5690e16438248Steve Fung// Define an otherwise invalid value that represents an unknown UID and GID. 561c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebsstatic const uid_t kUnknownUid = -1; 57773fd3c42883b17b5918c71aead5690e16438248Steve Fungstatic const gid_t kUnknownGid = -1; 581c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs 59777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixterconst char *UserCollector::kUserId = "Uid:\t"; 60777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixterconst char *UserCollector::kGroupId = "Gid:\t"; 61e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa 6272e3c828dcc8230a1ae94f0f814891d54b7c0b92Steve Fung// Product information keys in the /etc/os-release.d folder. 63aa265b633b992a701e954fe39c780a90d377a42dSteve Fungstatic const char kBdkVersionKey[] = "bdk_version"; 6472e3c828dcc8230a1ae94f0f814891d54b7c0b92Steve Fungstatic const char kProductIDKey[] = "product_id"; 6572e3c828dcc8230a1ae94f0f814891d54b7c0b92Steve Fungstatic const char kProductVersionKey[] = "product_version"; 66aa265b633b992a701e954fe39c780a90d377a42dSteve Fung 674818011085da225e6fb80512163ac8a8a22aed7fSteve Fung 689f90acaa4d420530d7b4ddd37112518df68e373aSimon Queusing base::FilePath; 69a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysingerusing base::StringPrintf; 709f90acaa4d420530d7b4ddd37112518df68e373aSimon Que 71e4a86037f405415c460ace194fbf16cfd93d4c6Chris SosaUserCollector::UserCollector() 72777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter : generate_diagnostics_(false), 730340316050044e0995b98fea87ed41ea77abb28bKen Mixter initialized_(false) { 74e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa} 75e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa 76e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosavoid UserCollector::Initialize( 77e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa UserCollector::CountCrashFunction count_crash_function, 78e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa const std::string &our_path, 79e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa UserCollector::IsFeedbackAllowedFunction is_feedback_allowed_function, 80d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung bool generate_diagnostics, 81d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung bool core2md_failure, 82d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung bool directory_failure, 83d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung const std::string &filter_in) { 840340316050044e0995b98fea87ed41ea77abb28bKen Mixter CrashCollector::Initialize(count_crash_function, 85a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter is_feedback_allowed_function); 86e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa our_path_ = our_path; 87e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa initialized_ = true; 88777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter generate_diagnostics_ = generate_diagnostics; 89d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung core2md_failure_ = core2md_failure; 90d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung directory_failure_ = directory_failure; 91d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung filter_in_ = filter_in; 92b440e50b6f4af0f7c3c5bc01d975d48f93ae3741Steve Fung 93a76ba8578390fe67874f2d102489e6d5629cb999Steve Fung gid_t groups[] = { AID_ROOT, AID_SYSTEM, AID_DBUS, AID_READPROC }; 94b440e50b6f4af0f7c3c5bc01d975d48f93ae3741Steve Fung if (setgroups(arraysize(groups), groups) != 0) { 95a76ba8578390fe67874f2d102489e6d5629cb999Steve Fung PLOG(FATAL) << "Unable to set groups to root, system, dbus, and readproc"; 96b440e50b6f4af0f7c3c5bc01d975d48f93ae3741Steve Fung } 97e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa} 98e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa 99e4a86037f405415c460ace194fbf16cfd93d4c6Chris SosaUserCollector::~UserCollector() { 100e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa} 101e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa 1026e709a11031c80c96f47da50b3231074334f462cBen Chanstd::string UserCollector::GetErrorTypeSignature(ErrorType error_type) const { 1036e709a11031c80c96f47da50b3231074334f462cBen Chan switch (error_type) { 1046e709a11031c80c96f47da50b3231074334f462cBen Chan case kErrorSystemIssue: 1056e709a11031c80c96f47da50b3231074334f462cBen Chan return "system-issue"; 1066e709a11031c80c96f47da50b3231074334f462cBen Chan case kErrorReadCoreData: 1076e709a11031c80c96f47da50b3231074334f462cBen Chan return "read-core-data"; 1086e709a11031c80c96f47da50b3231074334f462cBen Chan case kErrorUnusableProcFiles: 1096e709a11031c80c96f47da50b3231074334f462cBen Chan return "unusable-proc-files"; 1106e709a11031c80c96f47da50b3231074334f462cBen Chan case kErrorInvalidCoreFile: 1116e709a11031c80c96f47da50b3231074334f462cBen Chan return "invalid-core-file"; 1126e709a11031c80c96f47da50b3231074334f462cBen Chan case kErrorUnsupported32BitCoreFile: 1136e709a11031c80c96f47da50b3231074334f462cBen Chan return "unsupported-32bit-core-file"; 1146e709a11031c80c96f47da50b3231074334f462cBen Chan case kErrorCore2MinidumpConversion: 1156e709a11031c80c96f47da50b3231074334f462cBen Chan return "core2md-conversion"; 1166e709a11031c80c96f47da50b3231074334f462cBen Chan default: 1176e709a11031c80c96f47da50b3231074334f462cBen Chan return ""; 1186e709a11031c80c96f47da50b3231074334f462cBen Chan } 1196e709a11031c80c96f47da50b3231074334f462cBen Chan} 1206e709a11031c80c96f47da50b3231074334f462cBen Chan 121e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosabool UserCollector::SetUpInternal(bool enabled) { 122e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa CHECK(initialized_); 123a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter LOG(INFO) << (enabled ? "Enabling" : "Disabling") << " user crash handling"; 124a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter 125ab2ac7d11442975f700bbde5702a96d020d82254Steve Fung property_set(kCorePatternProperty, enabled ? "1" : "0"); 126ab2ac7d11442975f700bbde5702a96d020d82254Steve Fung 127e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa return true; 128e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa} 129e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa 130f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chanbool UserCollector::GetFirstLineWithPrefix( 131f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan const std::vector<std::string> &lines, 132f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan const char *prefix, std::string *line) { 133f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan std::vector<std::string>::const_iterator line_iterator; 134f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan for (line_iterator = lines.begin(); line_iterator != lines.end(); 135777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter ++line_iterator) { 136f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan if (line_iterator->find(prefix) == 0) { 137f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan *line = *line_iterator; 138f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan return true; 139f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan } 140777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter } 141f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan return false; 142f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan} 143f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan 144f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chanbool UserCollector::GetIdFromStatus( 145f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan const char *prefix, IdKind kind, 146f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan const std::vector<std::string> &status_lines, int *id) { 147f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan // From fs/proc/array.c:task_state(), this file contains: 148f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan // \nUid:\t<uid>\t<euid>\t<suid>\t<fsuid>\n 149f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan std::string id_line; 150f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan if (!GetFirstLineWithPrefix(status_lines, prefix, &id_line)) { 151777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter return false; 152777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter } 153f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan std::string id_substring = id_line.substr(strlen(prefix), std::string::npos); 154ea05ff9229163e6aacfb7f7dffdd76bff559673cAlex Vakulenko std::vector<std::string> ids = base::SplitString( 155ea05ff9229163e6aacfb7f7dffdd76bff559673cAlex Vakulenko id_substring, "\t", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 156777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter if (ids.size() != kIdMax || kind < 0 || kind >= kIdMax) { 157777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter return false; 158777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter } 159777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter const char *number = ids[kind].c_str(); 160262d798b380a59ef691ede4c6a32aa71ff191295Ben Chan char *end_number = nullptr; 161777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter *id = strtol(number, &end_number, 10); 162f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan if (*end_number != '\0') { 163777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter return false; 164f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan } 165f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan return true; 166f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan} 167f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan 168f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chanbool UserCollector::GetStateFromStatus( 169f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan const std::vector<std::string> &status_lines, std::string *state) { 170f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan std::string state_line; 171f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan if (!GetFirstLineWithPrefix(status_lines, kStatePrefix, &state_line)) { 172f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan return false; 173f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan } 174f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan *state = state_line.substr(strlen(kStatePrefix), std::string::npos); 175777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter return true; 176777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter} 177777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter 178207694d3f491ef602a859c30cc1379584f2d61cfKen Mixtervoid UserCollector::EnqueueCollectionErrorLog(pid_t pid, 1796e709a11031c80c96f47da50b3231074334f462cBen Chan ErrorType error_type, 180207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter const std::string &exec) { 181207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter FilePath crash_path; 182a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter LOG(INFO) << "Writing conversion problems as separate crash report."; 183262d798b380a59ef691ede4c6a32aa71ff191295Ben Chan if (!GetCreatedCrashDirectoryByEuid(0, &crash_path, nullptr)) { 184a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter LOG(ERROR) << "Could not even get log directory; out of space?"; 185207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter return; 186207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter } 1878fce2859059b27147ddd15f9a0e89a2816ed12caThiemo Nagel AddCrashMetaData("sig", kCollectionErrorSignature); 1888fce2859059b27147ddd15f9a0e89a2816ed12caThiemo Nagel AddCrashMetaData("error_type", GetErrorTypeSignature(error_type)); 189262d798b380a59ef691ede4c6a32aa71ff191295Ben Chan std::string dump_basename = FormatDumpBasename(exec, time(nullptr), pid); 19074dc62460b8cdd5bfeac47bfe8e759fc04b55ef8Alex Vakulenko std::string error_log = brillo::GetLog(); 1911b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter FilePath diag_log_path = GetCrashPath(crash_path, dump_basename, "diaglog"); 192acc7938ede0e3c07a2d1809f82b174b51f7ab7c5Simon Que if (GetLogContents(FilePath(log_config_path_), kCollectionErrorSignature, 1931b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter diag_log_path)) { 1941b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter // We load the contents of diag_log into memory and append it to 1951b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter // the error log. We cannot just append to files because we need 1961b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter // to always create new files to prevent attack. 1971b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter std::string diag_log_contents; 198a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger base::ReadFileToString(diag_log_path, &diag_log_contents); 1991b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter error_log.append(diag_log_contents); 200a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger base::DeleteFile(diag_log_path, false); 2011b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter } 202207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter FilePath log_path = GetCrashPath(crash_path, dump_basename, "log"); 203207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter FilePath meta_path = GetCrashPath(crash_path, dump_basename, "meta"); 204f30c641225e55055641ffe3fd679a96e44f34af6Ben Chan // We must use WriteNewFile instead of base::WriteFile as we do 2059b346474538a255bc7144ae358bb0ee129163d58Ken Mixter // not want to write with root access to a symlink that an attacker 2069b346474538a255bc7144ae358bb0ee129163d58Ken Mixter // might have created. 2078fce2859059b27147ddd15f9a0e89a2816ed12caThiemo Nagel if (WriteNewFile(log_path, error_log.data(), error_log.length()) < 0) { 2088fce2859059b27147ddd15f9a0e89a2816ed12caThiemo Nagel LOG(ERROR) << "Error writing new file " << log_path.value(); 2098fce2859059b27147ddd15f9a0e89a2816ed12caThiemo Nagel return; 2108fce2859059b27147ddd15f9a0e89a2816ed12caThiemo Nagel } 211207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter WriteCrashMetaData(meta_path, exec, log_path.value()); 212207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter} 213207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter 214777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixterbool UserCollector::CopyOffProcFiles(pid_t pid, 215777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter const FilePath &container_dir) { 216a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger if (!base::CreateDirectory(container_dir)) { 2176db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung PLOG(ERROR) << "Could not create " << container_dir.value(); 2186db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung return false; 2196db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung } 2206db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung int dir_mask = base::FILE_PERMISSION_READ_BY_USER 2216db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung | base::FILE_PERMISSION_WRITE_BY_USER 2226db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung | base::FILE_PERMISSION_EXECUTE_BY_USER 2236db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung | base::FILE_PERMISSION_READ_BY_GROUP 2246db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung | base::FILE_PERMISSION_WRITE_BY_GROUP; 2256db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung if (!base::SetPosixFilePermissions(container_dir, 2266db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung base::FILE_PERMISSION_MASK & dir_mask)) { 2276db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung PLOG(ERROR) << "Could not set permissions for " << container_dir.value() 2286db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung << " to " << std::oct 2296db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung << (base::FILE_PERMISSION_MASK & dir_mask); 230777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter return false; 231777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter } 232777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter FilePath process_path = GetProcessPath(pid); 233a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger if (!base::PathExists(process_path)) { 234a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter LOG(ERROR) << "Path " << process_path.value() << " does not exist"; 235777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter return false; 236777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter } 237777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter static const char *proc_files[] = { 238777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter "auxv", 239777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter "cmdline", 240777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter "environ", 241777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter "maps", 242777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter "status" 243777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter }; 244777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter for (unsigned i = 0; i < arraysize(proc_files); ++i) { 245a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger if (!base::CopyFile(process_path.Append(proc_files[i]), 246a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger container_dir.Append(proc_files[i]))) { 247a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter LOG(ERROR) << "Could not copy " << proc_files[i] << " file"; 248777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter return false; 249777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter } 250777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter } 251ec7d7835a24884ed0e18317dc07af2fed2a50e64Ben Chan return true; 252f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan} 253f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan 2546e709a11031c80c96f47da50b3231074334f462cBen Chanbool UserCollector::ValidateProcFiles(const FilePath &container_dir) const { 255f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan // Check if the maps file is empty, which could be due to the crashed 256f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan // process being reaped by the kernel before finishing a core dump. 257f84ea21aab3c1c6ef1f358534e5c437878675d74Ben Chan int64_t file_size = 0; 258a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger if (!base::GetFileSize(container_dir.Append("maps"), &file_size)) { 259f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan LOG(ERROR) << "Could not get the size of maps file"; 260f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan return false; 261f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan } 262f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan if (file_size == 0) { 263f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan LOG(ERROR) << "maps file is empty"; 264f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan return false; 265f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan } 266777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter return true; 267777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter} 268777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter 2696e709a11031c80c96f47da50b3231074334f462cBen ChanUserCollector::ErrorType UserCollector::ValidateCoreFile( 2706e709a11031c80c96f47da50b3231074334f462cBen Chan const FilePath &core_path) const { 2716e709a11031c80c96f47da50b3231074334f462cBen Chan int fd = HANDLE_EINTR(open(core_path.value().c_str(), O_RDONLY)); 2726e709a11031c80c96f47da50b3231074334f462cBen Chan if (fd < 0) { 273b3fe6c3a4e91e4843ff9c03098e3931bec23d447Chris Masone PLOG(ERROR) << "Could not open core file " << core_path.value(); 2746e709a11031c80c96f47da50b3231074334f462cBen Chan return kErrorInvalidCoreFile; 2756e709a11031c80c96f47da50b3231074334f462cBen Chan } 2766e709a11031c80c96f47da50b3231074334f462cBen Chan 2776e709a11031c80c96f47da50b3231074334f462cBen Chan char e_ident[EI_NIDENT]; 278a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger bool read_ok = base::ReadFromFD(fd, e_ident, sizeof(e_ident)); 279f1a5014637180457af21cc40a5ca64ab18a6947bMike Frysinger IGNORE_EINTR(close(fd)); 2806e709a11031c80c96f47da50b3231074334f462cBen Chan if (!read_ok) { 2816e709a11031c80c96f47da50b3231074334f462cBen Chan LOG(ERROR) << "Could not read header of core file"; 2826e709a11031c80c96f47da50b3231074334f462cBen Chan return kErrorInvalidCoreFile; 2836e709a11031c80c96f47da50b3231074334f462cBen Chan } 2846e709a11031c80c96f47da50b3231074334f462cBen Chan 2856e709a11031c80c96f47da50b3231074334f462cBen Chan if (e_ident[EI_MAG0] != ELFMAG0 || e_ident[EI_MAG1] != ELFMAG1 || 2866e709a11031c80c96f47da50b3231074334f462cBen Chan e_ident[EI_MAG2] != ELFMAG2 || e_ident[EI_MAG3] != ELFMAG3) { 2876e709a11031c80c96f47da50b3231074334f462cBen Chan LOG(ERROR) << "Invalid core file"; 2886e709a11031c80c96f47da50b3231074334f462cBen Chan return kErrorInvalidCoreFile; 2896e709a11031c80c96f47da50b3231074334f462cBen Chan } 2906e709a11031c80c96f47da50b3231074334f462cBen Chan 2916e709a11031c80c96f47da50b3231074334f462cBen Chan#if __WORDSIZE == 64 2926e709a11031c80c96f47da50b3231074334f462cBen Chan // TODO(benchan, mkrebs): Remove this check once core2md can 2936e709a11031c80c96f47da50b3231074334f462cBen Chan // handles both 32-bit and 64-bit ELF on a 64-bit platform. 2946e709a11031c80c96f47da50b3231074334f462cBen Chan if (e_ident[EI_CLASS] == ELFCLASS32) { 2956e709a11031c80c96f47da50b3231074334f462cBen Chan LOG(ERROR) << "Conversion of 32-bit core file on 64-bit platform is " 2966e709a11031c80c96f47da50b3231074334f462cBen Chan << "currently not supported"; 2976e709a11031c80c96f47da50b3231074334f462cBen Chan return kErrorUnsupported32BitCoreFile; 2986e709a11031c80c96f47da50b3231074334f462cBen Chan } 2996e709a11031c80c96f47da50b3231074334f462cBen Chan#endif 3006e709a11031c80c96f47da50b3231074334f462cBen Chan 3016e709a11031c80c96f47da50b3231074334f462cBen Chan return kErrorNone; 3026e709a11031c80c96f47da50b3231074334f462cBen Chan} 3036e709a11031c80c96f47da50b3231074334f462cBen Chan 3041c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebsbool UserCollector::GetCreatedCrashDirectory(pid_t pid, uid_t supplied_ruid, 305207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter FilePath *crash_file_path, 306207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter bool *out_of_capacity) { 307777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter FilePath process_path = GetProcessPath(pid); 308777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter std::string status; 309d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung if (directory_failure_) { 310a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter LOG(ERROR) << "Purposefully failing to create spool directory"; 311207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter return false; 312207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter } 313f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan 3141c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs uid_t uid; 315a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger if (base::ReadFileToString(process_path.Append("status"), &status)) { 316ea05ff9229163e6aacfb7f7dffdd76bff559673cAlex Vakulenko std::vector<std::string> status_lines = base::SplitString( 317ea05ff9229163e6aacfb7f7dffdd76bff559673cAlex Vakulenko status, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 318f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan 3191c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs std::string process_state; 3201c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs if (!GetStateFromStatus(status_lines, &process_state)) { 3211c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs LOG(ERROR) << "Could not find process state in status file"; 3221c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs return false; 3231c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs } 3241c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs LOG(INFO) << "State of crashed process [" << pid << "]: " << process_state; 325f13bb58358b879258c5c0eb48c6e09895d394ef1Ben Chan 3261c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs // Get effective UID of crashing process. 3271c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs int id; 3281c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs if (!GetIdFromStatus(kUserId, kIdEffective, status_lines, &id)) { 3291c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs LOG(ERROR) << "Could not find euid in status file"; 3301c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs return false; 3311c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs } 3321c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs uid = id; 3331c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs } else if (supplied_ruid != kUnknownUid) { 3341c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs LOG(INFO) << "Using supplied UID " << supplied_ruid 3351c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs << " for crashed process [" << pid 3361c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs << "] due to error reading status file"; 3371c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs uid = supplied_ruid; 3381c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs } else { 3391c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs LOG(ERROR) << "Could not read status file and kernel did not supply UID"; 3401c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs LOG(INFO) << "Path " << process_path.value() << " DirectoryExists: " 341a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger << base::DirectoryExists(process_path); 342207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter return false; 343207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter } 3441c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs 3451c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs if (!GetCreatedCrashDirectoryByEuid(uid, crash_file_path, out_of_capacity)) { 346a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter LOG(ERROR) << "Could not create crash directory"; 347777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter return false; 348777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter } 349207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter return true; 350777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter} 351777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter 352777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixterbool UserCollector::CopyStdinToCoreFile(const FilePath &core_path) { 353777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter // Copy off all stdin to a core file. 354ab2ac7d11442975f700bbde5702a96d020d82254Steve Fung FilePath stdin_path("/proc/self/fd/0"); 355a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger if (base::CopyFile(stdin_path, core_path)) { 356777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter return true; 357777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter } 358777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter 359b3fe6c3a4e91e4843ff9c03098e3931bec23d447Chris Masone PLOG(ERROR) << "Could not write core file"; 360777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter // If the file system was full, make sure we remove any remnants. 361a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger base::DeleteFile(core_path, false); 362777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter return false; 363777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter} 364777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter 365207694d3f491ef602a859c30cc1379584f2d61cfKen Mixterbool UserCollector::RunCoreToMinidump(const FilePath &core_path, 366207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter const FilePath &procfs_directory, 367207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter const FilePath &minidump_path, 368207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter const FilePath &temp_directory) { 369777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter FilePath output_path = temp_directory.Append("output"); 37074dc62460b8cdd5bfeac47bfe8e759fc04b55ef8Alex Vakulenko brillo::ProcessImpl core2md; 371a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter core2md.RedirectOutput(output_path.value()); 372a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter core2md.AddArg(kCoreToMinidumpConverterPath); 373a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter core2md.AddArg(core_path.value()); 374a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter core2md.AddArg(procfs_directory.value()); 375a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter 376d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung if (!core2md_failure_) { 377a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter core2md.AddArg(minidump_path.value()); 378a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter } else { 379207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter // To test how core2md errors are propagaged, cause an error 380207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter // by forgetting a required argument. 381207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter } 382207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter 383a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter int errorlevel = core2md.Run(); 384777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter 385777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter std::string output; 386a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger base::ReadFileToString(output_path, &output); 387777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter if (errorlevel != 0) { 388a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter LOG(ERROR) << "Problem during " << kCoreToMinidumpConverterPath 389a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter << " [result=" << errorlevel << "]: " << output; 390777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter return false; 391777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter } 392777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter 393a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger if (!base::PathExists(minidump_path)) { 394a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter LOG(ERROR) << "Minidump file " << minidump_path.value() 395a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter << " was not created"; 396777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter return false; 397777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter } 398777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter return true; 399777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter} 400777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter 4016e709a11031c80c96f47da50b3231074334f462cBen ChanUserCollector::ErrorType UserCollector::ConvertCoreToMinidump( 4026e709a11031c80c96f47da50b3231074334f462cBen Chan pid_t pid, 4036e709a11031c80c96f47da50b3231074334f462cBen Chan const FilePath &container_dir, 4046e709a11031c80c96f47da50b3231074334f462cBen Chan const FilePath &core_path, 4056e709a11031c80c96f47da50b3231074334f462cBen Chan const FilePath &minidump_path) { 406ec7d7835a24884ed0e18317dc07af2fed2a50e64Ben Chan // If proc files are unuable, we continue to read the core file from stdin, 407ec7d7835a24884ed0e18317dc07af2fed2a50e64Ben Chan // but only skip the core-to-minidump conversion, so that we may still use 408ec7d7835a24884ed0e18317dc07af2fed2a50e64Ben Chan // the core file for debugging. 409ec7d7835a24884ed0e18317dc07af2fed2a50e64Ben Chan bool proc_files_usable = 410ec7d7835a24884ed0e18317dc07af2fed2a50e64Ben Chan CopyOffProcFiles(pid, container_dir) && ValidateProcFiles(container_dir); 411ec7d7835a24884ed0e18317dc07af2fed2a50e64Ben Chan 4126db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung // Switch back to the original UID/GID. 4136db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung gid_t rgid, egid, sgid; 4146db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung if (getresgid(&rgid, &egid, &sgid) != 0) { 4156db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung PLOG(FATAL) << "Unable to read saved gid"; 4166db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung } 4176db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung if (setresgid(sgid, sgid, -1) != 0) { 4186db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung PLOG(FATAL) << "Unable to set real group ID back to saved gid"; 4196db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung } else { 4206db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung if (getresgid(&rgid, &egid, &sgid) != 0) { 4216db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung // If the groups cannot be read at this point, the rgid variable will 4226db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung // contain the previously read group ID from before changing it. This 4236db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung // will cause the chown call below to set the incorrect group for 4246db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung // non-root crashes. But do not treat this as a fatal error, so that 4256db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung // the rest of the collection will continue for potential manual 4266db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung // collection by a developer. 4276db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung PLOG(ERROR) << "Unable to read real group ID after setting it"; 4286db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung } 4296db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung } 4306db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung 4316db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung uid_t ruid, euid, suid; 4326db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung if (getresuid(&ruid, &euid, &suid) != 0) { 4336db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung PLOG(FATAL) << "Unable to read saved uid"; 4346db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung } 4356db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung if (setresuid(suid, suid, -1) != 0) { 4366db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung PLOG(FATAL) << "Unable to set real user ID back to saved uid"; 4376db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung } else { 4386db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung if (getresuid(&ruid, &euid, &suid) != 0) { 4396db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung // If the user ID cannot be read at this point, the ruid variable will 4406db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung // contain the previously read user ID from before changing it. This 4416db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung // will cause the chown call below to set the incorrect user for 4426db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung // non-root crashes. But do not treat this as a fatal error, so that 4436db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung // the rest of the collection will continue for potential manual 4446db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung // collection by a developer. 4456db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung PLOG(ERROR) << "Unable to read real user ID after setting it"; 4466db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung } 4476db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung } 4486db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung 449ec7d7835a24884ed0e18317dc07af2fed2a50e64Ben Chan if (!CopyStdinToCoreFile(core_path)) { 4506e709a11031c80c96f47da50b3231074334f462cBen Chan return kErrorReadCoreData; 451777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter } 452777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter 453ec7d7835a24884ed0e18317dc07af2fed2a50e64Ben Chan if (!proc_files_usable) { 454ec7d7835a24884ed0e18317dc07af2fed2a50e64Ben Chan LOG(INFO) << "Skipped converting core file to minidump due to " 455ec7d7835a24884ed0e18317dc07af2fed2a50e64Ben Chan << "unusable proc files"; 4566e709a11031c80c96f47da50b3231074334f462cBen Chan return kErrorUnusableProcFiles; 457777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter } 458777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter 4596e709a11031c80c96f47da50b3231074334f462cBen Chan ErrorType error = ValidateCoreFile(core_path); 4606e709a11031c80c96f47da50b3231074334f462cBen Chan if (error != kErrorNone) { 4616e709a11031c80c96f47da50b3231074334f462cBen Chan return error; 4626e709a11031c80c96f47da50b3231074334f462cBen Chan } 463777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter 4646db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung // Chown the temp container directory back to the original user/group that 4656db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung // crash_reporter is run as, so that additional files can be written to 4666db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung // the temp folder. 4676db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung if (chown(container_dir.value().c_str(), ruid, rgid) < 0) { 4686db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung PLOG(ERROR) << "Could not set owner for " << container_dir.value(); 4696db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung } 4706db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung 4716e709a11031c80c96f47da50b3231074334f462cBen Chan if (!RunCoreToMinidump(core_path, 4726e709a11031c80c96f47da50b3231074334f462cBen Chan container_dir, // procfs directory 4736e709a11031c80c96f47da50b3231074334f462cBen Chan minidump_path, 4746e709a11031c80c96f47da50b3231074334f462cBen Chan container_dir)) { // temporary directory 4756e709a11031c80c96f47da50b3231074334f462cBen Chan return kErrorCore2MinidumpConversion; 476777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter } 477777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter 4786e709a11031c80c96f47da50b3231074334f462cBen Chan LOG(INFO) << "Stored minidump to " << minidump_path.value(); 4796e709a11031c80c96f47da50b3231074334f462cBen Chan return kErrorNone; 480207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter} 481ee849c5ef4c416cb0321483fa10c92f8aada3179Ken Mixter 4826e709a11031c80c96f47da50b3231074334f462cBen ChanUserCollector::ErrorType UserCollector::ConvertAndEnqueueCrash( 4831c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs pid_t pid, const std::string &exec, uid_t supplied_ruid, 4841c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs bool *out_of_capacity) { 485207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter FilePath crash_path; 4861c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs if (!GetCreatedCrashDirectory(pid, supplied_ruid, &crash_path, 4871c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs out_of_capacity)) { 488a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter LOG(ERROR) << "Unable to find/create process-specific crash path"; 4896e709a11031c80c96f47da50b3231074334f462cBen Chan return kErrorSystemIssue; 490777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter } 491777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter 492294d5d1eeed1634800e0a52fe1bcf7418ac5d958Ben Chan // Directory like /tmp/crash_reporter/1234 which contains the 493207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter // procfs entries and other temporary files used during conversion. 494ab2ac7d11442975f700bbde5702a96d020d82254Steve Fung FilePath container_dir(StringPrintf("%s/%d", kCoreTempFolder, pid)); 4951b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter // Delete a pre-existing directory from crash reporter that may have 4961b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter // been left around for diagnostics from a failed conversion attempt. 4971b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter // If we don't, existing files can cause forking to fail. 498a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger base::DeleteFile(container_dir, true); 499262d798b380a59ef691ede4c6a32aa71ff191295Ben Chan std::string dump_basename = FormatDumpBasename(exec, time(nullptr), pid); 500207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter FilePath core_path = GetCrashPath(crash_path, dump_basename, "core"); 501207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter FilePath meta_path = GetCrashPath(crash_path, dump_basename, "meta"); 502207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter FilePath minidump_path = GetCrashPath(crash_path, dump_basename, "dmp"); 503c49dbd4775986f32b2f09659595f9f28ef7f6b44Ken Mixter FilePath log_path = GetCrashPath(crash_path, dump_basename, "log"); 504c49dbd4775986f32b2f09659595f9f28ef7f6b44Ken Mixter 505acc7938ede0e3c07a2d1809f82b174b51f7ab7c5Simon Que if (GetLogContents(FilePath(log_config_path_), exec, log_path)) 506c49dbd4775986f32b2f09659595f9f28ef7f6b44Ken Mixter AddCrashMetaData("log", log_path.value()); 507207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter 50874dc62460b8cdd5bfeac47bfe8e759fc04b55ef8Alex Vakulenko brillo::OsReleaseReader reader; 509aa265b633b992a701e954fe39c780a90d377a42dSteve Fung reader.Load(); 51072e3c828dcc8230a1ae94f0f814891d54b7c0b92Steve Fung std::string value = "undefined"; 51172e3c828dcc8230a1ae94f0f814891d54b7c0b92Steve Fung if (!reader.GetString(kBdkVersionKey, &value)) { 512aa265b633b992a701e954fe39c780a90d377a42dSteve Fung LOG(ERROR) << "Could not read " << kBdkVersionKey 513aa265b633b992a701e954fe39c780a90d377a42dSteve Fung << " from /etc/os-release.d/"; 514aa265b633b992a701e954fe39c780a90d377a42dSteve Fung } 51572e3c828dcc8230a1ae94f0f814891d54b7c0b92Steve Fung AddCrashMetaData(kBdkVersionKey, value); 51672e3c828dcc8230a1ae94f0f814891d54b7c0b92Steve Fung 51772e3c828dcc8230a1ae94f0f814891d54b7c0b92Steve Fung value = "undefined"; 51872e3c828dcc8230a1ae94f0f814891d54b7c0b92Steve Fung if (!reader.GetString(kProductIDKey, &value)) { 51972e3c828dcc8230a1ae94f0f814891d54b7c0b92Steve Fung LOG(ERROR) << "Could not read " << kProductIDKey 52072e3c828dcc8230a1ae94f0f814891d54b7c0b92Steve Fung << " from /etc/os-release.d/"; 52172e3c828dcc8230a1ae94f0f814891d54b7c0b92Steve Fung } 52272e3c828dcc8230a1ae94f0f814891d54b7c0b92Steve Fung AddCrashMetaData(kProductIDKey, value); 52372e3c828dcc8230a1ae94f0f814891d54b7c0b92Steve Fung 52472e3c828dcc8230a1ae94f0f814891d54b7c0b92Steve Fung value = "undefined"; 52572e3c828dcc8230a1ae94f0f814891d54b7c0b92Steve Fung if (!reader.GetString(kProductVersionKey, &value)) { 52672e3c828dcc8230a1ae94f0f814891d54b7c0b92Steve Fung LOG(ERROR) << "Could not read " << kProductVersionKey 52772e3c828dcc8230a1ae94f0f814891d54b7c0b92Steve Fung << " from /etc/os-release.d/"; 52872e3c828dcc8230a1ae94f0f814891d54b7c0b92Steve Fung } 52972e3c828dcc8230a1ae94f0f814891d54b7c0b92Steve Fung AddCrashMetaData(kProductVersionKey, value); 530aa265b633b992a701e954fe39c780a90d377a42dSteve Fung 5316e709a11031c80c96f47da50b3231074334f462cBen Chan ErrorType error_type = 5326e709a11031c80c96f47da50b3231074334f462cBen Chan ConvertCoreToMinidump(pid, container_dir, core_path, minidump_path); 5336e709a11031c80c96f47da50b3231074334f462cBen Chan if (error_type != kErrorNone) { 534a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter LOG(INFO) << "Leaving core file at " << core_path.value() 535a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter << " due to conversion error"; 5366e709a11031c80c96f47da50b3231074334f462cBen Chan return error_type; 537207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter } 538207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter 539207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter // Here we commit to sending this file. We must not return false 540207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter // after this point or we will generate a log report as well as a 541207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter // crash report. 542207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter WriteCrashMetaData(meta_path, 543207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter exec, 544207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter minidump_path.value()); 545207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter 546538ecbf7d5f4011440c45b27e84902f5953b1f82Michael Krebs if (!IsDeveloperImage()) { 547a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger base::DeleteFile(core_path, false); 548777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter } else { 549a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter LOG(INFO) << "Leaving core file at " << core_path.value() 550a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter << " due to developer image"; 551777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter } 552777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter 553a557c1187ff19d422db2a9c951ecd8f7243e79bdMike Frysinger base::DeleteFile(container_dir, true); 5546e709a11031c80c96f47da50b3231074334f462cBen Chan return kErrorNone; 555777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter} 556777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter 5571b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixterbool UserCollector::ParseCrashAttributes(const std::string &crash_attributes, 5581c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs pid_t *pid, int *signal, uid_t *uid, 559773fd3c42883b17b5918c71aead5690e16438248Steve Fung gid_t *gid, 5601b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter std::string *kernel_supplied_name) { 561773fd3c42883b17b5918c71aead5690e16438248Steve Fung pcrecpp::RE re("(\\d+):(\\d+):(\\d+):(\\d+):(.*)"); 562773fd3c42883b17b5918c71aead5690e16438248Steve Fung if (re.FullMatch(crash_attributes, pid, signal, uid, gid, 563773fd3c42883b17b5918c71aead5690e16438248Steve Fung kernel_supplied_name)) 5641c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs return true; 5651c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs 5661c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs LOG(INFO) << "Falling back to parsing crash attributes '" 567773fd3c42883b17b5918c71aead5690e16438248Steve Fung << crash_attributes << "' without UID and GID"; 5681c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs pcrecpp::RE re_without_uid("(\\d+):(\\d+):(.*)"); 5691c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs *uid = kUnknownUid; 570773fd3c42883b17b5918c71aead5690e16438248Steve Fung *gid = kUnknownGid; 5711c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs return re_without_uid.FullMatch(crash_attributes, pid, signal, 5721c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs kernel_supplied_name); 5731b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter} 5741b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter 5755d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixterbool UserCollector::ShouldDump(bool has_owner_consent, 5765d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter bool is_developer, 5775d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter std::string *reason) { 5785d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter reason->clear(); 5795d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter 5805d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter // For developer builds, we always want to keep the crash reports unless 5815d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter // we're testing the crash facilities themselves. This overrides 5825d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter // feedback. Crash sending still obeys consent. 583538ecbf7d5f4011440c45b27e84902f5953b1f82Michael Krebs if (is_developer) { 5845d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter *reason = "developer build - not testing - always dumping"; 5855d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter return true; 5865d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter } 5875d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter 5885d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter if (!has_owner_consent) { 5895d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter *reason = "ignoring - no consent"; 5905d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter return false; 5915d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter } 5925d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter 5935d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter *reason = "handling"; 5945d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter return true; 5955d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter} 5965d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter 5971b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixterbool UserCollector::HandleCrash(const std::string &crash_attributes, 5981b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter const char *force_exec) { 599e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa CHECK(initialized_); 6001c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs pid_t pid = 0; 6011b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter int signal = 0; 6021c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs uid_t supplied_ruid = kUnknownUid; 603773fd3c42883b17b5918c71aead5690e16438248Steve Fung gid_t supplied_rgid = kUnknownGid; 6041b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter std::string kernel_supplied_name; 6051b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter 6061c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs if (!ParseCrashAttributes(crash_attributes, &pid, &signal, &supplied_ruid, 607773fd3c42883b17b5918c71aead5690e16438248Steve Fung &supplied_rgid, &kernel_supplied_name)) { 608a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter LOG(ERROR) << "Invalid parameter: --user=" << crash_attributes; 6091b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter return false; 6101b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter } 6111b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter 6126db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung // Switch to the group and user that ran the crashing binary in order to 6136db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung // access their /proc files. Do not set suid/sgid, so that we can switch 6146db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung // back after copying the necessary files. 615773fd3c42883b17b5918c71aead5690e16438248Steve Fung if (setresgid(supplied_rgid, supplied_rgid, -1) != 0) { 6166db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung PLOG(FATAL) << "Unable to set real group ID to access process files"; 6176db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung } 6186db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung if (setresuid(supplied_ruid, supplied_ruid, -1) != 0) { 6196db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung PLOG(FATAL) << "Unable to set real user ID to access process files"; 6206db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung } 6216db7cd78364b168f8b78170937b3ddf239c89a86Steve Fung 622777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter std::string exec; 623777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter if (force_exec) { 624777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter exec.assign(force_exec); 625777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter } else if (!GetExecutableBaseNameFromPid(pid, &exec)) { 6261b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter // If we cannot find the exec name, use the kernel supplied name. 6271b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter // We don't always use the kernel's since it truncates the name to 6281b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter // 16 characters. 6291b8fe015585c0b966d5240b8e22eba1af8c69e88Ken Mixter exec = StringPrintf("supplied_%s", kernel_supplied_name.c_str()); 630777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter } 631c6a58e0f73a2e21941bbcba863eb78bc1c1ae0fbKen Mixter 632c6a58e0f73a2e21941bbcba863eb78bc1c1ae0fbKen Mixter // Allow us to test the crash reporting mechanism successfully even if 633c6a58e0f73a2e21941bbcba863eb78bc1c1ae0fbKen Mixter // other parts of the system crash. 634d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung if (!filter_in_.empty() && 635d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung (filter_in_ == "none" || 636d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung filter_in_ != exec)) { 637c6a58e0f73a2e21941bbcba863eb78bc1c1ae0fbKen Mixter // We use a different format message to make it more obvious in tests 638c6a58e0f73a2e21941bbcba863eb78bc1c1ae0fbKen Mixter // which crashes are test generated and which are real. 639a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter LOG(WARNING) << "Ignoring crash from " << exec << "[" << pid << "] while " 640d6169a2a4f775da37ffa8b8ba4d767efd0377343Steve Fung << "filter_in=" << filter_in_ << "."; 641c6a58e0f73a2e21941bbcba863eb78bc1c1ae0fbKen Mixter return true; 642c6a58e0f73a2e21941bbcba863eb78bc1c1ae0fbKen Mixter } 643c6a58e0f73a2e21941bbcba863eb78bc1c1ae0fbKen Mixter 6445d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter std::string reason; 6455d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter bool dump = ShouldDump(is_feedback_allowed_function_(), 646538ecbf7d5f4011440c45b27e84902f5953b1f82Michael Krebs IsDeveloperImage(), 6475d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter &reason); 6482105b49796f2b753b44ccc792fd387dd0dddf54fKen Mixter 649a324932e066ccb7ed9d62db9c409ee2c10052554Ken Mixter LOG(WARNING) << "Received crash notification for " << exec << "[" << pid 6501c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs << "] sig " << signal << ", user " << supplied_ruid 6511c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs << " (" << reason << ")"; 6521652fb2cc2bc6d08ac3719fd3d90b43485d539feThieu Le 6535d3a1a2c3543db21913f67cf240bad6c137063c9Ken Mixter if (dump) { 654e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa count_crash_function_(); 655777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter 6560340316050044e0995b98fea87ed41ea77abb28bKen Mixter if (generate_diagnostics_) { 657207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter bool out_of_capacity = false; 6586e709a11031c80c96f47da50b3231074334f462cBen Chan ErrorType error_type = 6591c57e9e330bc4c6a44955fd649ee9a4badb9e1dcMichael Krebs ConvertAndEnqueueCrash(pid, exec, supplied_ruid, &out_of_capacity); 6606e709a11031c80c96f47da50b3231074334f462cBen Chan if (error_type != kErrorNone) { 661207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter if (!out_of_capacity) 6626e709a11031c80c96f47da50b3231074334f462cBen Chan EnqueueCollectionErrorLog(pid, error_type, exec); 663207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter return false; 664207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter } 6650340316050044e0995b98fea87ed41ea77abb28bKen Mixter } 666777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter } 667207694d3f491ef602a859c30cc1379584f2d61cfKen Mixter 668777484c41cc63e2f97f41a443d1d55f7e6037a5eKen Mixter return true; 669e4a86037f405415c460ace194fbf16cfd93d4c6Chris Sosa} 670