禁用特定 USB 设备

hol*_*gac 5 linux usb kernel linux-device-driver linux-kernel

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

我尝试过的

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

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

ACTION=="add", SUBSYSTEM=="usb", OPTIONS+="ignore_device"
Run Code Online (Sandbox Code Playgroud)

但这个选项是在这个版本的 udev 中发布的。到目前为止我得到的是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)
Run Code Online (Sandbox Code Playgroud)

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

IOError: [Errno 25] Inappropriate ioctl for device
Run Code Online (Sandbox Code Playgroud)

我从这里得到的是,我无法向鼠标发送断开连接信号。也许 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 的手册页。但这些方法对我根本没有帮助。我认为我需要以编程方式更改内核或设备内部结构。

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

flo*_*tto 1

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

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