AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 740428
Accepted
Arash Rohani
Arash Rohani
Asked: 2023-03-21 14:10:33 +0800 CST2023-03-21 14:10:33 +0800 CST 2023-03-21 14:10:33 +0800 CST

udev 如何/在何处授予 X11 输入驱动程序打开 /dev/input/event* 文件的权限,而不同时授予已登录用户的访问权限?

  • 772

这是我的 /dev/input/event* 文件的权限:

crw-rw---- 1 root input 13, 64 Mar 21 09:02 /dev/input/event0
crw-rw---- 1 root input 13, 65 Mar 21 09:02 /dev/input/event1
crw-rw---- 1 root input 13, 66 Mar 21 09:02 /dev/input/event2
crw-rw---- 1 root input 13, 67 Mar 21 09:02 /dev/input/event3
crw-rw---- 1 root input 13, 68 Mar 21 09:02 /dev/input/event4
...

+如您所见,权限后没有,这意味着没有特殊的 ACL 权限。我也确认了getfacl。我也不是该input组的成员,也没有以 root 身份运行 X11。我只是startx在以用户身份登录后手动在控制台中键入以启动 xorg。

所以我的问题是udev如何以及在何处允许 X11 输入驱动程序(例如 xf86-input-libinput)在没有 ACL 的情况下打开那些文件?

如果我想打开 /dev/input/event 文件,我必须使用sudo或成为input组的一部分,但无根 X11 似乎能够毫无问题地做到这一点!


这是一个演示权限问题的最小 c 程序。如果 keybit_limit 设置为低于 578 的任何值,X11 驱动程序将有权读取相应的 /dev/input/event 并且具有您给定名称的设备将显示在 xinput 输出中。任何高于 KEY_CNT 的值都会导致 Xorg 日志中出现权限错误,并且 xinput 不会显示新设备。尽管您仍然可以看到带有sudo evtest. 两种情况下/dev/input/event的权限和组是完全一样的,但是在KEY_CNT场景下X11无法读取,1 2 3 key不会在Xorg中注册。

#include <stdio.h>
#include <sys/ioctl.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/uinput.h>

#define ERROR(format, ...) {                                             \
    fprintf(stderr, "\x1b[31merror: " format "\x1b[0m\n", ##__VA_ARGS__); \
    return 1;                                                            \
}

#define SEND_EVENT(ev_type, ev_code, ev_value) { \
    uev.type = ev_type;                          \
    uev.code = ev_code;                          \
    uev.value = ev_value;                        \
    write(ufd, &uev, sizeof(uev));               \
}

int main(int argc, char *argv[]) {

    if (argc < 2) ERROR("needs uinput device name!");

    int ufd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
    if (ufd < 0) ERROR("could not open '/dev/uinput'");
    ioctl(ufd, UI_SET_EVBIT, EV_KEY);

    int keybit_limit;

    /* X11 will recognize this device for me */
    // keybit_limit = 577;

    /* but anything above that will cause permission denied errors in xorg log and xinput will not show the device */
    keybit_limit = KEY_CNT;

    for (int i = 0; i < keybit_limit; i++) {
        if (ioctl(ufd, UI_SET_KEYBIT, i) < 0) ERROR("cannot set uinput keybit: %d", i);
    }

    struct uinput_setup usetup;
    memset(&usetup, 0, sizeof(usetup));
    usetup.id.bustype = BUS_USB;
    strcpy(usetup.name, argv[1]);
    if (ioctl(ufd, UI_DEV_SETUP, &usetup) < 0) ERROR("cannot set up uinput device");
    if (ioctl(ufd, UI_DEV_CREATE) < 0) ERROR("cannot create uinput device");
    struct input_event uev;
    uev.time.tv_sec = 0;
    uev.time.tv_usec = 0;

    sleep(1);

    /* press 1 2 3 */
    SEND_EVENT(EV_KEY, KEY_1, 1);
    SEND_EVENT(EV_KEY, KEY_2, 1);
    SEND_EVENT(EV_KEY, KEY_3, 1);
    SEND_EVENT(EV_SYN, SYN_REPORT, 0);

    /* release 1 2 3 */
    SEND_EVENT(EV_KEY, KEY_1, 0);
    SEND_EVENT(EV_KEY, KEY_2, 0);
    SEND_EVENT(EV_KEY, KEY_3, 0);
    SEND_EVENT(EV_SYN, SYN_REPORT, 0);

    /* give you time to check xinput */
    sleep(300);

    ioctl(ufd, UI_DEV_DESTROY);
    close(ufd);
    return 0;
}

以下是 ~/.local/share/xorg/Xorg.0.log 文件中的权限错误,当keybit_limit = KEY_CNT传递给程序的 uinput 设备名称为“MYDEVICE”时:

[ 28717.931] (II) config/udev: Adding input device MYDEVICE (/dev/input/event24)
[ 28717.931] (**) MYDEVICE: Applying InputClass "libinput pointer catchall"
[ 28717.931] (**) MYDEVICE: Applying InputClass "libinput keyboard catchall"
[ 28717.931] (**) MYDEVICE: Applying InputClass "system-keyboard"
[ 28717.931] (II) Using input driver 'libinput' for 'MYDEVICE'
[ 28717.933] (EE) systemd-logind: failed to take device /dev/input/event24: No such device
[ 28717.933] (**) MYDEVICE: always reports core events
[ 28717.933] (**) Option "Device" "/dev/input/event24"
[ 28717.933] (EE) xf86OpenSerial: Cannot open device /dev/input/event24
    Permission denied.
