【问题标题】:Disabling specific USB devices禁用特定的 USB 设备
【发布时间】:2014-01-08 01:04:17
【问题描述】:

我需要在 linux(确切地说是 debian)中编写一个程序,如果它没有通过特定的过滤器,它会禁用 USB 设备。例如,该程序可能被设置为禁止使用网络摄像头、USB 记忆棒和键盘,启用鼠标和打印机(通过 USB)。过滤器可能会在运行时更改。例如,程序可能会收到一条启用 USB 记忆棒的消息,它应该在不重新启动系统的情况下做出响应。该程序是用 python 编写的,但嵌入 c 代码(或其他代码)也是可以接受的。

我的尝试

我尝试了很多方法,但其中一些与编程无关。

首先,我试图弄乱 udev。我可以监控插入设备时的活动并编写过滤器。曾经有一个选项“ignore_device”忽略过滤的设备。例如,要忽略属于 usb 子系统成员的所有设备,我会将其编写为 udev 规则:

ACTION=="add", SUBSYSTEM=="usb", OPTIONS+="ignore_device"

但是这个选项是在 udev 的this 版本中发布的。到目前为止,我得到的是 udev 目前主要用于监控。当然,我可以为上面运行脚本的规则编写额外的规则,但我必须在其他地方进行禁用。

其次,我尝试使用 ioctl 向设备句柄发送 DISCONNECT 信号。我正在用 USB 鼠标对此进行测试。这是python代码:(我也在C中尝试过,没有任何改变)

import fcntl
import sys
USBDEVFS_RESET = ord('U') << (4*2) | 20
USBDEVFS_DISCONNECT = ord('U') << (4*2) | 22
raw_name = "/dev/bus/usb/{:03d}/{:03d}"
filename = raw_name.format(1,2)
fd = open(filename, "wb")
fcntl.ioctl(fd, USBDEVFS_DISCONNECT, 0)

在这里,如果我发送 USBDEVFS_RESET,它会起作用,鼠标输入会被忽略一两秒。但是断开信号会引发错误:

IOError: [Errno 25] Inappropriate ioctl for device

我从这里得到的是,我无法向鼠标发送断开信号。也许 USB 棒或打印机或其他一些设备可以工作,我没有尝试过。我想开发尽可能通用的程序,以防止编写额外的设备特定代码,所以这种方法对我来说似乎没用。这里的另一点是,当我手动断开/连接鼠标时,我会在 udev 监视器中看到事件。但是当我发送复位信号时,没有发送任何事件。

udev 监视器显示鼠标已安装到此路径:/sys/bus/usb/devices/1-3(这是/sys/devices/pci0000:00/0000:00:14.0/usb1/1-3 的符号链接)。一些文件告诉我,此文件夹包含设备的设置,将 /power/level 设置为“关闭”或“暂停”将关闭设备电源。但我无法操作 /power 中的任何文件。仔细想想,这毕竟不是一个好主意。

问题

那么,问题是,完成这项任务的最佳方法是什么?我有一个想法,但我不确定它是否会起作用,即使它起作用,也可能是矫枉过正。我的想法是编写一个“包装驱动程序”,将自己标识为 linux 内核作为所有 USB 设备的驱动程序。 “包装器驱动程序”读取设备信息,如果设备运行良好,它充当内核中真实驱动程序的包装器,调用它们的函数。如果不是,“包装器驱动程序”将忽略该设备。

我什至不确定它是否可以完成,我在内核或驱动程序编程方面没有经验。

另一种方法是,以某种方式 - 以编程方式获取设备的句柄并告诉它关闭电源(或让它永远忙,无论什么工作)。我也做了一些小研究,但找不到合适的简单方法。他们说所有设备都被视为“文件”,但我根本无法访问这些文件。

注意: 这个问题主要是关于 linux 内部的,但它也涉及内核编程。我阅读了很多关于 USB 操作/监控程序的内容,我阅读了 udevadm 的手册页。但是这些方法对我一点帮助都没有。我认为我需要以编程方式更改内核或设备内部。

我还尝试操作位于/sys/devices/pci0000:00/0000:00:14.0/usb1/1-4 中的authorized 文件(用于键盘)。它的默认值为 1。将其更改为 0 成功禁用总线(不是设备,而是物理 USB 端口。插入另一个端口时仍然可以使用相同的设备)。但是将其设为 0 也会阻止来自此 USB 端口的 udev 事件。因此,如果用户插入禁用的设备,我可以禁用该端口,但我无法决定何时启用它,因为我无法在 udev 中侦听 remove 事件。如果我深入研究较低级别的代码(可能是内核)并以其他方式监听 USB 事件,这是否有意义?

【问题讨论】:

  • 删除内核驱动程序并从系统中删除模块,然后锁定原始设备节点以阻止未授权的用户空间客户端。但是考虑到整个想法对某个坚定的人的保护很弱。
  • @ChrisStratton 嘿,讨厌游戏,而不是玩家......
  • 对不起,这正在变成一场纯粹的配置辩论,它属于超级用户,而不是这里。

标签: linux linux-kernel usb kernel linux-device-driver


【解决方案1】:

我认为解决您的问题的最简单方法是将所有 USB 设备驱动程序列入黑名单,鼠标、键盘等除外。

最简洁的方法是使用 udev 使用 USB 设备 ID 将鼠标等列入白名单

【讨论】:

  • 如果黑名单是指通过 /etc/modprobe.d/(something).conf 将设备列入黑名单,这会在内核启动时禁用设备。我希望能够在运行时更改设置,而无需重新启动。不过谢谢!
  • 我在原问题中没有写任何关于重启的内容,现在我编辑了它。
【解决方案2】:

编写包装器驱动程序绝对是矫枉过正,从来没有选择过这种方式。

一种可能的解决方案是将 USB 访问权限与用户权限绑定。这是一个相关链接,您可能会觉得方便

http://robots.mobilerobots.com/wiki/Linux_udev_USB_Device_Permissions_Configuration

【讨论】:

  • 这可能有助于防止某人通过 libusb 或类似工具进行自己的访问,但对内核驱动程序几乎没有作用。
  • 如果在任何情况下,有一个根进程正在访问 USB 设备并向用户进程(如代理服务器)发送数据,则几乎无法检测到。
  • 如果用户有 root 权限,您可以通过多种方式绕过,至少无需更复杂的方法。
  • 用户没有root权限,但管理员可能会安装使用我们标记为禁止的某些设备的软件。由于该软件以 root 身份运行,因此它可以访问该设备。如果用户可以通过该软件以某种方式监控设备属性或内容,那么这种方法是有问题的。我知道管理员不应该安装这样的软件,但总比抱歉更安全。
  • 说白了,你的“管理员”必须接受你的“禁止” 当那些不认真对待你的问题的人开始制造时,你最终不会得到一个安全的系统对其进行随机更改。这个问题似乎进入了离题领域。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-12
  • 2015-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多