// 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 "permission_broker/deny_claimed_hidraw_device_rule.h"

#include <bits/wordsize.h>
#include <libudev.h>
#include <linux/input.h>

#include <algorithm>
#include <limits>
#include <string>
#include <vector>

#include "base/containers/adapters.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "permission_broker/udev_scopers.h"

namespace permission_broker {

namespace {

const std::vector<std::string> kGenericSubsystems = {
    "bluetooth", "hid", "hidraw", "rfkill", "usb", "usbmisc"};

const char kLogitechUnifyingReceiverDriver[] = "logitech-djreceiver";
const char kThingmDriver[] = "thingm";

const base::StringPiece kJoydevPrefix = "/dev/input/js";

const size_t kAllowedAbsCapabilities[] = {
    ABS_X,     ABS_Y,        ABS_Z,      ABS_RX,    ABS_RY,
    ABS_RZ,    ABS_THROTTLE, ABS_RUDDER, ABS_WHEEL, ABS_GAS,
    ABS_BRAKE, ABS_HAT0X,    ABS_HAT0Y,  ABS_HAT1X, ABS_HAT1Y,
    ABS_HAT2X, ABS_HAT2Y,    ABS_HAT3X,  ABS_HAT3Y, ABS_MISC,
};

bool ParseInputCapabilities(const char* input, std::vector<uint64_t>* output) {
  // The kernel expresses capabilities as a bitfield, broken into long-sized
  // chunks encoded in hexadecimal.
  std::vector<std::string> chunks = base::SplitString(
      input, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);

  output->clear();
  output->reserve(chunks.size());

  // The most-significant chunk of the bitmask is stored first, iterate over
  // the chunks in reverse so that the result is easier to work with.
  for (const std::string& chunk : base::Reversed(chunks)) {
    uint64_t value = 0;
    if (!base::HexStringToUInt64(chunk, &value)) {
      LOG(ERROR) << "Failed to parse: " << chunk;
      return false;
    }
    // NOLINTNEXTLINE(runtime/int)
    if (value > std::numeric_limits<unsigned long>::max()) {
      LOG(ERROR) << "Chunk value too large for platform: " << value;
      return false;
    }
    output->push_back(value);
  }

  if (__WORDSIZE == 32) {
    // Compact the vector of 32-bit values into a vector of 64-bit values.
    for (size_t i = 0; i < chunks.size(); i += 2) {
      (*output)[i / 2] = (*output)[i];
      if (i + 1 < chunks.size())
        (*output)[i / 2] |= (uint64_t)((*output)[i + 1]) << 32;
    }
    output->resize((chunks.size() + 1) / 2);
  }

  return true;
}

bool IsCapabilityBitSet(const std::vector<uint64_t>& bitfield, size_t bit) {
  size_t offset = bit / (sizeof(uint64_t) * 8);
  if (offset >= bitfield.size())
    return false;

  return bitfield[offset] & (1ULL << (bit - offset * sizeof(bitfield[0]) * 8));
}

bool AnyCapabilityBitsSet(const std::vector<uint64_t>& bitfield) {
  for (auto value : bitfield) {
    if (value != 0)
      return true;
  }
  return false;
}

void UnsetCapabilityBit(std::vector<uint64_t>* bitfield, size_t bit) {
  size_t offset = bit / (sizeof(uint64_t) * 8);
  if (offset >= bitfield->size())
    return;

  (*bitfield)[offset] &= ~(1ULL << (bit - offset * sizeof(uint64_t) * 8));
}

constexpr bool IsCfmDevice() {
  return USE_CFM_ENABLED_DEVICE;
}

// Joydev devices expose a devnode string with the format:
//     /dev/input/js#
// Where # is the numeric index of the joydev device.
bool IsJoydevDeviceNode(base::StringPiece devnode) {
  // Match the devnode prefix.
  if (!base::StartsWith(devnode, kJoydevPrefix, base::CompareCase::SENSITIVE))
    return false;

  // Match if the suffix parses as a non-negative integer.
  devnode.remove_prefix(kJoydevPrefix.length());
  int joydev_index = 0;
  if (!base::StringToInt(devnode, &joydev_index))
    return false;
  return joydev_index >= 0;
}

}  // namespace

DenyClaimedHidrawDeviceRule::DenyClaimedHidrawDeviceRule()
    : HidrawSubsystemUdevRule("DenyClaimedHidrawDeviceRule") {}

Rule::Result DenyClaimedHidrawDeviceRule::ProcessHidrawDevice(
    struct udev_device* device) {
  struct udev_device* hid_parent =
      udev_device_get_parent_with_subsystem_devtype(device, "hid", nullptr);
  if (!hid_parent) {
    // A hidraw device without a HID parent, we don't know what this can be.
    return DENY;
  }

