// Copyright (c) 2012 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/kernel_warning_collector.h"

#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/strcat.h>
#include <base/strings/stringprintf.h>
#include <re2/re2.h>

#include "crash-reporter/util.h"

namespace {
const char kGenericWarningExecName[] = "kernel-warning";
const char kWifiWarningExecName[] = "kernel-wifi-warning";
const char kSMMUFaultExecName[] = "kernel-smmu-fault";
const char kSuspendWarningExecName[] = "kernel-suspend-warning";
const char kKernelIwlwifiErrorExecName[] = "kernel-iwlwifi-error";
const char kKernelAth10kErrorExecName[] = "kernel-ath10k-error";
const char kKernelWarningSignatureKey[] = "sig";
const pid_t kKernelPid = 0;
}  // namespace

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

KernelWarningCollector::KernelWarningCollector()
    : CrashCollector("kernel_warning"), warning_report_path_("/dev/stdin") {}

KernelWarningCollector::~KernelWarningCollector() {}

bool KernelWarningCollector::LoadKernelWarning(std::string* content,
                                               std::string* signature,
                                               std::string* func_name,
                                               WarningType type) {
  FilePath kernel_warning_path(warning_report_path_.c_str());
  if (!base::ReadFileToString(kernel_warning_path, content)) {
    PLOG(ERROR) << "Could not open " << kernel_warning_path.value();
    return false;
  }

  if (type == kIwlwifi) {
    if (!ExtractIwlwifiSignature(*content, signature, func_name)) {
      return false;
    } else if (signature->length() > 0) {
      return true;
    }
  } else if (type == kSMMUFault) {
    if (!ExtractSMMUFaultSignature(*content, signature, func_name)) {
      return false;
    } else if (signature->length() > 0) {
      return true;
    }
  } else if (type == kAth10k) {
    if (!ExtractAth10kSignature(*content, signature, func_name)) {
      return false;
    } else if (signature->length() > 0) {
      return true;
    }
  } else {
    if (!ExtractSignature(*content, signature, func_name)) {
      return false;
    } else if (signature->length() > 0) {
      return true;
    }
  }

  LOG(WARNING) << "Couldn't find match for signature line. "
               << "Falling back to first line of warning.";
  *signature = content->substr(0, content->find('\n'));
  return true;
}

// Extract the crashing function name from the signature.
// Signature example: 6a839c19-lkdtm_do_action+0x225/0x5bc
// Signature example2: 6a839c19-unknown-function+0x161/0x344 [iwlmvm]
constexpr LazyRE2 sig_re = {R"(^[0-9a-fA-F]+-([0-9a-zA-Z_-]+)\+.*$)"};

bool KernelWarningCollector::ExtractSignature(const std::string& content,
                                              std::string* signature,
                                              std::string* func_name) {
  // The signature is in the first or second line.
  // First, try the first, and if it's not there, try the second.
  std::string::size_type end_position = content.find('\n');
  if (end_position == std::string::npos) {
    LOG(ERROR) << "unexpected kernel warning format";
    return false;
  }
  size_t start = 0;
  for (int i = 0; i < 2; i++) {
    *signature = content.substr(start, end_position - start);

    if (RE2::FullMatch(*signature, *sig_re, func_name)) {
      return true;
    } else {
      LOG(INFO) << *signature << " does not match regex";
      signature->clear();
      func_name->clear();
    }

    // Else, try the next line.
    start = end_position + 1;
    end_position = content.find('\n', start);
  }

  return true;
}

// Extract the crashing function name from the signature.
// The crashing function for the lmac appears after the line:
// Loaded firmware version: 46.b20aefee.0
// Signature example: 0x00000084 | NMI_INTERRUPT_UNKNOWN
// The crashing function for the umac appears after the line:
// iwlwifi 0000:00:0c.0: Status: 0x00000100, count: 7
// Signature example: 0x20000066 | NMI_INTERRUPT_HOST
constexpr LazyRE2 before_iwlwifi_assert_lmac = {
    R"(iwlwifi (?:.+): Loaded firmware version:)"};
