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

namespace permission_broker {

namespace {

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

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

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

  return true;
}

bool IsCapabilityBitSet(const std::vector<uint64>& bitfield, size_t bit) {
  size_t offset = bit / (sizeof(long) * 8);  // NOLINT(runtime/int)
  if (offset >= bitfield.size()) {
    return false;
  }
  // NOLINTNEXTLINE(runtime/int)
  return bitfield[offset] & (1ULL << (bit - offset * sizeof(long) * 8));
}

}  // namespace

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

Rule::Result DenyClaimedHidrawDeviceRule::ProcessHidrawDevice(
    struct udev_device *device) {
  // For now, treat non-USB HID devices as claimed.
  struct udev_device* usb_interface =
      udev_device_get_parent_with_subsystem_devtype(
          device, "usb", "usb_interface");
  if (!usb_interface) {
    return DENY;
  }

  // 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 white-list it.
  struct udev_device* hid_parent =
      udev_device_get_parent_with_subsystem_devtype(device, "hid", NULL);
  if (hid_parent) {
    const char* hid_parent_driver = udev_device_get_driver(hid_parent);
    if (strcmp(hid_parent_driver, kLogitechUnifyingReceiverDriver) == 0) {
      LOG(INFO) << "Found Logitech Unifying receiver. Skipping rule.";
      return IGNORE;
    }
  }

  std::string usb_interface_path(udev_device_get_syspath(usb_interface));

  // Scan all children of the USB interface for subsystems other than generic
  // USB or HID. 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");
    if (!child_usb_interface) {
      continue;
    }
    std::string child_usb_interface_path(
        udev_device_get_syspath(child_usb_interface));
    // This device shares a USB interface with the hidraw device in question.
    // Check its subsystem to see if it should block hidraw access.
    if (child_usb_interface_path == usb_interface_path) {
      if (ShouldSiblingSubsystemExcludeHidAccess(child.get())) {
        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;
  }

  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) {
  std::vector<uint64> capabilities;
  if (abs_capabilities) {
    if (!ParseInputCapabilities(abs_capabilities, &capabilities)) {
      // Parse error? Fail safe.
      return true;
    }
    for (uint64 value : capabilities) {
      if (value != 0) {
        // Any absolute pointer capabilities exclude access.
        return true;
      }
    }
  }

  if (rel_capabilities) {
    if (!ParseInputCapabilities(rel_capabilities, &capabilities)) {
      // Parse error? Fail safe.
      return true;
    }
    for (uint64 value : capabilities) {
      if (value != 0) {
        // Any relative pointer capabilities exclude access.
        return true;
      }
    }
  }

  if (key_capabilities) {
    if (!ParseInputCapabilities(key_capabilities, &capabilities)) {
      // Parse error? Fail safe.
      return 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;
      }
    }
  }

  return false;
}

}  // namespace permission_broker
