Skip to content
Permalink
Browse files

Add support for sysctl-based evdev property enumeration

A big security advantage of Wayland is not allowing applications to
read input devices all the time. Having /dev/input/* accessible to
the user account subverts this advantage.

libudev-devd was opening the evdev devices to detect their types (mouse,
keyboard, touchpad, etc). This does not work when /dev/input/* is
inaccessible.

With the kernel exposing this information via sysctls, we can work without
/dev/input/* access, preserving the Wayland security model.
  • Loading branch information
myfreeweb authored and zeising committed Dec 30, 2018
1 parent 2001db6 commit 8efdba3cd5d28dcd4dc847995670d7e2b4392b21
Showing with 48 additions and 2 deletions.
  1. +48 −2 udev-utils.c
@@ -310,9 +310,10 @@ void
create_evdev_handler(struct udev_device *ud)
{
struct udev_device *parent;
const char *sysname;
char name[80], product[80], phys[80];
const char *sysname, *unit;
char name[80], product[80], phys[80], mib[32];
int fd, input_type = IT_NONE;
size_t len;
bool opened = false;
bool has_keys, has_buttons, has_lmr;
bool has_rel_axes, has_abs_axes, has_mt;
@@ -322,6 +323,50 @@ create_evdev_handler(struct udev_device *ud)
unsigned long prp_bits[NLONGS(INPUT_PROP_CNT)];
struct input_id id;

sysname = udev_device_get_sysname(ud);
len = syspathlen_wo_units(sysname);
unit = sysname + len;

snprintf(mib, sizeof(mib), "kern.evdev.input.%s.name", unit);
len = sizeof(name);
if (sysctlbyname(mib, name, &len, NULL, 0) < 0)
goto use_ioctl;

snprintf(mib, sizeof(mib), "kern.evdev.input.%s.phys", unit);
len = sizeof(phys);
if (sysctlbyname(mib, phys, &len, NULL, 0) < 0)
goto use_ioctl;

snprintf(mib, sizeof(mib), "kern.evdev.input.%s.id", unit);
len = sizeof(id);
if (sysctlbyname(mib, &id, &len, NULL, 0) < 0)
goto use_ioctl;

snprintf(mib, sizeof(mib), "kern.evdev.input.%s.key_bits", unit);
len = sizeof(key_bits);
if (sysctlbyname(mib, key_bits, &len, NULL, 0) < 0)
goto use_ioctl;

snprintf(mib, sizeof(mib), "kern.evdev.input.%s.rel_bits", unit);
len = sizeof(rel_bits);
if (sysctlbyname(mib, rel_bits, &len, NULL, 0) < 0)
goto use_ioctl;

snprintf(mib, sizeof(mib), "kern.evdev.input.%s.abs_bits", unit);
len = sizeof(abs_bits);
if (sysctlbyname(mib, abs_bits, &len, NULL, 0) < 0)
goto use_ioctl;

snprintf(mib, sizeof(mib), "kern.evdev.input.%s.props", unit);
len = sizeof(prp_bits);
if (sysctlbyname(mib, prp_bits, &len, NULL, 0) < 0)
goto use_ioctl;

goto found_values;

use_ioctl:
ERR("sysctl not found, opening device and using ioctl");

fd = path_to_fd(udev_device_get_devnode(ud));
if (fd == -1) {
fd = open(udev_device_get_devnode(ud), O_RDONLY | O_CLOEXEC);
@@ -341,6 +386,7 @@ create_evdev_handler(struct udev_device *ud)
goto bail_out;
}

found_values:
/* Derived from EvdevProbe() function of xf86-input-evdev driver */
has_keys = bit_find(key_bits, 0, BTN_MISC);
has_buttons = bit_find(key_bits, BTN_MISC, BTN_JOYSTICK);

0 comments on commit 8efdba3

Please sign in to comment.
You can’t perform that action at this time.