constexpr LazyRE2 before_iwlwifi_assert_umac = {R"(iwlwifi (?:.+): Status:)"};
constexpr LazyRE2 iwlwifi_sig_re = {
    R"((iwlwifi (?:.+): \b(\w+)\b \| \b(\w+)\b))"};

enum class LineType {
  Umac,
  Lmac,
  None,
  CheckUmac,
};

bool KernelWarningCollector::ExtractIwlwifiSignature(const std::string& content,
                                                     std::string* signature,
                                                     std::string* func_name) {
  LineType last_line = LineType::None;
  // Extracting the function name depends on where the assert occurs in
  // lmac/umac:
  // 1- Assert in lmac:
  //       The umac have the default assert value in its signature
  //       (0x20000070).
  // 2- Assert in umac:
  //       The lmac have the default assert value in its signature
  //       (0x00000071).
  // Based on that, the function name in lmac/umac should be ignored if the
  // assert number in the signature is equal to 0x00000071 in lmac or 0x20000070
  // in umac.
  const std::string default_lmac_assert = "0x00000071";
  const std::string default_umac_assert = "0x20000070";
  // The signature is reported as unknown in the case of parsing error.
  const std::string unknown_iwlwifi_signature = "iwlwifi unknown signature";
  std::string assert_number;
  std::string iwlwifi_signature;
  std::string::size_type end_position = content.find('\n');
  if (end_position == std::string::npos) {
    LOG(ERROR) << "unexpected kernel iwlwifi error format";
    return false;
  }

  // Look for the signature in the lmac and check the assert number. if the lmac
  // assert number not equal (0x00000071), then return that as the signature.
  // Otherwise, check the signature of the umac. if the umac assert number not
  // equal (0x20000070), then return that as the signature. Otherwise, break.
  size_t start = 0;
  size_t end = content.size();
  while (start < end && end_position != std::string::npos) {
    *signature = content.substr(start, end_position - start);

    if (last_line == LineType::None) {
      if (RE2::PartialMatch(*signature, *before_iwlwifi_assert_lmac)) {
        last_line = LineType::Lmac;
      }
    } else if (last_line == LineType::Lmac) {
      // Check the signature of the lmac.
      if (RE2::PartialMatch(*signature, *iwlwifi_sig_re, &iwlwifi_signature,
                            &assert_number, func_name)) {
        if (default_lmac_assert != assert_number) {
          *signature = iwlwifi_signature;
          return true;
        } else {
          // Check umac if the lmac assertion number == default_lmac_assert.
          last_line = LineType::CheckUmac;
          signature->clear();
          func_name->clear();
        }
      } else {
        // Break if the signature of the lmac didn't match.
        LOG(INFO) << *signature << " does not match lmac regex";
        *signature = unknown_iwlwifi_signature;
        func_name->clear();
        break;
      }
    } else if (last_line == LineType::CheckUmac) {
      // Check the line before the umac signature.
      if (RE2::PartialMatch(*signature, *before_iwlwifi_assert_umac)) {
        last_line = LineType::Umac;
      }
    } else if (last_line == LineType::Umac) {
      // Check the signature of the umac.
      if (RE2::PartialMatch(*signature, *iwlwifi_sig_re, &iwlwifi_signature,
                            &assert_number, func_name)) {
        if (default_umac_assert != assert_number) {
          *signature = iwlwifi_signature;
          return true;
        } else {
          // Break if the umac assertion number == default_umac_assert.
          LOG(ERROR) << "unexpected kernel iwlwifi error format. "
                        "Both umac/lmac dumps have the default assert numbers.";
          *signature = unknown_iwlwifi_signature;
          func_name->clear();
          break;
        }
      } else {
        // Break if the signature of the umac didn't match.
        LOG(INFO) << *signature << " does not match umac regex";
        *signature = unknown_iwlwifi_signature;
        func_name->clear();
        break;
      }
    }

    // Else, try the next line.
    start = end_position + 1;
    end_position = content.find('\n', start);
  }

  return true;
}

constexpr LazyRE2 smmu_sig_re = {R"((\S+): Unhandled context fault: (.*))"};

