From 0c1c566c3d3280f9f5e6724cc93acd08760c9f15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quentin=20Th=C3=A9bault?= Date: Tue, 21 Apr 2026 15:08:45 +0900 Subject: [PATCH] evdev: trust fds provided by a seat manager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These changes make libinput trust file descriptors provided by a seat manager (e.g. seatd) even when the device nodes are not accessible on the filesystem. This enables use cases where libinput consumers (e.g. wayland compositors) run inside containers without devfs. Closes: #1280 Signed-off-by: Quentin Thébault Sponsored-by: Defenso --- src/evdev.c | 18 ++++++++---------- src/path-seat.c | 14 +++++++++++++- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index cac971f4..ac633cac 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -2095,23 +2095,21 @@ static bool evdev_device_have_same_syspath(struct udev_device *udev_device, int fd) { struct udev *udev = udev_device_get_udev(udev_device); - struct udev_device *udev_device_new = NULL; + _unref_(udev_device) *udev_device_new = NULL; struct stat st; - bool rc = false; if (fstat(fd, &st) < 0) - goto out; + return false; udev_device_new = udev_device_new_from_devnum(udev, 'c', st.st_rdev); + /* In a jail/container where devfs doesn't expose the device, we + * cannot verify the syspath. Trust the fd provider (e.g. seatd). + */ if (!udev_device_new) - goto out; + return true; - rc = streq(udev_device_get_syspath(udev_device_new), - udev_device_get_syspath(udev_device)); -out: - if (udev_device_new) - udev_device_unref(udev_device_new); - return rc; + return streq(udev_device_get_syspath(udev_device_new), + udev_device_get_syspath(udev_device)); } static bool diff --git a/src/path-seat.c b/src/path-seat.c index d76bea0a..6c496d47 100644 --- a/src/path-seat.c +++ b/src/path-seat.c @@ -332,8 +332,20 @@ udev_device_from_devnode(struct libinput *libinput, struct stat st; size_t count = 0; - if (stat(devnode, &st) < 0) + if (stat(devnode, &st) < 0) { +#ifdef __FreeBSD__ + /* + * If stat fails (e.g. device node not visible in a jail), fall + * back to creating a udev device directly from the devnode + * path. This works in FreeBSD because libudev-devd constructs + * devices using the information exposed by the kernel through + * the sysctl interface. + */ + return udev_device_new_from_syspath(udev, devnode); +#else return NULL; +#endif + } dev = udev_device_new_from_devnum(udev, 'c', st.st_rdev);