  const char* hid_parent_driver = udev_device_get_driver(hid_parent);
  if (hid_parent_driver) {
    // Add an exception to the rule for Logitech Unifying receiver. This hidraw
    // device is a parent of devices that have input subsystem. Yet the traffic
    // to those children is not available on the hidraw node of the receiver,
    // so it is safe to allow it.
    if (strcmp(hid_parent_driver, kLogitechUnifyingReceiverDriver) == 0) {
      LOG(INFO) << "Found Logitech Unifying receiver. Skipping rule.";
      return IGNORE;
    }

    // An led subsystem driver is provided for this device but for historical
    // reasons we want to continue to allow raw HID access as well.
    if (strcmp(hid_parent_driver, kThingmDriver) == 0) {
      LOG(INFO) << "Found ThingM blink(1). Skipping rule.";
      return IGNORE;
    }
  }

  std::string hid_parent_path(udev_device_get_syspath(hid_parent));
  std::string usb_interface_path;
  struct udev_device* usb_interface =
      udev_device_get_parent_with_subsystem_devtype(device, "usb",
                                                    "usb_interface");

  if (usb_interface)
    usb_interface_path = udev_device_get_syspath(usb_interface);

  // Count the number of children of the same HID parent as us.
  int hid_siblings = 0;

  bool should_sibling_subsystem_exclude_access = false;

  // Scan all children of the USB interface for subsystems other than generic
  // USB or HID, and all the children of the same HID parent device.
  // The presence of such subsystems is an indication that the device is in
  // use by another driver.
  //
  // Because udev lacks the ability to filter an enumeration by arbitrary
  // ancestor properties (e.g. "enumerate all nodes with a usb_interface
  // ancestor") we have to scan the entire set of devices to find potential
  // matches.
  struct udev* udev = udev_device_get_udev(device);
  ScopedUdevEnumeratePtr enumerate(udev_enumerate_new(udev));
  udev_enumerate_scan_devices(enumerate.get());
  struct udev_list_entry* entry;
  udev_list_entry_foreach(entry,
                          udev_enumerate_get_list_entry(enumerate.get())) {
    const char* syspath = udev_list_entry_get_name(entry);
    ScopedUdevDevicePtr child(udev_device_new_from_syspath(udev, syspath));
    struct udev_device* child_usb_interface =
        udev_device_get_parent_with_subsystem_devtype(child.get(), "usb",
                                                      "usb_interface");
    struct udev_device* child_hid_parent =
        udev_device_get_parent_with_subsystem_devtype(child.get(), "hid",
                                                      nullptr);
    if (!child_usb_interface && !child_hid_parent) {
      continue;
    }
    // Some gamepads expose functionality that is only accessible through the
    // hidraw node. To allow hidraw access to such devices, skip the sibling
    // subsystem and capabilities checks if one of the siblings is a joydev
    // device.
    const char* devnode = udev_device_get_devnode(child.get());
    if (devnode && IsJoydevDeviceNode(devnode))
      return IGNORE;

    // This device shares a USB interface with the hidraw device in question.
    // Check its subsystem to see if it should block hidraw access.
    if (!should_sibling_subsystem_exclude_access && usb_interface &&
        child_usb_interface &&
        usb_interface_path == udev_device_get_syspath(child_usb_interface)) {
      should_sibling_subsystem_exclude_access =
          ShouldSiblingSubsystemExcludeHidAccess(child.get());
    }
    // This device shares the same HID device as parent, count it.
    if (child_hid_parent &&
        hid_parent_path == udev_device_get_syspath(child_hid_parent)) {
      hid_siblings++;
    }
  }

  // If the underlying device presents other interfaces, deny access to the
  // hidraw node as it may allow access to private data transmitted over these
  // interfaces.
  if (should_sibling_subsystem_exclude_access)
    return DENY;

  // If the underlying HID device presents no other interface than hidraw,
  // we can use it.
  // USB devices have already been filtered directly in the loop above.
  if (!usb_interface && hid_siblings != 1)
    return DENY;

  return IGNORE;
}

bool DenyClaimedHidrawDeviceRule::ShouldSiblingSubsystemExcludeHidAccess(
    struct udev_device* sibling) {
  const char* subsystem = udev_device_get_subsystem(sibling);
  if (!subsystem) {
    return false;
  }

  // Generic subsystems (such as "hid" or "usb") should never exclude access.
  if (std::find(kGenericSubsystems.begin(), kGenericSubsystems.end(),
                subsystem) != kGenericSubsystems.end()) {
    return false;
  }

  // Don't block hidraw access due to leds subsystem.
  if (IsCfmDevice() && strcmp(subsystem, "leds") == 0) {
    return false;
  }

  if (strcmp(subsystem, "input") == 0 &&
      !ShouldInputCapabilitiesExcludeHidAccess(
          udev_device_get_sysattr_value(sibling, "capabilities/abs"),
          udev_device_get_sysattr_value(sibling, "capabilities/rel"),
          udev_device_get_sysattr_value(sibling, "capabilities/key"))) {
    return false;
  }

  return true;
}

bool DenyClaimedHidrawDeviceRule::ShouldInputCapabilitiesExcludeHidAccess(
    const char* abs_capabilities,
    const char* rel_capabilities,
    const char* key_capabilities) {
  bool has_absolute_mouse_axes = false;
  bool has_absolute_mouse_keys = false;
  std::vector<uint64_t> capabilities;
  if (abs_capabilities) {
    if (!ParseInputCapabilities(abs_capabilities, &capabilities)) {
      // Parse error? Fail safe.
      return true;
    }

    // If the device has ABS_X and ABS_Y and no other absolute axes, it may be
    // an absolute pointing device.
    if (IsCapabilityBitSet(capabilities, ABS_X) &&
        IsCapabilityBitSet(capabilities, ABS_Y)) {
      UnsetCapabilityBit(&capabilities, ABS_X);
      UnsetCapabilityBit(&capabilities, ABS_Y);
      if (!AnyCapabilityBitsSet(capabilities))
        has_absolute_mouse_axes = true;
    }

    // Remove allowed capabilities. Any other absolute pointer capabilities
    // exclude access.
    for (size_t i = 0; i < base::size(kAllowedAbsCapabilities); ++i)
      UnsetCapabilityBit(&capabilities, kAllowedAbsCapabilities[i]);
    if (AnyCapabilityBitsSet(capabilities))
      return true;
  }

  if (rel_capabilities) {
    if (!ParseInputCapabilities(rel_capabilities, &capabilities)) {
      // Parse error? Fail safe.
      return true;
    }
    // Any relative pointer capabilities exclude access.
    if (AnyCapabilityBitsSet(capabilities))
      return true;
  }

  if (key_capabilities) {
    if (!ParseInputCapabilities(key_capabilities, &capabilities)) {
      // Parse error? Fail safe.
      return true;
    }

    // If the device has BTN_LEFT, BTN_RIGHT, BTN_MIDDLE and no other keys,
    // it may be an absolute pointing device.
    if (IsCapabilityBitSet(capabilities, BTN_LEFT) &&
        IsCapabilityBitSet(capabilities, BTN_RIGHT) &&
        IsCapabilityBitSet(capabilities, BTN_MIDDLE)) {
      UnsetCapabilityBit(&capabilities, BTN_LEFT);
      UnsetCapabilityBit(&capabilities, BTN_RIGHT);
      UnsetCapabilityBit(&capabilities, BTN_MIDDLE);
      if (!AnyCapabilityBitsSet(capabilities))
        has_absolute_mouse_keys = true;
    }

    // Any key code <= KEY_KPDOT (83) excludes access.
    for (int key = 0; key <= KEY_KPDOT; key++) {
      if (IsCapabilityBitSet(capabilities, key)) {
        return true;
      }
    }
    // Braille dots are outside the "normal keyboard keys" range.
    for (int key = KEY_BRL_DOT1; key <= KEY_BRL_DOT10; key++) {
      if (IsCapabilityBitSet(capabilities, key)) {
        return true;
      }
    }
  }

  // Exclude absolute pointing devices that match joydev's capabilities check.
  if (has_absolute_mouse_axes && has_absolute_mouse_keys)
    return true;

  return false;
}

}  // namespace permission_broker
