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