// Copyright 2016 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/user_collector_base.h"

#include <pcrecpp.h>
#include "crash-reporter/vm_support.h"

#if USE_DIRENCRYPTION
#include <keyutils.h>
#endif  // USE_DIRENCRYPTION

#include <base/files/file_util.h>
#include <base/strings/string_split.h>
#include <base/strings/stringprintf.h>
#include <brillo/process.h>

#include "crash-reporter/util.h"

using base::FilePath;
using base::ReadFileToString;
using base::StringPrintf;

namespace {

const char kStatePrefix[] = "State:\t";
const char kUptimeField[] = "ptime";
const char kUserCrashSignal[] = "org.chromium.CrashReporter.UserCrash";

#if USE_DIRENCRYPTION
// Name of the session keyring.
const char kDircrypt[] = "dircrypt";
#endif  // USE_DIRENCRYPTION

void AccounceUserCrash() {
  brillo::ProcessImpl dbus;
  dbus.AddArg("/usr/bin/dbus-send");
  dbus.AddArg("--type=signal");
  dbus.AddArg("--system");
  dbus.AddArg("/");
  dbus.AddArg(kUserCrashSignal);
  // Announce through D-Bus whenever a user crash happens. This is
  // used by the metrics daemon to log active use time between
  // crashes.
  //
  // This could be done more efficiently by explicit fork/exec or
  // using a dbus library directly. However, this should run
  // relatively rarely and longer term we may need to implement a
  // better way to do this that doesn't rely on D-Bus.
  LOG_IF(WARNING, !dbus.Start()) << "dbus-send running failed";

  // We run in the background in case dbus daemon itself is crashed
  // and not responding.  This allows us to not block and potentially
  // deadlock on a dbus-daemon crash.  If dbus-daemon crashes without
  // restarting, each crash will fork off a lot of dbus-send
  // processes.  Such a system is in a unusable state and will need
  // to be restarted anyway.
  dbus.Release();
}

}  // namespace

const char* UserCollectorBase::kUserId = "Uid:\t";
const char* UserCollectorBase::kGroupId = "Gid:\t";

UserCollectorBase::UserCollectorBase(
    const std::string& collector_name,
    CrashDirectorySelectionMethod crash_directory_selection_method)
    : CrashCollector(collector_name,
                     crash_directory_selection_method,
                     kNormalCrashSendMode,
                     collector_name) {}

void UserCollectorBase::Initialize(
    IsFeedbackAllowedFunction is_feedback_allowed_function,
    bool generate_diagnostics,
    bool directory_failure,
    const std::string& filter_in,
    bool early) {
  CrashCollector::Initialize(is_feedback_allowed_function, early);
  initialized_ = true;
  generate_diagnostics_ = generate_diagnostics;
  directory_failure_ = directory_failure;
  filter_in_ = filter_in;
}

bool UserCollectorBase::HandleCrash(const std::string& crash_attributes,
                                    const char* force_exec) {
  CHECK(initialized_);

  base::TimeDelta crash_time;
  GetUptime(&crash_time);

  pid_t pid;
  int signal;
  uid_t supplied_ruid;
  gid_t supplied_rgid;
  std::string kernel_supplied_name;

  if (!ParseCrashAttributes(crash_attributes, &pid, &signal, &supplied_ruid,
                            &supplied_rgid, &kernel_supplied_name)) {
    LOG(ERROR) << "Invalid parameter: --user=" << crash_attributes;
    return false;
  }

  std::string exec;
  if (force_exec) {
    exec.assign(force_exec);
  } else if (!GetExecutableBaseNameFromPid(pid, &exec)) {
    // If we cannot find the exec name, use the kernel supplied name.
    // We don't always use the kernel's since it truncates the name to
    // 16 characters.
    exec = StringPrintf("supplied_%s", kernel_supplied_name.c_str());
  }

  // Allow us to test the crash reporting mechanism successfully even if
  // other parts of the system crash.
  if (!filter_in_.empty() && (filter_in_ == "none" || filter_in_ != exec)) {
    // We use a different format message to make it more obvious in tests
    // which crashes are test generated and which are real.
    LOG(WARNING) << "Ignoring crash from " << exec << "[" << pid << "] while "
                 << "filter_in=" << filter_in_ << ".";
    return true;
  }

  std::string reason;
  bool dump = ShouldDump(pid, supplied_ruid, exec, &reason);

  // anomaly_detector's CrashReporterParser looks for this message; don't change
  // it without updating the regex.
  const auto message = StringPrintf(
      "Received crash notification for %s[%d] sig %d, user %u group %u",
      exec.c_str(), pid, signal, supplied_ruid, supplied_rgid);

  // TODO(crbug.com/1053847) The executable name is sensitive user data inside
  // the VM, so don't log this message. Eventually we will move the VM logs
  // inside the cryptohome and this will be unnecessary.
  if (!VmSupport::Get()) {
    LogCrash(message, reason);
  }

  if (dump) {
    AccounceUserCrash();

    AddExtraMetadata(exec, pid);

    if (generate_diagnostics_) {
      bool out_of_capacity = false;
      ErrorType error_type =
          ConvertAndEnqueueCrash(pid, exec, supplied_ruid, supplied_rgid,
                                 crash_time, &out_of_capacity);
      if (error_type != kErrorNone) {
        if (!out_of_capacity) {
          const std::string basename =
              FormatDumpBasename(exec, time(nullptr), pid);
          EnqueueCollectionErrorLog(error_type, exec, basename);
        }
        return false;
      }
    }
  }

  return true;
}

bool UserCollectorBase::ParseCrashAttributes(
    const std::string& crash_attributes,
    pid_t* pid,
    int* signal,
    uid_t* uid,
    gid_t* gid,
    std::string* exec_name) {
  pcrecpp::RE re("(\\d+):(\\d+):(\\d+):(\\d+):(.*)");
  return re.FullMatch(crash_attributes, pid, signal, uid, gid, exec_name);
}

bool UserCollectorBase::ShouldDump(base::Optional<pid_t> pid,
                                   bool has_owner_consent,
                                   bool is_developer,
                                   std::string* reason) const {
  // For developer builds, we always want to keep the crash reports unless
  // we're testing the crash facilities themselves.  This overrides
  // feedback.  Crash sending still obeys consent.
  if (is_developer) {
    *reason = "developer build - not testing - always dumping";
    return true;
  }

  if (!has_owner_consent) {
    *reason = "ignoring - no consent";
    return false;
  }

  VmSupport* vm_support = VmSupport::Get();
  if (vm_support) {
    if (!pid.has_value()) {
      *reason = "ignoring - unknown PID inside VM";
      return false;
    }

    if (!vm_support->ShouldDump(*pid, reason)) {
      return false;
    }
  }

  *reason = "handling";
  return true;
}

bool UserCollectorBase::ShouldDump(bool has_owner_consent,
                                   bool is_developer,
                                   std::string* reason) const {
  return ShouldDump(base::nullopt, has_owner_consent, is_developer, reason);
}

bool UserCollectorBase::GetFirstLineWithPrefix(
    const std::vector<std::string>& lines,
    const char* prefix,
    std::string* line) {
  for (const auto& current_line : lines) {
    if (current_line.find(prefix) == 0) {
      *line = current_line;
      return true;
    }
  }
  return false;
}

