Why do /dev/input/eventX permissions differ depending on how X server is launched

command linedebianlinuxpermissionsunix

I have a simple command line binary written in C on Debian that reads USB gamepad input on /dev/input/eventX and shows which gamepad buttons are pressed. I do this by opening and reading /dev/input/eventX (whichever node has the gamepad). It works fine, without root, when:

  • The X server is launched by lightdm
  • Using a local tty (not ssh) using ctrl+alt F1

Problem is, if I disable lightdm and launch the X server manually using xinit (using the default xterm), I do not have permission to access anything in /dev/input/eventX when using xterm. This isn't a problem when lightdm is responsible for launching X, or when using a text-based tty locally.

I am not using a window manager.

Doing ls -l shows special ACL permissions (+) for the gamepad devices. So if a normal user on a tty can read this device, why can't X programs launched under the X server running under the same user account access the devices:

crw-rw----+  1 root input 13, 67 Jul 31 19:13 event3

Why is this? Why the difference in permissions if using the local text console (i.e. ctrl+alt F1,F2,etc) vs xterm?

Best Answer

The ACL entries are dynamically added/removed on tty switch and login/logout events.

  • If you log in to the console at tty2, you get device permissions.
  • If you press Alt+F3 and switch to tty3 where nobody (or another user) is logged in, you lose device permissions and the tty3 user gets them.

This means xinit needs to be used slightly differently.

  • If you log in at tty2, start an X server on tty7, and switch to tty7 – you lose device permissions, because technically there is nobody logged in on tty7 at all, and tty2 is now "inactive".
  • If you log in at tty2 and start an X server on the same tty2, you retain all permissions.

In most distributions, startx will do the right thing, but with raw xinit you may need to manually specify vt2 or vt$(fgconsole) among the X server arguments. (In general you should use startx instead of xinit.)

xinit xterm -- :0 vt$(fgconsole)
Related Question