mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-06-23 15:38:26 +02:00
evdev: verify fd via cached devnum on FreeBSD
evdev_device_have_same_syspath() guards against opening the wrong device by re-resolving the fd's st_rdev through udev and comparing syspaths. On FreeBSD this works when the input device nodes are present in the caller's devfs, but not inside a jail whose devfs does not expose them: udev_device_new_from_devnum() then has nothing to resolve, and the check rejects every fd -- even fds that a seat manager (e.g. seatd) opened on the host and passed in. On FreeBSD the evdev syspath (/dev/input/eventN) is determined by the device's minor number, while the cached devnum carries both that minor and the evdev major. Comparing the full devnum against fstat(fd).st_rdev therefore verifies the same identity as the syspath comparison -- in fact slightly more strongly, since it also confirms the major -- without needing the device node to be visible to the caller. libudev-devd populates that cached devnum from the kern.evdev.input.N.devnum sysctl, which remains readable inside a jail. Guard the new path with __FreeBSD__ and move the existing udev-based lookup into the #else branch. The lookup is rewritten to return directly on each exit instead of using a shared goto label, because the FreeBSD branch returns before those locals are declared and would otherwise leave them (and the label) unused on a FreeBSD build. Linux behaviour is unchanged. Signed-off-by: Quentin Thébault <quentin.thebault@defenso.fr> Sponsored-by: Defenso Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1471>
This commit is contained in:
parent
b12bc3b4bd
commit
4c7f7b1e5c
1 changed files with 21 additions and 11 deletions
32
src/evdev.c
32
src/evdev.c
|
|
@ -2116,24 +2116,34 @@ evdev_notify_added_device(struct evdev_device *device)
|
|||
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;
|
||||
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);
|
||||
if (!udev_device_new)
|
||||
goto out;
|
||||
#ifdef __FreeBSD__
|
||||
/* On FreeBSD the evdev syspath (/dev/input/eventN) is determined by
|
||||
* the device's minor number, while the cached devnum carries both
|
||||
* that minor and the evdev major. Comparing the full devnum against
|
||||
* the fd's st_rdev therefore verifies the same identity as the
|
||||
* syspath comparison -- in fact slightly more strongly, since it
|
||||
* also confirms the major -- without needing the device node to be
|
||||
* visible to the caller. libudev-devd populates that devnum from
|
||||
* the kern.evdev.input.N.devnum sysctl, which is readable even in a
|
||||
* jail whose devfs does not expose the input node.
|
||||
*/
|
||||
return udev_device_get_devnum(udev_device) == st.st_rdev;
|
||||
#else
|
||||
struct udev *udev = udev_device_get_udev(udev_device);
|
||||
_unref_(udev_device) *udev_device_new =
|
||||
udev_device_new_from_devnum(udev, 'c', st.st_rdev);
|
||||
bool rc = false;
|
||||
|
||||
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);
|
||||
rc = streq(udev_device_get_syspath(udev_device_new),
|
||||
udev_device_get_syspath(udev_device));
|
||||
return rc;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue