mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-04 05:50:26 +01:00
evdev: remove a race condition opening the wrong device
Potential race condition: - udev notifies us that a udev_device became available - we go for a coffee and chat to the neighbours on the way - the device is unplugged - a new device is plugged in, gets the same devnode - we finish our coffee and come back - open(udev_device_get_devnode()) - new device is now opened as the old device To avoid the above race, we compare the syspath of the device at the open fd with the syspath of the device we originally wanted. If they differ, we fail. evdev_compare_syspath was simply moved up. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
parent
0f8aa6d46c
commit
9f225f8ea5
1 changed files with 26 additions and 23 deletions
49
src/evdev.c
49
src/evdev.c
|
|
@ -1447,6 +1447,29 @@ evdev_notify_added_device(struct evdev_device *device)
|
|||
notify_added_device(&device->base);
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_device_compare_syspath(struct udev_device *udev_device, int fd)
|
||||
{
|
||||
struct udev *udev = udev_device_get_udev(udev_device);
|
||||
struct udev_device *udev_device_new;
|
||||
struct stat st;
|
||||
int rc = 1;
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
goto out;
|
||||
|
||||
udev_device_new = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
|
||||
if (!udev_device_new)
|
||||
goto out;
|
||||
|
||||
rc = strcmp(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;
|
||||
}
|
||||
|
||||
struct evdev_device *
|
||||
evdev_device_create(struct libinput_seat *seat,
|
||||
struct udev_device *udev_device)
|
||||
|
|
@ -1469,6 +1492,9 @@ evdev_device_create(struct libinput_seat *seat,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (evdev_device_compare_syspath(udev_device, fd) != 0)
|
||||
goto err;
|
||||
|
||||
device = zalloc(sizeof *device);
|
||||
if (device == NULL)
|
||||
goto err;
|
||||
|
|
@ -1907,29 +1933,6 @@ evdev_device_suspend(struct evdev_device *device)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_device_compare_syspath(struct udev_device *udev_device, int fd)
|
||||
{
|
||||
struct udev *udev = udev_device_get_udev(udev_device);
|
||||
struct udev_device *udev_device_new;
|
||||
struct stat st;
|
||||
int rc = 1;
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
goto out;
|
||||
|
||||
udev_device_new = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
|
||||
if (!udev_device_new)
|
||||
goto out;
|
||||
|
||||
rc = strcmp(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;
|
||||
}
|
||||
|
||||
int
|
||||
evdev_device_resume(struct evdev_device *device)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue