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

#include <pcrecpp.h>
#include <stdint.h>

#include <map>
#include <string>

#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <brillo/data_encoding.h>
#include <brillo/process.h>
#include <brillo/syslog_logging.h>

#include "crash-reporter/util.h"

using base::FilePath;

namespace {

const char kDefaultMinidumpName[] = "upload_file_minidump";

// Filenames for logs attached to crash reports. Also used as metadata keys.
const char kChromeLogFilename[] = "chrome.txt";
const char kGpuStateFilename[] = "i915_error_state.log.xz";

// Filename for the pid of the browser process if it was aborted due to a
// browser hang. Written by session_manager.
constexpr char kAbortedBrowserPidPath[] = "/run/chrome/aborted_browser_pid";

// Extract a string delimited by the given character, from the given offset
// into a source string. Returns false if the string is zero-sized or no
// delimiter was found.
bool GetDelimitedString(const std::string& str,
                        char ch,
                        size_t offset,
                        std::string* substr) {
  size_t at = str.find_first_of(ch, offset);
  if (at == std::string::npos || at == offset)
    return false;
  *substr = str.substr(offset, at - offset);
  return true;
}

}  // namespace

ChromeCollector::ChromeCollector(CrashSendingMode crash_sending_mode)
    : CrashCollector("chrome",
                     kUseNormalCrashDirectorySelectionMethod,
                     crash_sending_mode),
      output_file_ptr_(stdout),
      max_upload_bytes_(util::kDefaultMaxUploadBytes) {}

ChromeCollector::~ChromeCollector() {}

bool ChromeCollector::HandleCrashWithDumpData(const std::string& data,
                                              pid_t pid,
                                              uid_t uid,
                                              const std::string& exe_name,
                                              const std::string& dump_dir) {
  if (!is_feedback_allowed_function_())
    return true;

  LOG(WARNING) << "Received crash notification for " << exe_name << "[" << pid
               << "] user " << uid << " (called directly)";

  if (exe_name.find('/') != std::string::npos) {
    LOG(ERROR) << "exe_name contains illegal characters: " << exe_name;
    return false;
  }

  FilePath dir;
  if (!dump_dir.empty()) {
    dir = FilePath(dump_dir);
  } else if (!GetCreatedCrashDirectoryByEuid(uid, &dir, nullptr)) {
    LOG(ERROR) << "Can't create crash directory for uid " << uid;
    return false;
  }

  std::string dump_basename = FormatDumpBasename(exe_name, time(nullptr), pid);
  FilePath meta_path = GetCrashPath(dir, dump_basename, "meta");
  FilePath minidump_path = GetCrashPath(dir, dump_basename, "dmp");

  if (!ParseCrashLog(data, dir, minidump_path, dump_basename)) {
    LOG(ERROR) << "Failed to parse Chrome's crash log";
    return false;
  }

  // Keyed by crash metadata key name.
  const std::map<std::string, base::FilePath> additional_logs =
      GetAdditionalLogs(dir, dump_basename, exe_name);
  for (const auto& it : additional_logs) {
    VLOG(1) << "Adding metadata: " << it.first << " -> " << it.second.value();
    // Call AddCrashMetaUploadFile() rather than AddCrashMetaData() here. The
    // former adds a prefix to the key name; without the prefix, only the key
    // "logs" appears to be displayed on the crash server.
    AddCrashMetaUploadFile(it.first, it.second.BaseName().value());
  }

  base::FilePath aborted_path(kAbortedBrowserPidPath);
  std::string pid_data;
  if (base::ReadFileToString(aborted_path, &pid_data)) {
    base::TrimWhitespaceASCII(pid_data, base::TRIM_TRAILING, &pid_data);
    if (pid_data == base::IntToString(pid)) {
      AddCrashMetaUploadData("browser_hang", "true");
      base::DeleteFile(aborted_path, false);
    }
  }

  // We're done.
  FinishCrash(meta_path, exe_name, minidump_path.BaseName().value());

  // In production |output_file_ptr_| must be stdout because chrome expects to
  // read the magic string there.
  fprintf(output_file_ptr_, "%s", kSuccessMagic);
  fflush(output_file_ptr_);

  return true;
}

