我在这里使用 evdev 和 uinput编写了一个伪和弦键盘重映射器。我不想让我的普通用户读取和写入 /dev/input/event* 和 /dev/uinput 的权限,所以我创建了一个新用户 (hopr),其唯一目的是运行程序。在尝试使其工作时,我注意到 uinput 的一些非常特殊的行为,我希望有人可以解释。
为了确保这是关于 uinput 而不是别的,我使用 python-evdev 编写了一个简单的测试脚本:
from evdev import UInput, ecodes
KEY_RELEASE = 0L
KEY_PRESS = 1L
ui = UInput()
ui.write(ecodes.EV_KEY, ecodes.KEY_A, KEY_PRESS)
ui.write(ecodes.EV_KEY, ecodes.KEY_A, KEY_RELEASE)
ui.syn()
ui.close()
我还创建了一个名为 hopr 的新用户和一个名为 uinput 的新组,并将 hopr 添加到组 uinput 和 input(以读取事件)。计划是将 /dev/uinput 的组更改为 uinput,并且该组只有 rw 权限。两个用户的组是:
user: user adm cdrom sudo dip plugdev lpadmin sambashare
hopr: hopr input uinput
首先,我只是尝试在不更改组且在 /etc/udev/rules.d 中没有额外规则的情况下运行脚本。默认情况下,XUbuntu 16.04 中 /dev/uinput 的权限对于用户 root 和组 root 是 rw。
crw-rw----+ 1 root root 10, 223 mar 23 09:36 /dev/uinput
user> python test.py # OK
hopr> python test.py # evdev.uinput.UInputError: "/dev/uinput" cannot be opened for writing
看到我的普通用户能够运行脚本但新用户不能运行,我有点惊讶。接下来,我使用 chmod为每个人添加了 rw 权限:
crw-rw-rw-+ 1 root root 10, 223 mar 23 09:36 /dev/uinput
user> python test.py # OK
hopr> python test.py # OK
好的,正如预期的那样。接下来,我再次为所有人删除了 rw 并使用 chown将组更改为 uinput :
crw-rw----+ 1 root uinput 10, 223 mar 23 09:36 /dev/uinput
user> python test.py # OK
hopr> python test.py # evdev.uinput.UInputError: "/dev/uinput" cannot be opened for writing
同样,这是出乎意料的,但情况变得更糟。接下来,我再次为每个人添加了 rw 权限,但保留了组 uinput
crw-rw-rw-+ 1 root uinput 10, 223 mar 23 09:36 /dev/uinput
user> python test.py # OK
hopr> python test.py # evdev.uinput.UInputError: "/dev/uinput" cannot be opened for writing
现在我真的很困惑,但是使用 chown将组更改回 root使它再次工作
crw-rw-rw-+ 1 root root 10, 223 mar 23 09:36 /dev/uinput
user> python test.py # OK
hopr> python test.py # OK
显然这里有些东西我不明白,所以我也尝试使用 /dev/udev/rules.d 中的规则正确设置它:
KERNEL=="uinput*", GROUP="uinput", MODE="0660"
令我惊讶的是,现在一切都(几乎)按预期工作!受限的 hopr 用户可以在没有 rw 权限的情况下运行程序。唯一的问题是为什么我的普通用户也可以运行它。
crw-rw----+ 1 root uinput 10, 223 mar 23 09:58 /dev/uinput
user> python test.py # OK
hopr> python test.py # OK
所以,我的问题是:
- 为什么我的默认用户可以使用 /dev/uinput 尽管文件权限说我不应该能够?我该如何关闭它?
- 为什么我不能只是 chown 组?为什么我必须在 /etc/udev/rules.d 中使用规则?
- chmod/chown、rules 和 uinput 到底发生了什么?为什么受限制的 hopr 用户不能使用 uinput,尽管当组被 chown 为 uinput 时,每个人都 rw,但是当组是 root 时它可以?
- 在 /etc/udev/rules.d 中使用规则是设置它的正确方法吗?我可以期望这样的设置适用于所有/大多数 linux 版本吗?我注意到 Ubuntu 15.04 对 /dev/uinput 有不同的默认权限。