This is the permission of my /dev/input/event* files:
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
...
As you can see there's no + after the permissions which means no special ACL permissions.
I also confirmed it with getfacl.
I'm not part of the input group either and am not running X11 as root.
I just manually type startx in the console after logging in as the user to start xorg.
So my question is how and where does udev give permission to X11 input drivers (e.g. xf86-input-libinput) to open the those files without ACL?
If I want to open the /dev/input/event files I have to use sudo or be part of input group but rootless X11 seems to be able to do that with no problem!
Here's a minimal c program to demonstrate the permission issue. If keybit_limit is set to anything below 578, X11 drivers will have the permission to read the corresponding /dev/input/event and a device with your given name will show up in xinput output. Anything higher than that up to KEY_CNT will cause permission errors in Xorg log and xinput won't show the new device. Although you still can see the device with sudo evtest. The permission and group of /dev/input/event in both situations are exactly the same but in the KEY_CNT scenario X11 can't read it and the 1 2 3 keys will not be registered in 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;
}
Here are the permission errors in ~/.local/share/xorg/Xorg.0.log file when keybit_limit = KEY_CNT and uinput device name passed to the program is "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"
I have tested both evdev and libinput drivers for X11 with a xorg.conf.d file and both will behave the same. If I put myself in input group or use uaccess tag in a udev rule for the device then X11 drivers can read it. This suggests that in <578 scenario the device is read as root but in the KEY_CNT scenario the device is read as user.
Why is that? And which process is doing that?