// 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 <limits>
#include <string>
#include <vector>

#include "base/containers/adapters.h"
#include "base/logging.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 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 whitelist 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 USB/HID is okay.
  if (strcmp(subsystem, "hid") == 0 ||
      strcmp(subsystem, "hidraw") == 0 ||
      strcmp(subsystem, "usb") == 0 ||
      strcmp(subsystem, "usbmisc") == 0) {
    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 whitelisted capabilities. Any other absolute pointer capabilities
    // exclude access.
    for (size_t i = 0; i < arraysize(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
