// 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));
}

// 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 (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
