blob: 50783a0b82d20df5577dc6b37edb9982d4a58646 [file] [log] [blame]
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "crash-reporter/mount_failure_collector.h"
#include <string>
#include <vector>
#include <base/files/file_enumerator.h>
#include <base/files/file_util.h>
#include "crash-reporter/paths.h"
#include "crash-reporter/util.h"
namespace {
const char kEncryptedStatefulDeviceLabel[] = "encstateful";
const char kStatefulDeviceLabel[] = "stateful";
const char kInvalidDeviceLabel[] = "invalid";
std::vector<std::string> ConstructLoggingCommands(StorageDeviceType device_type,
bool is_mount_failure) {
std::vector<std::string> cmds;
if (is_mount_failure) {
// Common logging for mount failure cases:
// - dumpe2fs.
// - dmesg for current run.
// - ramoops, if any.
cmds = {"dumpe2fs_" +
MountFailureCollector::StorageDeviceTypeToString(device_type),
"kernel-warning", "console-ramoops"};
// For encrypted stateful mount failure, add logs from mount-encrypted.
if (device_type == StorageDeviceType::kEncryptedStateful)
cmds.push_back("mount-encrypted");
} else {
cmds = {"shutdown_umount_failure_state", "umount-encrypted"};
}
return cmds;
}
} // namespace
MountFailureCollector::MountFailureCollector(StorageDeviceType device_type)
: CrashCollector("mount_failure_collector"), device_type_(device_type) {}
// static
StorageDeviceType MountFailureCollector::ValidateStorageDeviceType(
const std::string& device_label) {
if (device_label == kStatefulDeviceLabel)
return StorageDeviceType::kStateful;
else if (device_label == kEncryptedStatefulDeviceLabel)
return StorageDeviceType::kEncryptedStateful;
else
return StorageDeviceType::kInvalidDevice;
}
// static
std::string MountFailureCollector::StorageDeviceTypeToString(
StorageDeviceType device_type) {
switch (device_type) {
case StorageDeviceType::kStateful:
return kStatefulDeviceLabel;
case StorageDeviceType::kEncryptedStateful:
return kEncryptedStatefulDeviceLabel;
default:
return kInvalidDeviceLabel;
}
}
bool MountFailureCollector::Collect(bool is_mount_failure) {
if (!is_feedback_allowed_function_()) {
LOG(INFO) << "Not collecting clobber report; no user consent";
return true;
}
if (device_type_ == StorageDeviceType::kInvalidDevice) {
LOG(ERROR) << "Invalid storage device.";
return true;
}
std::string device_label = StorageDeviceTypeToString(device_type_);
std::string exec_name = (is_mount_failure ? "mount" : "umount");
exec_name += "_failure_" + device_label;
std::string dump_basename = FormatDumpBasename(exec_name, time(nullptr), 0);
auto logging_cmds = ConstructLoggingCommands(device_type_, is_mount_failure);
base::FilePath crash_directory;
if (!GetCreatedCrashDirectoryByEuid(kRootUid, &crash_directory, nullptr)) {
return true;
}
// Use exec name as the crash signature.
AddCrashMetaData("sig", exec_name);
base::FilePath log_path = GetCrashPath(crash_directory, dump_basename, "log");
base::FilePath meta_path =
GetCrashPath(crash_directory, dump_basename, "meta");
bool result =
GetMultipleLogContents(log_config_path_, logging_cmds, log_path);
if (result) {
FinishCrash(meta_path, exec_name, log_path.BaseName().value());
}
return true;
}