[ 28717.933] (II) event24: opening input device '/dev/input/event24' failed (Permission denied).
[ 28717.933] (II) event24 - failed to create input device '/dev/input/event24'.
[ 28717.933] (EE) libinput: MYDEVICE: Failed to create a device for /dev/input/event24
[ 28717.933] (EE) PreInit returned 2 for "MYDEVICE"
[ 28717.933] (II) UnloadModule: "libinput"

我已经使用 xorg.conf.d 文件测试了 X11 的 evdev 和 libinput 驱动程序,两者的行为相同。如果我将自己放在input组中或在设备的 udev 规则中使用 uaccess 标记,则 X11 驱动程序可以读取它。这表明在 <578 场景中设备以 root 身份读取,但在 KEY_CNT 场景中设备以用户身份读取。

这是为什么?哪个进程正在这样做?

permissions
  • 2 2 个回答
  • 59 Views

2 个回答

  • Voted
  1. telcoM
    2023-03-21T15:07:37+08:002023-03-21T15:07:37+08:00

    Udev 不会“授予 X11 输入驱动程序权限”。Udev 已经创建了您显示的设备节点,一旦完成,它关于输入设备的工作就基本完成了。系统的其余部分将必须处理它指定的设备权限。

    startx/usr/bin/xinit通常是用于完成其工作的脚本。

    事实证明,在现代 Xorg X 服务器中,setuid root 权限是作为一个小的独立包装器实现的,/usr/lib/xorg/Xorg.wrap. 手册Xwrapper.config(5)页说:

    描述

    Xorg X 服务器可能需要 root 权限才能正常运行。要使用这些权限启动 Xorg X 服务器,您的系统正在使用安装为 /usr/lib/xorg/Xorg.wrap 的 suid root 包装器,它将执行安装为/usr/lib/xorg/Xorg.

    默认情况下,Xorg.wrap 将自动检测是否需要 root 权限,如果不需要,它将在启动真正的 X 服务器之前放弃其提升的权限。默认情况下,Xorg.wrap 将只允许在物理控制台上从登录会话执行真正的 X 服务器。

    这是在 Debian 11 上;您的发行版可能使用了不同的路径。

    运行ls -l /usr/bin/xinit /usr/bin/Xorg /usr/lib/xorg/Xorg.wrap。如果它报告的权限包含 ans而不是通常的x,那么您的答案是:如果 thes位于第一个x位置 ( ),则可执行文件将以文件所有者的-rws......权限运行(在类似情况下通常是 root这)。这通常称为可执行文件是setuid root或suid root。

    如果在第二个位置,进程将在运行时获得拥有可执行文件的组s的成员身份 :这被称为可执行文件是该组的setgid或sgid 。(请注意,在目录或不可执行文件上,setgid 权限位可能有其他含义,具体取决于所使用的文件系统类型。)

    请注意,复制文件时通常不会复制 setuid 和 setgid 权限位:即使复制了,当您复制 root 拥有的文件时,新副本将归您所有,而不是 root。它可能允许其他用户像您一样运行复制的可执行文件,但它不会帮助您成为 root。要在完全保留权限的同时复制setuid root文件,您必须自己成为 root。

    • 1
  2. Best Answer
    user1686
    2023-03-22T01:29:10+08:002023-03-22T01:29:10+08:00

    Xorg 不直接打开设备节点——它使 D-Bus IPC 调用systemd-logind服务,它代表调用者打开设备节点(在检查诸如哪个用户在前台 tty 上“登录”之类的事情之后)并使用 D-Bus 的 fd 传递功能(基于 Unix 套接字中的 SCM_CREDENTIALS 功能)将文件描述符转发到 Xorg。

    有关相关的D-Bus API,请参阅org.freedesktop.login1(5)TakeDevice()。

    当前台 tty 切换到另一个用户的会话时,此方法允许 systemd-logind 主动撤销对输入设备的访问(相反,设置和删除 ACL 将允许一个用户的程序简单地保持文件描述符打开并继续读取输入,即使另一个用户的会话在前台)。

    对于非 systemd 发行版,seated 提供了功能相似的 API (libseat_open_device),但 Xorg 尚不支持它,而是依赖于 setuid 包装器Xorg.wrap。

    (撤销机制是 ioctl(EVIOCREVOKE),特定于输入设备。对于 DRM 设备有类似的东西,但到目前为止还没有类似的音频或相机设备;声音服务器如 pipewire 监听 logind 的“会话切换”信号和合作关闭和重新打开设备。)

    • 1

相关问题

  • 组权限如何工作?

  • Redis日志文件权限错误,但是权限已经是777

  • 以 root 权限启动 zypper 命令

  • 以非特权用户身份运行时,meld 无法访问 /dev/fd/* 的可能原因是什么?

  • 另一个用户的非空子目录是否可以安全地从我的目录中删除?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve