我正在使用 GSM 调制解调器并使用/dev/ttyUSB2
设备。
设备拥有适当的权利:
$ ls -alh /dev/ttyUSB2
crw-rw---- 1 root dialout 188, 2 May 25 19:44 /dev/ttyUSB2
我在dialout
组中,只能向该调制解调器发送一次 AT 命令。发送“ATD”命令(echo -e -n "ATD ...;\r" > /dev/ttyUSB2
)后,根据lsof /dev/ttyUSB2
进程ModemManager
打开这个文件,如果我发送另一个 AT 命令,我会收到消息:
bash: /dev/ttyUSB2: Device or resource busy
好的,由于某种原因,ModemManager 使该文件处于忙碌状态,但是当发生这种情况时,我仍然可以以相同的方式发送命令,但来自root
用户。
我有两个问题:
- 为什么 root 用户可以覆盖此“设备或资源繁忙”锁定?
- 普通用户应该像根用户一样绕过它的哪些权限/其他设置。
答案1
我最近在 Gentoo 上使用时遇到了类似的错误wvdial
(使用正确配置的内核、usb_modeswitch
设置、验证 wvdial 设置可以在另一个系统上工作等)。正如您所描述的,root 可以轻松初始化调制解调器并连接到 Internet,而dialout
组中的用户会收到与您非常相似的错误消息。相关的设备文件是:
$ ls -l /dev/ttyUSB2
crw-rw---- 1 root dialout 188, 2 Apr 6 01:43 /dev/ttyUSB2
问题原来是 wvdial 无法在我的系统上/run/lock
拥有的下创建必要的锁定文件。root:uucp
将我的常规用户添加到 后uucp
,可以创建锁定文件:
$ ls -la /run/lock
drwxrwxr-x 2 root uucp 80 Apr 6 01:43 .
drwxr-xr-x 10 root root 520 Apr 6 01:44 ..
-rw-r--r-- 1 foo foo 11 Apr 6 01:43 LCK..ttyUSB2
[...]
并且用户能够成功连接,就像 root 一样。 (如果您想知道,find / -group uucp
则不会返回除该文件夹之外的任何内容。)
我不熟悉ModemManager
(也不习惯直接写入/读取设备文件),但考虑到我们描述的相似性,我怀疑您可能需要将常规用户添加到另一个补充组。尝试以 root 身份建立连接并检查 ModemManager 涉及哪些其他文件;其中之一(或父目录)可能是问题的根源。
答案2
如果你看一下代码tty_reopen()
Linux 内核源码中的函数,本身由tty_open_current_tty()
自身调用,由其tty_open()
注册为open
tty文件操作的函数:
if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN))
return -EBUSY;
EBUSY
如果 tty 已标记为TTY_EXCLUSIVE
(通过 a ioctl(TIOCEXCL)
)并且该进程无法执行,则返回CAP_SYS_ADMIN
。
它记录在tty_ioctl
手册页中:
独占模式
TIOCEXCL
void
将终端置于独占模式。open
不允许在终端上进行进一步的(2) 操作。 (EBUSY
除了具有该功能的进程之外,它们都会失败CAP_SYS_ADMIN
。)
TIOCGEXCL
int *argp
(自Linux 3.8起)如果终端当前处于独占模式,则在argp指向的位置放置一个非零值;否则,将零放入 *argp 中。
TIOCNXCL
void
禁用独占模式。
因此,在这里,ModemManager
可能打开了设备并调用ioctl(TIOCEXCL)
它,因此除了那些运行root
(或有CAP_SYS_ADMIN
能力)的进程之外,没有其他进程可以打开它。
你可以看到它在代码中的函数ioctl()
中执行此操作port_connected()
有了这个评论:
/* When the port is connected, drop the serial port lock so PPP can do
* something with the port. When the port is disconnected, grab the lock
* again.
*/