udevログインしたユーザーにアクセスを許可せずに/ dev / input / event *ファイルを開くことができるX11入力ドライバのアクセス許可をどのように/どこに追加しますか?

udevログインしたユーザーにアクセスを許可せずに/ dev / input / event *ファイルを開くことができるX11入力ドライバのアクセス許可をどのように/どこに追加しますか?

私の/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。私もこのグループのメンバーではなく、inputX11をrootとして実行しません。startxユーザーとしてログインしたら、コンソールに手動で入力してxorgを起動しました。

だから私の質問はどのようにそしてどこudevは、ACLなしでこれらのファイルを開くためのX11入力ドライバ(xf86-input-libinputなど)権限を付与しますか?

/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キーは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;
}

keybit_limit = KEY_CNT以下は、プログラムに渡されたuinputデバイス名が「MYDEVICE」の場合、~/.local/share/xorg/Xorg.0.logファイルに表示される許可エラーです。

[ 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 シナリオではデバイスがユーザとして読み取られることを示しています。

なぜそんなことですか?どのプロセスがこれを実行していますか?

ベストアンサー1

Xorgはデバイスノードを直接開けません。デバイスにD-Bus IPC呼び出しを行います。システムログイン呼び出し元に代わってデバイスノードを開き(フォアグラウンドttyでどのユーザーが「ログイン」したかなどを確認した後)、D-Busのfdパス機能SCM_CREDENTIALSを使用してファイル記述子をXorg(Unixソケットベース)に渡すサービス)の機能。

バラよりorg.freedesktop.login1(5)関連するTakeDevice()D-Bus APIの場合。

この方法を使用すると、フロント tty が別のユーザーのセッションに切り替えられたときに systemd-logind が入力デバイスへのアクセスを積極的に取り消すことができます (逆に ACL を設定および削除すると、1 人のプログラムが単にファイル記述子を開く残してinputを読み続けることができます)。他のユーザーのセッションが前景にある場合)。

システム化されていないディストリビューションの場合、Seatdは機能的に似たAPI(libseat_open_device)を提供しますが、Xorgはまだそれをサポートしておらず、代わりにsetuidXorg.wrapラッパーに依存しています。

(終了メカニズムは入力デバイス固有のioctl(EVIOCREVOKE)です。DRMデバイスにも同様のメカニズムがありますが、これまでオーディオやカメラデバイスに対応するメカニズムはありません。パイプラインなどのサウンドサーバーはログイン「セッションスイッチ」を受信します。 (信号を送信し、デバイスの電源を切ってから再びオンにすることに協力してください。)

おすすめ記事