bool UserCollectorBase::GetIdFromStatus(
    const char* prefix,
    IdKind kind,
    const std::vector<std::string>& status_lines,
    int* id) {
  // From fs/proc/array.c:task_state(), this file contains:
  // \nUid:\t<uid>\t<euid>\t<suid>\t<fsuid>\n
  std::string id_line;
  if (!GetFirstLineWithPrefix(status_lines, prefix, &id_line)) {
    return false;
  }
  std::string id_substring = id_line.substr(strlen(prefix), std::string::npos);
  std::vector<std::string> ids = base::SplitString(
      id_substring, "\t", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
  if (ids.size() != kIdMax || kind < 0 || kind >= kIdMax) {
    return false;
  }
  const char* number = ids[kind].c_str();
  char* end_number = nullptr;
  *id = strtol(number, &end_number, 10);
  if (*end_number != '\0') {
    return false;
  }
  return true;
}

bool UserCollectorBase::GetStateFromStatus(
    const std::vector<std::string>& status_lines, std::string* state) {
  std::string state_line;
  if (!GetFirstLineWithPrefix(status_lines, kStatePrefix, &state_line)) {
    return false;
  }
  *state = state_line.substr(strlen(kStatePrefix), std::string::npos);
  return true;
}

bool UserCollectorBase::ClobberContainerDirectory(
    const base::FilePath& container_dir) {
  // Delete a pre-existing directory from crash reporter that may have
  // been left around for diagnostics from a failed conversion attempt.
  // If we don't, existing files can cause forking to fail.
  if (!base::DeleteFile(container_dir, true)) {
    PLOG(ERROR) << "Could not delete " << container_dir.value();
    return false;
  }

  if (!base::CreateDirectory(container_dir)) {
    PLOG(ERROR) << "Could not create " << container_dir.value();
    return false;
  }

  return true;
}

const FilePath UserCollectorBase::GetCrashProcessingDir() {
  return FilePath("/tmp/crash_reporter");
}

UserCollectorBase::ErrorType UserCollectorBase::ConvertAndEnqueueCrash(
    pid_t pid,
    const std::string& exec,
    uid_t supplied_ruid,
    gid_t supplied_rgid,
    const base::TimeDelta& crash_time,
    bool* out_of_capacity) {
  FilePath crash_path;
  if (!GetCreatedCrashDirectory(pid, supplied_ruid, &crash_path,
                                out_of_capacity)) {
    LOG(ERROR) << "Unable to find/create process-specific crash path";
    return kErrorSystemIssue;
  }

  // Directory like /tmp/crash_reporter/1234 which contains the
  // procfs entries and other temporary files used during conversion.
  const FilePath container_dir =
      GetCrashProcessingDir().Append(StringPrintf("%d", pid));
  if (!ClobberContainerDirectory(container_dir))
    return kErrorSystemIssue;

  std::string dump_basename = FormatDumpBasename(exec, time(nullptr), pid);
  FilePath core_path = GetCrashPath(crash_path, dump_basename, "core");
  FilePath meta_path = GetCrashPath(crash_path, dump_basename, "meta");
  FilePath minidump_path = GetCrashPath(crash_path, dump_basename, "dmp");
  FilePath log_path = GetCrashPath(crash_path, dump_basename, "log");
  FilePath proc_log_path = GetCrashPath(crash_path, dump_basename, "proclog");

  if (GetLogContents(FilePath(log_config_path_), exec, log_path)) {
    AddCrashMetaUploadFile("log", log_path.BaseName().value());
  }

  if (GetProcessTree(pid, proc_log_path)) {
    AddCrashMetaUploadFile("process_tree", proc_log_path.BaseName().value());
  }

#if USE_DIRENCRYPTION
  // Join the session keyring, if one exists.
  JoinSessionKeyring();
#endif  // USE_DIRENCRYPTION

  ErrorType error_type =
      ConvertCoreToMinidump(pid, container_dir, core_path, minidump_path);
  if (error_type != kErrorNone) {
    if (error_type != kErrorReadCoreData)
      LOG(INFO) << "Leaving core file at " << core_path.value()
                << " due to conversion error";
    return error_type;
  } else {
    base::FilePath target;
    if (!NormalizeFilePath(minidump_path, &target))
      target = minidump_path;

    // TODO(crbug.com/1053847) The executable name is sensitive user data inside
    // the VM, so don't log this message. Eventually we will move the VM logs
    // inside the cryptohome and this will be unnecessary.
    if (!VmSupport::Get()) {
      LOG(INFO) << "Stored minidump to " << target.value();
    }
  }

  base::TimeDelta start_time;
  if (GetUptimeAtProcessStart(pid, &start_time) && crash_time > start_time) {
    const base::TimeDelta uptime = crash_time - start_time;
    AddCrashMetaUploadData(kUptimeField,
                           std::to_string(uptime.InMilliseconds()));
  } else {
    LOG(WARNING) << "Failed to get process uptime.";
  }

  // Here we commit to sending this file.  We must not return false
  // after this point or we will generate a log report as well as a
  // crash report.
  FinishCrash(meta_path, exec, minidump_path.BaseName().value());

  if (!util::IsDeveloperImage()) {
    base::DeleteFile(core_path, false);
  } else {
    LOG(INFO) << "Leaving core file at " << core_path.value()
              << " due to developer image";
  }

  base::DeleteFile(container_dir, true);
  return kErrorNone;
}

bool UserCollectorBase::GetCreatedCrashDirectory(pid_t pid,
                                                 uid_t supplied_ruid,
                                                 FilePath* crash_file_path,
                                                 bool* out_of_capacity) {
  FilePath process_path = GetProcessPath(pid);
  std::string status;
  if (directory_failure_) {
    LOG(ERROR) << "Purposefully failing to create spool directory";
    return false;
  }

  uid_t uid;
  if (base::ReadFileToString(process_path.Append("status"), &status)) {
    std::vector<std::string> status_lines = base::SplitString(
        status, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);

    std::string process_state;
    if (!GetStateFromStatus(status_lines, &process_state)) {
      LOG(ERROR) << "Could not find process state in status file";
      return false;
    }
    LOG(INFO) << "State of crashed process [" << pid << "]: " << process_state;

    // Get effective UID of crashing process.
    int id;
    if (!GetIdFromStatus(kUserId, kIdEffective, status_lines, &id)) {
      LOG(ERROR) << "Could not find euid in status file";
      return false;
    }
    uid = id;
  } else {
    LOG(INFO) << "Using supplied UID " << supplied_ruid
              << " for crashed process [" << pid
              << "] due to error reading status file";
    uid = supplied_ruid;
  }

  if (!GetCreatedCrashDirectoryByEuid(uid, crash_file_path, out_of_capacity)) {
    LOG(ERROR) << "Could not create crash directory";
    return false;
  }
  return true;
}

std::vector<std::string> UserCollectorBase::GetCommandLine(pid_t pid) const {
  const FilePath path = GetProcessPath(pid).Append("cmdline");
  // The /proc/[pid]/cmdline file contains the command line separated and
  // terminated by a null byte, e.g. "command\0arg\0arg\0". The file is
  // empty if the process is a zombie.
  std::string cmdline;
  if (!ReadFileToString(path, &cmdline)) {
    PLOG(ERROR) << "Could not read " << path.value();
    return std::vector<std::string>();
  }

  if (cmdline.empty()) {
    LOG(ERROR) << "Empty cmdline for " << path.value();
    return std::vector<std::string>();
  }

  // Split the string by null bytes.
  return base::SplitString(cmdline, std::string(1, '\0'), base::KEEP_WHITESPACE,
                           base::SPLIT_WANT_ALL);
}

#if USE_DIRENCRYPTION
void UserCollectorBase::JoinSessionKeyring() {
  key_serial_t session_keyring = keyctl_join_session_keyring(kDircrypt);
  if (session_keyring == -1) {
    // The session keyring may not exist if ext4 encryption isn't enabled so
    // just log an info message instead of an error.
    PLOG(INFO) << "Unable to join session keying";
  }
}
#endif  // USE_DIRENCRYPTION
