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

#include "permission_broker/usb_driver_tracker.h"

#include <errno.h>
#include <fcntl.h>
#include <linux/usbdevice_fs.h>
#include <sys/epoll.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <unistd.h>

#include <string>
#include <utility>

#include <base/bind.h>
#include <base/containers/contains.h>
#include <base/containers/cxx20_erase_vector.h>
#include <base/files/file_descriptor_watcher_posix.h>
#include <base/logging.h>
#include <base/posix/eintr_wrapper.h>
#include <base/strings/string_number_conversions.h>
#include <base/unguessable_token.h>

#include "permission_broker/udev_scopers.h"

namespace permission_broker {

UsbDriverTracker::UsbDriverTracker() = default;

UsbDriverTracker::~UsbDriverTracker() {
  CleanUpTracking();
}

void UsbDriverTracker::HandleClosedFd(std::string client_id) {
  auto iter = dev_fds_.find(client_id);
  if (iter != dev_fds_.end()) {
    auto& entry = iter->second;
    // Reattaching the kernel driver to the USB interface.
    while (!entry.interfaces.empty()) {
      uint8_t iface_num = *entry.interfaces.begin();
      // This might remove elements in entry.interfaces.
      if (!ReattachInterface(client_id, iface_num)) {
        LOG(ERROR) << "Failed to reattach interface "
                   << static_cast<int>(iface_num) << " for client "
                   << client_id;
        // Remove the interface from the tracking record even if reattaching
        // fails (ex: ioctl() failure) to avoid orphan tracking record as this
        // client is being closed.
        ClearDetachedInterfaceRecord(client_id, entry.path, iface_num);
      }
    }
    // We are done with the client_id.
    dev_fds_.erase(iter);
  } else {
    LOG(WARNING) << "Untracked USB client " << client_id;
  }
}

bool UsbDriverTracker::DetachPathFromKernel(int fd,
                                            const std::string* client_id,
                                            const base::FilePath& path) {
  // Use the USB device node major/minor to find the udev entry.
  struct stat st;
  if (fstat(fd, &st) || !S_ISCHR(st.st_mode)) {
    LOG(WARNING) << "Cannot stat " << path << " device id";
    return false;
  }

  ScopedUdevPtr udev(udev_new());
  ScopedUdevDevicePtr device(
      udev_device_new_from_devnum(udev.get(), 'c', st.st_rdev));
  if (!device.get()) {
    return false;
  }

  ScopedUdevEnumeratePtr enumerate(udev_enumerate_new(udev.get()));
  udev_enumerate_add_match_parent(enumerate.get(), device.get());
  udev_enumerate_scan_devices(enumerate.get());

  // Try to find our USB interface nodes, by iterating through all devices
  // and extracting our children devices.
  bool detached = false;
  struct udev_list_entry* entry;
  udev_list_entry_foreach(entry,
                          udev_enumerate_get_list_entry(enumerate.get())) {
    const char* entry_path = udev_list_entry_get_name(entry);
    ScopedUdevDevicePtr child(
        udev_device_new_from_syspath(udev.get(), entry_path));

    const char* child_type = udev_device_get_devtype(child.get());
    if (!child_type || strcmp(child_type, "usb_interface") != 0) {
      continue;
    }

    const char* driver = udev_device_get_driver(child.get());
    if (driver) {
      // A kernel driver is using this interface, try to detach it.
      const char* iface =
          udev_device_get_sysattr_value(child.get(), "bInterfaceNumber");
      unsigned iface_num;
      if (!iface || !base::StringToUint(iface, &iface_num)) {
        detached = false;
        continue;
      }

      detached = true;
      if (client_id) {
        if (!DetachInterface(*client_id, iface_num)) {
          LOG(ERROR) << "Fail to detach interface "
                     << static_cast<int>(iface_num) << " for client "
                     << client_id;
          detached = false;
        }
      } else {
        // This is the case in Permission Broker OpenPath() which doesn't use
        // any client tracking.
        if (!DisconnectInterface(fd, iface_num)) {
          LOG(ERROR) << "Failed to detach interface "
                     << static_cast<int>(iface_num) << " with fd " << fd;
          detached = false;
        }
      }
    }
  }

  return detached;
}

std::unique_ptr<base::FileDescriptorWatcher::Controller>
UsbDriverTracker::WatchLifelineFd(const std::string& client_id,
                                  int lifeline_fd) {
  return base::FileDescriptorWatcher::WatchReadable(
      lifeline_fd,
      base::BindRepeating(&UsbDriverTracker::HandleClosedFd,
                          weak_ptr_factory_.GetWeakPtr(), client_id));
}

std::optional<std::string> UsbDriverTracker::RegisterClient(
    int lifeline_fd, const base::FilePath& path) {
  // |dup_lifeline_fd| is the duplicated file descriptor of the client's
  // lifeline pipe read end. The ownership needs to be transferred to the
  // internal tracking structure to keep readable callback registered.
  base::ScopedFD fd(HANDLE_EINTR(open(path.value().c_str(), O_RDWR)));
  if (!fd.is_valid()) {
    PLOG(ERROR) << "Failed to open path " << path;
    return std::nullopt;
  }
  base::ScopedFD dup_lifeline_fd(HANDLE_EINTR(dup(lifeline_fd)));
  if (!dup_lifeline_fd.is_valid()) {
    PLOG(ERROR) << "Failed to dup lifeline_fd " << lifeline_fd;
    return std::nullopt;
  }

  std::string client_id;
  do {
    client_id = base::UnguessableToken::Create().ToString();
  } while (base::Contains(dev_fds_, client_id));

  auto controller = WatchLifelineFd(client_id, dup_lifeline_fd.get());
  if (!controller) {
    LOG(ERROR) << "Unable to watch lifeline_fd " << dup_lifeline_fd.get()
               << " for client " << client_id;
    return std::nullopt;
  }

  dev_fds_.emplace(client_id,
                   UsbInterfaces{.path = path,
                                 .controller = std::move(controller),
                                 .interfaces = {},
                                 .fd = std::move(fd),
                                 .lifeline_fd = std::move(dup_lifeline_fd)});

  return client_id;
}

bool UsbDriverTracker::DisconnectInterface(int fd, uint8_t iface_num) {
  struct usbdevfs_ioctl dio;
  dio.ifno = iface_num;
  dio.ioctl_code = USBDEVFS_DISCONNECT;
  dio.data = nullptr;
  int rc = ioctl(fd, USBDEVFS_IOCTL, &dio);
  // ENODATA is a benign error code which is when the interface isn't
  // associated with any driver.
  if (rc < 0 && errno != ENODATA) {
    PLOG(ERROR) << "Failed to disconnect interface "
                << static_cast<int>(iface_num) << " with fd " << fd;
    return false;
  }

  return true;
}

bool UsbDriverTracker::ConnectInterface(int fd, uint8_t iface_num) {
  struct usbdevfs_ioctl dio;
  dio.ifno = iface_num;
  dio.ioctl_code = USBDEVFS_CONNECT;
  dio.data = nullptr;
  int rc = ioctl(fd, USBDEVFS_IOCTL, &dio);
  if (rc < 0) {
    PLOG(ERROR) << "Failed to connect interface " << static_cast<int>(iface_num)
                << " with fd " << fd;
    return false;
  }

  return true;
}

void UsbDriverTracker::RecordInterfaceDetached(const std::string& client_id,
                                               const base::FilePath& path,
                                               uint8_t iface_num) {
  auto client_it = dev_fds_.find(client_id);
  if (client_it == dev_fds_.end()) {
    LOG(DFATAL) << "Can't find client " << client_id
                << " in the tracking record";
    return;
  }
  if (base::Contains(client_it->second.interfaces, iface_num)) {
    LOG(DFATAL) << "Detached interface " << static_cast<int>(iface_num)
                << " on path " << path
                << " has already been recorded by client " << client_id;
    return;
  }

  client_it->second.interfaces.push_back(iface_num);
  dev_ifaces_[path][iface_num] = client_id;
}

void UsbDriverTracker::ClearDetachedInterfaceRecord(
    const std::string& client_id,
    const base::FilePath& path,
    uint8_t iface_num) {
  auto client_it = dev_fds_.find(client_id);
  auto path_it = dev_ifaces_.find(path);
  if (client_it == dev_fds_.end()) {
    LOG(DFATAL) << "Can't find client " << client_id
                << " in the tracking record";
    return;
  }
  if (path_it == dev_ifaces_.end()) {
    LOG(DFATAL) << "Can't find path " << path << " in the tracking record";
    return;
  }

  auto num_erased = base::Erase(client_it->second.interfaces, iface_num);
  if (num_erased != 1) {
    LOG(DFATAL) << "Unexpected number of erased records " << num_erased
                << " for interface " << static_cast<int>(iface_num)
                << " on path " << path << " for client " << client_id;
  }
  path_it->second.erase(iface_num);
  if (path_it->second.empty()) {
    dev_ifaces_.erase(path_it);
  }
}

bool UsbDriverTracker::IsClientIdTracked(const std::string& client_id) {
  return base::Contains(dev_fds_, client_id);
}

void UsbDriverTracker::CleanUpTracking() {
  // Reattach all delegated USB interfaces.
  while (!dev_fds_.empty()) {
    // This might remove the element.
    HandleClosedFd(dev_fds_.begin()->first);
  }
}

bool UsbDriverTracker::DetachInterface(const std::string& client_id,
                                       uint8_t iface_num) {
  if (!IsClientIdTracked(client_id)) {
    LOG(WARNING) << "DetachInterface: Untracked client " << client_id;
    return false;
  }

  const auto& path = dev_fds_[client_id].path;
  const auto& fd = dev_fds_[client_id].fd;
  auto path_it = dev_ifaces_.find(path);
  if (path_it != dev_ifaces_.end()) {
    auto iface_it = path_it->second.find(iface_num);
    if (iface_it != path_it->second.end()) {
      if (iface_it->second != client_id) {
        LOG(WARNING) << "The interface " << static_cast<int>(iface_num)
                     << " at path " << path << " can't be detached by client "
                     << client_id << " as it has been detached by other client "
                     << iface_it->second;
        return false;
      }
      // No-op if the interface has been detached by the requested client.
      return true;
    }
  }

  if (!DisconnectInterface(fd.get(), iface_num)) {
    LOG(ERROR) << "Kernel USB driver disconnection for " << path
               << " on interface " << static_cast<int>(iface_num)
               << " by client " << client_id << " failed";
    return false;
  }

  RecordInterfaceDetached(client_id, path, iface_num);
  return true;
}

bool UsbDriverTracker::ReattachInterface(const std::string& client_id,
                                         uint8_t iface_num) {
  if (!IsClientIdTracked(client_id)) {
    LOG(WARNING) << "ReattachInterface: Untracked client " << client_id;
    return false;
  }

  const auto& path = dev_fds_[client_id].path;
  const auto& fd = dev_fds_[client_id].fd;
  auto path_it = dev_ifaces_.find(path);
  if (path_it == dev_ifaces_.end()) {
    // No-op if the path hasn't been detached by any clients.
    return true;
  }
  auto iface_it = path_it->second.find(iface_num);
  if (iface_it == path_it->second.end()) {
    // No-op if the interface hasn't been detached by any clients.
    return true;
  }
  if (iface_it->second != client_id) {
    LOG(WARNING) << "The interface " << static_cast<int>(iface_num)
                 << " at path " << path << " can't be attached by client "
                 << client_id << " as it was detached by other client "
                 << iface_it->second;
    return false;
  }

  if (!ConnectInterface(fd.get(), iface_num)) {
    LOG(ERROR) << "Kernel USB driver connection for " << path
               << " on interface " << static_cast<int>(iface_num)
               << " by client " << client_id << " failed";
    return false;
  }

  ClearDetachedInterfaceRecord(client_id, path, iface_num);
  return true;
}

}  // namespace permission_broker
