// Copyright 2020 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "pciguard/sysfs_utils.h"

#include <base/command_line.h>
#include <base/files/file_enumerator.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/string_util.h>
#include <brillo/syslog_logging.h>

#include <set>
#include <string>
#include <sysexits.h>

namespace pciguard {

namespace {

// Actual driver allowlist.
const char* kAllowlist[] = {
    // TODO(b/163121310): Finalize allowlist
    "pcieport",  // PCI Core services - AER, Hotplug etc.
    "xhci_hcd",  // XHCI host controller driver.
    "nvme",      // PCI Express NVME host controller driver.
    "ahci",      // AHCI driver
    "igb",       // Intel Gigabit Ethernet driver
    "igc",       // Intel I225-LM/I225-V Ethernet controller driver
};

}  // namespace

SysfsUtils::SysfsUtils() : SysfsUtils(FilePath("/")) {}

SysfsUtils::SysfsUtils(FilePath root)
    : allowlist_path_(root.Append("sys/bus/pci/drivers_allowlist")),
      pci_lockdown_path_(root.Append("sys/bus/pci/drivers_allowlist_lockdown")),
      pci_rescan_path_(root.Append("sys/bus/pci/rescan")),
      tbt_devices_path_(root.Append("sys/bus/thunderbolt/devices")),
      pci_devices_path_(root.Append("sys/bus/pci/devices")) {}

int SysfsUtils::SetAuthorizedAttribute(base::FilePath devpath, bool enable) {
  if (!PathExists(devpath)) {
    PLOG(ERROR) << "Path doesn't exist : " << devpath;
    return EXIT_FAILURE;
  }

  base::FilePath symlink;
  // Check it is a thunderbolt path
  if (!base::ReadSymbolicLink(devpath.Append("subsystem"), &symlink) ||
      !base::EndsWith(symlink.value(), "/bus/thunderbolt",
                      base::CompareCase::SENSITIVE)) {
    LOG(ERROR) << "Not a thunderbolt devpath: " << devpath;
    return EXIT_FAILURE;
  }

  base::FilePath authorized_path = devpath.Append("authorized");
  std::string authorized;

  // Proceed only if authorized file exists
  if (!base::ReadFileToString(authorized_path, &authorized))
    return EXIT_SUCCESS;

  // Nevermind if no need to change the state.
  if (!authorized.empty() &&
      ((enable && authorized[0] != '0') || (!enable && authorized[0] == '0')))
    return EXIT_SUCCESS;

  auto val = "0";
  if (enable) {
    LOG(INFO) << "Authorizing:" << devpath;
    val = "1";
  } else {
    LOG(INFO) << "Deauthorizing:" << devpath;
  }

  if (base::WriteFile(authorized_path, val, 1) != 1) {
    PLOG(ERROR) << "Couldn't write " << val << " to " << authorized_path;
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}

int SysfsUtils::DeauthorizeThunderboltDev(base::FilePath devpath) {
  return SetAuthorizedAttribute(devpath, false);
}

int SysfsUtils::OnInit(void) {
  if (!base::PathIsWritable(allowlist_path_) ||
      !base::PathIsWritable(pci_lockdown_path_)) {
    PLOG(ERROR) << "Kernel is missing needed support for external PCI security";
    return EX_OSFILE;
  }

  if (base::WriteFile(pci_lockdown_path_, "1", 1) != 1) {
    PLOG(ERROR) << "Couldn't write 1 to " << pci_lockdown_path_;
    return EX_IOERR;
  }

  for (auto drvr_name : kAllowlist) {
    if (base::WriteFile(allowlist_path_, drvr_name, sizeof(drvr_name)) ==
        sizeof(drvr_name))
      LOG(INFO) << "Allowed " << drvr_name;
    else
      PLOG(ERROR) << "Couldn't allow " << drvr_name;
  }
  return EX_OK;
}

int SysfsUtils::AuthorizeThunderboltDev(base::FilePath devpath) {
  return SetAuthorizedAttribute(devpath, true);
}

int SysfsUtils::AuthorizeAllDevices(void) {
  LOG(INFO) << "Authorizing all external PCI devices";

  // Allow drivers to bind to PCI devices. This also binds any PCI devices
  // that may have been hotplugged "into" external peripherals, while the
  // screen was locked.
  if (base::WriteFile(pci_lockdown_path_, "0", 1) != 1) {
    PLOG(ERROR) << "Couldn't write 0 to " << pci_lockdown_path_;
    return EXIT_FAILURE;
  }

  int ret = EXIT_SUCCESS;

  // Add any PCI devices that we removed when the user had logged off.
  if (base::WriteFile(pci_rescan_path_, "1", 1) != 1) {
    PLOG(ERROR) << "Couldn't write 1 to " << pci_rescan_path_;
    ret = EXIT_FAILURE;
  }

  // Create an BFS ordered set of thunderbolt devices.
  auto cmp = [](const base::FilePath& dev1, const base::FilePath& dev2) {
    base::FilePath symlink1, symlink2;
    (void)base::ReadSymbolicLink(dev1, &symlink1);
    (void)base::ReadSymbolicLink(dev2, &symlink2);
    return symlink1 < symlink2;
  };
  std::set<base::FilePath, decltype(cmp)> thunderbolt_devs(cmp);
  base::FileEnumerator iter(tbt_devices_path_, false,
                            base::FileEnumerator::DIRECTORIES);
  for (auto devpath = iter.Next(); !devpath.empty(); devpath = iter.Next())
    thunderbolt_devs.insert(devpath);

  // Authorize the thunderbolt devices in BFS order (sorting using the
  // symlinks to which the devices point, gives us BFS). This is
  // required because if a parent is deauthorized, the children are
  // automatically deauthorized, but vice versa is not true.
  for (auto dev : thunderbolt_devs) {
    if (AuthorizeThunderboltDev(dev))
      ret = EXIT_FAILURE;
  }

  return ret;
}

int SysfsUtils::DenyNewDevices(void) {
  LOG(INFO) << "Will deny all new external PCI devices";

  // Deny drivers to bind to any *new* external PCI devices.
  if (base::WriteFile(pci_lockdown_path_, "1", 1) != 1) {
    PLOG(ERROR) << "Couldn't write 1 to " << pci_lockdown_path_;
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;
}

int SysfsUtils::DeauthorizeAllDevices(void) {
  int ret = EXIT_SUCCESS;
  if (DenyNewDevices())
    return EXIT_FAILURE;

  LOG(INFO) << "Deauthorizing all external PCI devices";

  // Remove all untrusted (external) PCI devices.
  base::FileEnumerator iter(pci_devices_path_, false,
                            base::FileEnumerator::DIRECTORIES);
  for (auto devpath = iter.Next(); !devpath.empty(); devpath = iter.Next()) {
    std::string removable;

    // It is possible this device may already been have removed (as an effect
    // of its parent being removed).
    if (!PathExists(devpath))
      continue;

    // Proceed only if it is a removable device
    if (!base::ReadFileToString(devpath.Append("removable"), &removable) ||
        removable != "removable")
      continue;

    // Remove device.
    if (base::WriteFile(devpath.Append("remove"), "1", 1) != 1) {
      PLOG(ERROR) << "Couldn't remove untrusted device " << devpath;
      ret = EXIT_FAILURE;
    }
  }

  // Deauthorize all thunderbolt devices.
  base::FileEnumerator tbt_iter(tbt_devices_path_, false,
                                base::FileEnumerator::DIRECTORIES);
  for (auto devpath = tbt_iter.Next(); !devpath.empty();
       devpath = tbt_iter.Next()) {
    if (DeauthorizeThunderboltDev(devpath))
      ret = EXIT_FAILURE;
  }
  return ret;
}

}  // namespace pciguard