bool KernelWarningCollector::ExtractSMMUFaultSignature(
    const std::string& content,
    std::string* signature,
    std::string* func_name) {
  // The signature is the part of the line after "Unhandled context fault:"
  std::string line;
  std::string::size_type end_position = content.find('\n');
  if (end_position == std::string::npos) {
    LOG(ERROR) << "unexpected smmu fault warning format";
    return false;
  }

  line = content.substr(0, end_position);
  if (RE2::PartialMatch(line, *smmu_sig_re, func_name, signature)) {
    return true;
  }
  LOG(INFO) << line << " does not match regex";
  signature->clear();
  func_name->clear();
  return false;
}

constexpr LazyRE2 ath10k_sig_re = {R"((ath10k_.*firmware crashed))"};

bool KernelWarningCollector::ExtractAth10kSignature(const std::string& content,
                                                    std::string* signature,
                                                    std::string* func_name) {
  std::string line;
  std::string::size_type end_position = content.find('\n');
  if (end_position == std::string::npos) {
    LOG(ERROR) << "unexpected ath10k crash format";
    return false;
  }

  line = content.substr(0, end_position);
  if (RE2::PartialMatch(line, *ath10k_sig_re, signature)) {
    *func_name = "firmware crashed";
    return true;
  }
  LOG(INFO) << line << " does not match regex";
  signature->clear();
  func_name->clear();
  return false;
}

bool KernelWarningCollector::Collect(int weight, WarningType type) {
  LOG(INFO) << "Processing kernel warning";

  if (weight != 1) {
    AddCrashMetaUploadData("weight", StringPrintf("%d", weight));
  }

  std::string kernel_warning;
  std::string warning_signature;
  std::string func_name;
  if (!LoadKernelWarning(&kernel_warning, &warning_signature, &func_name,
                         type)) {
    return false;
  }

  FilePath root_crash_directory;
  if (!GetCreatedCrashDirectoryByEuid(kRootUid, &root_crash_directory,
                                      nullptr)) {
    return false;
  }

  const char* exec_name;
  if (type == kWifi)
    exec_name = kWifiWarningExecName;
  else if (type == kSMMUFault)
    exec_name = kSMMUFaultExecName;
  else if (type == kSuspend)
    exec_name = kSuspendWarningExecName;
  else if (type == kGeneric)
    exec_name = kGenericWarningExecName;
  else if (type == kAth10k)
    exec_name = kKernelAth10kErrorExecName;
  else
    exec_name = kKernelIwlwifiErrorExecName;

  // Attempt to make the exec_name more unique to avoid collisions.
  if (!func_name.empty()) {
    func_name.insert(func_name.begin(), '_');
  } else {
    LOG(WARNING) << "Couldn't extract function name from signature. "
                    "Going on without it.";
  }

  std::string dump_basename = FormatDumpBasename(
      base::StrCat({exec_name, func_name}), time(nullptr), kKernelPid);
  FilePath log_path =
      GetCrashPath(root_crash_directory, dump_basename, "log.gz");
  FilePath meta_path =
      GetCrashPath(root_crash_directory, dump_basename, "meta");
  FilePath kernel_crash_path = root_crash_directory.Append(
      StringPrintf("%s.kcrash", dump_basename.c_str()));

  // We must use WriteNewFile instead of base::WriteFile as we
  // do not want to write with root access to a symlink that an attacker
  // might have created.
  if (WriteNewFile(kernel_crash_path, kernel_warning.data(),
                   kernel_warning.length()) !=
      static_cast<int>(kernel_warning.length())) {
    LOG(INFO) << "Failed to write kernel warning to "
              << kernel_crash_path.value().c_str();
    return true;
  }

  AddCrashMetaData(kKernelWarningSignatureKey, warning_signature);

  // Get the log contents, compress, and attach to crash report.
  bool result = GetLogContents(log_config_path_, exec_name, log_path);
  if (result) {
    AddCrashMetaUploadFile("log", log_path.BaseName().value());
  }

  FinishCrash(meta_path, exec_name, kernel_crash_path.BaseName().value());

  return true;
}
