Crab213's Blog.

在Linux系统中禁用USB端口

2018/04/28

简单禁用单个端口

使用udev进行禁用。每个USB端口在sysfs中都有一个名为authorized的属性,该属性的值表表示该PORT上的设备是否获得内核的授权,没有授权的设备,内核不会让其被用户态访问。

可以编写udev rules文件禁用特定的USB端口, 首先确定USB端口的名称,可以通过运行:

1
lsusb -t

命令查看。找出对应的USB端口之后(这里为1-10,其中1代表USB总线编号,10表示port编号),之后编写对应的udev文件/etc/udev/rules.d/99-usb-lockdown.rules

1
ACTION=="add", SUBSYSTEMS=="usb", KERNEL=="1-10", RUN+="/bin/sh -c 'echo 0 >/sys$DEVPATH/authorized'"

即可禁用编号为1-10的port。事实上,通过这个接口还可以实现在用户态实现重置USB端口:

1
2
echo 0 > /sys/$DEVPATH/authorized
echo 1 > /sys/$DEVPATH/authorized

$DEVPATH修改为对应的port名称即可。如果port上差的是一个hub,则该hub下的所有USB端口都会被禁用。

动态禁用USB端口

如果需要实现动态进行USB设备禁用,可以通过编写简单脚本的方式完成:

  • 直接配置udev rules运行特定脚本(或者自己开发的程序),通过%k和%p以命令行参数的形式传入KERNELDEVPATH变量
  • 在上述脚本中读取全局配置文件,通过比较KERNEL变量对特定的USB端口进行禁用,其余USB端口保持原样不动
  • 可以通过修改配置文件动态配置,由于每次USB设备插入时都需要重新读取配置文件,所以配置文件是即时生效的。

附上用于验证的udev rules和测试用的脚本及测试文件:

/usr/bin/blockusb.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash

KERNEL=$1
DEVPATH=$2

. /etc/usblock

block_usb() {
echo 0 > "/sys$DEVPATH/authorized"
}

for item in "${USBLOCK[@]}"; do
[ "$item" == "$KERNEL" ] && block_usb
done

/etc/udev/rules.d/99-usb-lock-down.rules

1
ACTION=="add", SUBSYSTEMS=="usb", RUN+="/usr/bin/blockusb.sh %k %p"

/etc/usblock

1
USBLOCK=(1-10 2-2)

可以使用以下命令重新载入udev rules:

1
udevadm control --reload-rules && udevadm trigger

关于USB设备的authorized接口,可以参考内核文档。需要注意的是,端口名并不是严格对应于物理端口的,很多USB主控都使用companion模式实现对多种USB协议的支持。在该模式下,一个USB3.0的端口插入一个USB2.0的设备之后,会被挂入一个对应companion USB2.0总线上,导致总线编号的改变。也就是说,使用上述脚本的时候需要将companion主控的情况也考虑在内。

CATALOG
  1. 1. 简单禁用单个端口
  2. 2. 动态禁用USB端口