bool ChromeCollector::HandleCrash(const FilePath& file_path,
                                  pid_t pid,
                                  uid_t uid,
                                  const std::string& exe_name) {
  std::string data;
  if (!base::ReadFileToString(base::FilePath(file_path), &data)) {
    PLOG(ERROR) << "Can't read crash log: " << file_path.value();
    return false;
  }

  return HandleCrashWithDumpData(data, pid, uid, exe_name, "" /* dump_dir */);
}

bool ChromeCollector::HandleCrashThroughMemfd(int memfd,
                                              pid_t pid,
                                              uid_t uid,
                                              const std::string& exe_name,
                                              const std::string& dump_dir) {
  std::string data;
  if (!util::ReadMemfdToString(memfd, &data)) {
    PLOG(ERROR) << "Can't read crash log from memfd: " << memfd;
    return false;
  }

  return HandleCrashWithDumpData(data, pid, uid, exe_name, dump_dir);
}

bool ChromeCollector::ParseCrashLog(const std::string& data,
                                    const FilePath& dir,
                                    const FilePath& minidump,
                                    const std::string& basename) {
  size_t at = 0;
  while (at < data.size()) {
    // Look for a : followed by a decimal number, followed by another :
    // followed by N bytes of data.
    std::string name, size_string;
    if (!GetDelimitedString(data, ':', at, &name)) {
      LOG(ERROR) << "Can't find : after name @ offset " << at;
      break;
    }
    at += name.size() + 1;  // Skip the name & : delimiter.

    if (!GetDelimitedString(data, ':', at, &size_string)) {
      LOG(ERROR) << "Can't find : after size @ offset " << at;
      break;
    }
    at += size_string.size() + 1;  // Skip the size & : delimiter.

    size_t size;
    if (!base::StringToSizeT(size_string, &size)) {
      LOG(ERROR) << "String not convertible to integer: " << size_string;
      break;
    }

    // Data would run past the end, did we get a truncated file?
    if (at + size > data.size()) {
      LOG(ERROR) << "Overrun, expected " << size << " bytes of data, got "
                 << (data.size() - at);
      break;
    }

    if (name.find("filename") != std::string::npos) {
      // File.
      // Name will be in a semi-MIME format of
      // <descriptive name>"; filename="<name>"
      // Descriptive name will be upload_file_minidump for the dump.
      std::string desc, filename;
      pcrecpp::RE re("(.*)\" *; *filename=\"(.*)\"");
      if (!re.FullMatch(name.c_str(), &desc, &filename)) {
        LOG(ERROR) << "Filename was not in expected format: " << name;
        break;
      }

      if (desc.compare(kDefaultMinidumpName) == 0) {
        // The minidump.
        WriteNewFile(minidump, data.c_str() + at, size);
      } else {
        // Some other file.
        FilePath path = GetCrashPath(dir, basename + "-" + filename, "other");
        if (WriteNewFile(path, data.c_str() + at, size) >= 0) {
          AddCrashMetaUploadFile(desc, path.BaseName().value());
        }
      }
    } else {
      // Other attribute.
      std::string value_str;
      value_str.reserve(size);

      // Since metadata is one line/value the values must be escaped properly.
      for (size_t i = at; i < at + size; i++) {
        switch (data[i]) {
          case '"':
          case '\\':
            value_str.push_back('\\');
            value_str.push_back(data[i]);
            break;

          case '\r':
            value_str += "\\r";
            break;

          case '\n':
            value_str += "\\n";
            break;

          case '\t':
            value_str += "\\t";
            break;

          case '\0':
            value_str += "\\0";
            break;

          default:
            value_str.push_back(data[i]);
            break;
        }
      }
      AddCrashMetaUploadData(name, value_str);
    }

    at += size;
  }

  return at == data.size();
}

void ChromeCollector::AddLogIfNotTooBig(
    const char* log_map_key,
    const base::FilePath& complete_file_name,
    std::map<std::string, base::FilePath>* logs) {
  if (get_bytes_written() <= max_upload_bytes_) {
    (*logs)[log_map_key] = complete_file_name.BaseName();
  } else {
    // Logs were really big, don't upload them.
    LOG(WARNING) << "Skipping upload of " << complete_file_name.value()
                 << " because report size would exceed limit ("
                 << max_upload_bytes_ << "B)";
    // And free up resources to avoid leaving orphaned file around.
    if (!RemoveNewFile(complete_file_name)) {
      LOG(WARNING) << "Could not remove " << complete_file_name.value();
    }
  }
}

std::map<std::string, base::FilePath> ChromeCollector::GetAdditionalLogs(
    const FilePath& dir,
    const std::string& basename,
    const std::string& exe_name) {
  std::map<std::string, base::FilePath> logs;
  if (get_bytes_written() > max_upload_bytes_) {
    // Minidump is already too big, no point in processing logs or querying
    // debugd.
    LOG(WARNING) << "Skipping upload of supplemental logs because report size "
                 << "already exceeds limit (" << max_upload_bytes_ << "B)";
    return logs;
  }

  // Run the command specified by the config file to gather logs.
  const FilePath chrome_log_path =
      GetCrashPath(dir, basename, kChromeLogFilename).AddExtension("gz");
  if (GetLogContents(log_config_path_, exe_name, chrome_log_path)) {
    AddLogIfNotTooBig(kChromeLogFilename, chrome_log_path, &logs);
  }

  // For unit testing, debugd_proxy_ isn't initialized, so skip attempting to
  // get the GPU error state from debugd.
  SetUpDBus();
  if (debugd_proxy_) {
    const FilePath dri_error_state_path =
        GetCrashPath(dir, basename, kGpuStateFilename);
    if (GetDriErrorState(dri_error_state_path))
      AddLogIfNotTooBig(kGpuStateFilename, dri_error_state_path, &logs);
  }

  return logs;
}

bool ChromeCollector::GetDriErrorState(const FilePath& error_state_path) {
  brillo::ErrorPtr error;
  std::string error_state_str;
  // Chrome has a 12 second timeout for crash_reporter to execute when it
  // invokes it, so use a 5 second timeout here on our D-Bus call.
  constexpr int kDebugdGetLogTimeoutMsec = 5000;
  debugd_proxy_->GetLog("i915_error_state", &error_state_str, &error,
                        kDebugdGetLogTimeoutMsec);

  if (error) {
    LOG(ERROR) << "Error calling D-Bus proxy call to interface "
               << "'" << debugd_proxy_->GetObjectPath().value()
               << "':" << error->GetMessage();
    return false;
  }

  if (error_state_str == "<empty>")
    return false;

  const char kBase64Header[] = "<base64>: ";
  const size_t kBase64HeaderLength = sizeof(kBase64Header) - 1;
  if (error_state_str.compare(0, kBase64HeaderLength, kBase64Header)) {
    LOG(ERROR) << "i915_error_state is missing base64 header";
    return false;
  }

  std::string decoded_error_state;

  if (!brillo::data_encoding::Base64Decode(
          error_state_str.c_str() + kBase64HeaderLength,
          &decoded_error_state)) {
    LOG(ERROR) << "Could not decode i915_error_state";
    return false;
  }

  // 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.
  int written = WriteNewFile(error_state_path, decoded_error_state.c_str(),
                             decoded_error_state.length());
  if (written < 0 ||
      static_cast<size_t>(written) != decoded_error_state.length()) {
    PLOG(ERROR) << "Could not write file " << error_state_path.value()
                << " Written: " << written
                << " Len: " << decoded_error_state.length();
    base::DeleteFile(error_state_path, false);
    return false;
  }

  return true;
}

// See chrome's src/components/crash/content/app/breakpad_linux.cc.
// static
const char ChromeCollector::kSuccessMagic[] = "_sys_cr_finished";
