// Copyright 2018 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/util.h"

#include <poll.h>
#include <signal.h>
#include <stdlib.h>

#include <algorithm>
#include <map>
#include <memory>

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

#include <base/files/file_util.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <brillo/cryptohome.h>
#include <brillo/key_value_store.h>
#include <brillo/userdb_utils.h>
#include <vboot/crossystem.h>
#include <zlib.h>

#include "crash-reporter/paths.h"

namespace util {

namespace {

constexpr size_t kBufferSize = 4096;

// Path to hardware class description.
constexpr char kHwClassPath[] = "/sys/devices/platform/chromeos_acpi/HWID";

constexpr char kDevSwBoot[] = "devsw_boot";
constexpr char kDevMode[] = "dev";

// If the OS version is older than this we do not upload crash reports.
constexpr base::TimeDelta kAgeForNoUploads = base::TimeDelta::FromDays(180);

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

}  // namespace

const int kDefaultMaxUploadBytes = 1024 * 1024;

bool IsCrashTestInProgress() {
  return base::PathExists(paths::GetAt(paths::kSystemRunStateDirectory,
                                       paths::kCrashTestInProgress));
}

bool IsDeviceCoredumpUploadAllowed() {
  return base::PathExists(paths::GetAt(paths::kCrashReporterStateDirectory,
                                       paths::kDeviceCoredumpUploadAllowed));
}

bool IsDeveloperImage() {
  // If we're testing crash reporter itself, we don't want to special-case
  // for developer images.
  if (IsCrashTestInProgress())
    return false;
  return base::PathExists(paths::Get(paths::kLeaveCoreFile));
}

// Determines if this is a test image, IGNORING IsCrashTestInProgress.
// Use sparingly, and only if you're really sure you want to have different
// behavior during crash tests than on real devices.
bool IsReallyTestImage() {
  std::string channel;
  if (!GetCachedKeyValueDefault(base::FilePath(paths::kLsbRelease),
                                "CHROMEOS_RELEASE_TRACK", &channel)) {
    return false;
  }
  return base::StartsWith(channel, "test", base::CompareCase::SENSITIVE);
}

bool IsTestImage() {
  // If we're testing crash reporter itself, we don't want to special-case
  // for test images.
  if (IsCrashTestInProgress())
    return false;

  return IsReallyTestImage();
}

bool IsOfficialImage() {
  std::string description;
  if (!GetCachedKeyValueDefault(base::FilePath(paths::kLsbRelease),
                                "CHROMEOS_RELEASE_DESCRIPTION", &description)) {
    return false;
  }

  return description.find("Official") != std::string::npos;
}

bool HasMockConsent() {
  // Don't bypass user consent on real Chromebooks; this is for testing.
  // We can't use IsTestImage because that's always false if a crash test is in
  // progress.
  if (!IsReallyTestImage()) {
    return false;
  }
  return base::PathExists(
      paths::GetAt(paths::kSystemRunStateDirectory, paths::kMockConsent));
}

bool SkipCrashCollection(int argc, char* argv[]) {
  // Don't skip crashes on real Chromebooks; this is for testing.
  // We can't use IsTestImage because that's always false if a crash test is in
  // progress.
  if (!IsReallyTestImage()) {
    return false;
  }

  base::FilePath file =
      paths::GetAt(paths::kSystemRunStateDirectory, paths::kFilterInFile);
  if (!base::PathExists(file)) {
    return false;
  }

  std::string contents;
  if (!base::ReadFileToString(file, &contents)) {
    LOG(WARNING) << "Failed to read " << file;
    return false;
  }

  std::vector<std::string> args(argv + 1, argv + argc);
  std::string command_line = base::JoinString(args, " ");

  // If the command line consists solely of these flags, it's always allowed
  // (regardless of filter-in state).
  // These flags are always accepted because they do not create crash files.
  // Tests may wish to verify or depend on their effects while also blocking all
  // crashes (using a filter-in of "none").
  const std::vector<std::string> allowlist = {
      "--init",
      "--clean_shutdown",
      "--log_to_stderr",
  };

  bool all_args_allowed = true;
  for (auto it = args.begin(); it != args.end() && all_args_allowed; ++it) {
    if (std::find(allowlist.begin(), allowlist.end(), *it) == allowlist.end()) {
      all_args_allowed = false;
    }
  }
  if (all_args_allowed) {
    return false;
  }

  if (contents == "none" || command_line.find(contents) == std::string::npos) {
    // Doesn't match, so skip this crash.
    LOG(WARNING) << "Ignoring crash invocation '" << command_line << "' due to "
                 << "filter_in=" << contents << ".";
    return true;
  }
  return false;
}

bool SetGroupAndPermissions(const base::FilePath& file,
                            const char* group,
                            bool execute) {
  gid_t gid;
  if (!brillo::userdb::GetGroupInfo(group, &gid)) {
    LOG(ERROR) << "Couldn't look up group " << group;
    return false;
  }
  if (lchown(file.value().c_str(), -1, gid) != 0) {
    PLOG(ERROR) << "Couldn't chown " << file.value();
    return false;
  }
  int mode;
  if (!base::GetPosixFilePermissions(file, &mode)) {
    PLOG(ERROR) << "Couldn't get file permissions for " << file.value();
    return false;
  }
  mode_t group_mode = S_IRGRP | S_IWGRP;
  if (execute) {
    group_mode |= S_IXGRP;
  }
  if (!base::SetPosixFilePermissions(file, mode | group_mode)) {
    PLOG(ERROR) << "Couldn't chmod " << file.value();
    return false;
  }
  return true;
}

base::Time GetOsTimestamp() {
  base::FilePath lsb_release_path =
      paths::Get(paths::kEtcDirectory).Append(paths::kLsbRelease);
  base::File::Info info;
  if (!base::GetFileInfo(lsb_release_path, &info)) {
    LOG(ERROR) << "Failed reading info for /etc/lsb-release";
    return base::Time();
  }

  return info.last_modified;
}

bool IsOsTimestampTooOldForUploads(base::Time timestamp, base::Clock* clock) {
  if (timestamp.is_null()) {
    return false;
  }
  base::Time now = clock->Now();
  // In case of invalid timestamps, always upload a crash -- something strange
  // is happening.
  if (timestamp > now) {
    LOG(ERROR) << "OS timestamp is in the future: " << timestamp;
    return false;
  } else if (timestamp < base::Time::UnixEpoch()) {
    LOG(ERROR) << "OS timestamp is negative: " << timestamp;
    return false;
  }
  return (now - timestamp) > kAgeForNoUploads;
}

std::string GetHardwareClass() {
  std::string hw_class;
  if (base::ReadFileToString(paths::Get(kHwClassPath), &hw_class))
    return hw_class;
  char hw_class_arr[VB_MAX_STRING_PROPERTY];
  if (!VbGetSystemPropertyString("hwid", hw_class_arr, sizeof(hw_class_arr)))
    return "undefined";
  return hw_class_arr;
}

std::string GetBootModeString() {
  // If we're testing crash reporter itself, we don't want to special-case
  // for developer mode.
  if (IsCrashTestInProgress())
    return "";

  int vb_value = VbGetSystemPropertyInt(kDevSwBoot);
  if (vb_value < 0) {
    LOG(ERROR) << "Error trying to determine boot mode";
    return "missing-crossystem";
  }
  if (vb_value == 1)
    return kDevMode;

  return "";
}

bool GetCachedKeyValue(const base::FilePath& base_name,
                       const std::string& key,
                       const std::vector<base::FilePath>& directories,
                       std::string* value) {
  std::vector<std::string> error_reasons;
  for (const auto& directory : directories) {
    const base::FilePath file_name = directory.Append(base_name);
    if (!base::PathExists(file_name)) {
      error_reasons.push_back(file_name.value() + " not found");
      continue;
    }
    brillo::KeyValueStore store;
    if (!store.Load(file_name)) {
      LOG(WARNING) << "Problem parsing " << file_name.value();
      // Even though there was some failure, take as much as we could read.
    }
    if (!store.GetString(key, value)) {
      error_reasons.push_back("Key not found in " + file_name.value());
      continue;
    }
    return true;
  }
  LOG(WARNING) << "Unable to find " << key << ": "
               << base::JoinString(error_reasons, ", ");
  return false;
}

bool GetCachedKeyValueDefault(const base::FilePath& base_name,
                              const std::string& key,
                              std::string* value) {
  const std::vector<base::FilePath> kDirectories = {
      paths::Get(paths::kCrashReporterStateDirectory),
      paths::Get(paths::kEtcDirectory),
  };
  return GetCachedKeyValue(base_name, key, kDirectories, value);
}

bool GetUserCrashDirectories(
    org::chromium::SessionManagerInterfaceProxyInterface* session_manager_proxy,
    std::vector<base::FilePath>* directories) {
  brillo::ErrorPtr error;
  std::map<std::string, std::string> sessions;
  session_manager_proxy->RetrieveActiveSessions(&sessions, &error);

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

  for (const auto& iter : sessions) {
    directories->push_back(
        paths::Get(brillo::cryptohome::home::GetHashedUserPath(iter.second)
                       .Append("crash")
                       .value()));
  }

  return true;
}

bool GetDaemonStoreCrashDirectories(
    org::chromium::SessionManagerInterfaceProxyInterface* session_manager_proxy,
    std::vector<base::FilePath>* directories) {
  brillo::ErrorPtr error;
  std::map<std::string, std::string> sessions;
  session_manager_proxy->RetrieveActiveSessions(&sessions, &error);

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

  for (const auto& iter : sessions) {
    directories->push_back(
        paths::Get(base::FilePath(paths::kCryptohomeCrashDirectory)
                       .Append(iter.second)
                       .value()));
  }

  return true;
}

std::vector<unsigned char> GzipStream(brillo::StreamPtr data) {
  // Adapted from https://zlib.net/zlib_how.html
  z_stream deflate_stream;
  memset(&deflate_stream, 0, sizeof(deflate_stream));
  deflate_stream.zalloc = Z_NULL;
  deflate_stream.zfree = Z_NULL;

  // Using a window size of 31 sets us to gzip mode (16) + default window size
  // (15).
  const int kDefaultWindowSize = 15;
  const int kWindowSizeGzipAdd = 16;
  const int kDefaultMemLevel = 8;
  int result = deflateInit2(&deflate_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
                            kDefaultWindowSize + kWindowSizeGzipAdd,
                            kDefaultMemLevel, Z_DEFAULT_STRATEGY);
  if (result != Z_OK) {
    LOG(ERROR) << "Error initializing zlib: error code " << result
               << ", error msg: "
               << (deflate_stream.msg == nullptr ? "None" : deflate_stream.msg);
    return std::vector<unsigned char>();
  }

  std::vector<unsigned char> deflated;
  int flush = Z_NO_FLUSH;
  /* compress until end of stream */
  do {
    size_t read_size = 0;
    unsigned char in[kBufferSize];
    if (!data->ReadBlocking(in, kBufferSize, &read_size, nullptr)) {
      // We are reading from a memory stream, so this really shouldn't happen.
      LOG(ERROR) << "Error reading from input stream";
      deflateEnd(&deflate_stream);
      return std::vector<unsigned char>();
    }
    if (data->GetRemainingSize() <= 0) {
      // We must request a flush on the last chunk of data, else deflateEnd
      // may just discard some compressed data.
      flush = Z_FINISH;
    }
    deflate_stream.next_in = in;
    deflate_stream.avail_in = read_size;
    do {
      unsigned char out[kBufferSize];
      deflate_stream.avail_out = kBufferSize;
      deflate_stream.next_out = out;
      result = deflate(&deflate_stream, flush);
      // Note that most return values are acceptable; don't error out if result
      // is not Z_OK. See discussion at https://zlib.net/zlib_how.html
      DCHECK_NE(result, Z_STREAM_ERROR);
      DCHECK_LE(deflate_stream.avail_out, kBufferSize);
      int amount_in_output_buffer = kBufferSize - deflate_stream.avail_out;
      deflated.insert(deflated.end(), out, out + amount_in_output_buffer);
    } while (deflate_stream.avail_out == 0);
    DCHECK_EQ(deflate_stream.avail_in, 0) << "deflate did not consume all data";
  } while (flush != Z_FINISH);
  DCHECK_EQ(result, Z_STREAM_END) << "Stream did not complete properly";
  deflateEnd(&deflate_stream);
  return deflated;
}

int RunAndCaptureOutput(brillo::ProcessImpl* process,
                        int fd,
                        std::string* output) {
  process->RedirectUsingPipe(fd, false);
  if (process->Start()) {
    const int out = process->GetPipe(fd);
    char buffer[kBufferSize];
    output->clear();

    while (true) {
      const ssize_t count = HANDLE_EINTR(read(out, buffer, kBufferSize));
      if (count < 0) {
        process->Wait();
        break;
      }

      if (count == 0)
        return process->Wait();

      output->append(buffer, count);
    }
  }

  return -1;
}

void LogMultilineError(const std::string& error) {
  std::vector<base::StringPiece> lines = base::SplitStringPiece(
      error, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  for (auto line : lines)
    LOG(ERROR) << line;
}

bool ReadMemfdToString(int mem_fd, std::string* contents) {
  if (contents)
    contents->clear();
  base::ScopedFILE file(fdopen(mem_fd, "r"));
  if (!file) {
    PLOG(ERROR) << "Failed to fdopen(" << mem_fd << ")";
    return false;
  }
  if (fseeko(file.get(), 0, SEEK_END) != 0) {
    PLOG(ERROR) << "fseeko() error";
    return false;
  }
  off_t file_size = ftello(file.get());
  if (file_size < 0) {
    PLOG(ERROR) << "ftello() error";
    return false;
  } else if (file_size == 0) {
    LOG(ERROR) << "Minidump memfd has size of 0";
    return false;
  }

  if (fseeko(file.get(), 0, SEEK_SET) != 0) {
    PLOG(ERROR) << "fseeko() error";
    return false;
  }

  std::unique_ptr<char[]> buf(new char[file_size]);
  if (fread(buf.get(), 1, file_size, file.get()) != file_size) {
    PLOG(ERROR) << "fread() error";
    return false;
  }
  if (contents)
    contents->assign(buf.get(), file_size);

  return true;
}

int GetSelinuxWeight() {
  return 1000;
}

int GetServiceFailureWeight() {
  return 50;
}

bool ReadFdToStream(unsigned int fd, std::stringstream* stream) {
  base::File src(fd);
  char buffer[kBufferSize];

  while (true) {
    const int count = src.ReadAtCurrentPosNoBestEffort(buffer, kBufferSize);
    if (count < 0)
      return false;

    if (count == 0)
      return stream->tellp() > 0;  // Crash log should not be empty.

    stream->write(buffer, count);
  }
}

#if USE_DIRENCRYPTION
void 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

}  // namespace util
