mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-06-09 23:48:22 +02:00
evdev: be stricter about devices with odd absinfo values
Reject devices that have extreme min/max values (might cause integer overflow in libinput), negative resolutions and a min > max. The former two could be triggered by malicious input devices. Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1486>
This commit is contained in:
parent
6efbf9ff74
commit
04a35384e6
2 changed files with 100 additions and 0 deletions
22
src/evdev.c
22
src/evdev.c
|
|
@ -1671,6 +1671,16 @@ evdev_check_min_max(struct evdev_device *device, unsigned int code)
|
|||
return true;
|
||||
|
||||
absinfo = libevdev_get_abs_info(evdev, code);
|
||||
|
||||
if (((uint64_t)absinfo->maximum - (uint64_t)absinfo->minimum) > INT32_MAX / 2) {
|
||||
evdev_log_bug_kernel(device,
|
||||
"kernel axis range [%d, %d] on %s too extreme\n",
|
||||
absinfo->minimum,
|
||||
absinfo->maximum,
|
||||
libevdev_event_code_get_name(EV_ABS, code));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (absinfo->minimum == absinfo->maximum) {
|
||||
/* Some devices have a sort-of legitimate min/max of 0 for
|
||||
* ABS_MISC and above (e.g. Roccat Kone XTD). Don't ignore
|
||||
|
|
@ -1690,6 +1700,18 @@ evdev_check_min_max(struct evdev_device *device, unsigned int code)
|
|||
libevdev_event_code_get_name(EV_ABS, code));
|
||||
return false;
|
||||
}
|
||||
} else if (absinfo->minimum > absinfo->maximum) {
|
||||
evdev_log_bug_kernel(device,
|
||||
"device has min > max on %s\n",
|
||||
libevdev_event_code_get_name(EV_ABS, code));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (absinfo->resolution < 0) {
|
||||
evdev_log_bug_kernel(device,
|
||||
"kernel resolution is negative on %s\n",
|
||||
libevdev_event_code_get_name(EV_ABS, code));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1656,6 +1656,77 @@ START_TEST(device_button_down_remove)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
enum extreme_axis_range_idx {
|
||||
EXTREME_RANGE_0_TO_INT32MAX,
|
||||
EXTREME_RANGE_INT32MIN_TO_0,
|
||||
EXTREME_RANGE_NEGHALF_TO_POSHALF,
|
||||
};
|
||||
|
||||
START_TEST(abs_device_extreme_axis_range)
|
||||
{
|
||||
struct libevdev_uinput *uinput;
|
||||
struct libinput_device *device;
|
||||
int idx = litest_test_param_get_i32(test_env->params, "range");
|
||||
/* All ranges exceed INT32_MAX/2, device should be rejected */
|
||||
const struct {
|
||||
int32_t min, max;
|
||||
} ranges[] = {
|
||||
[EXTREME_RANGE_0_TO_INT32MAX] = { 0, INT32_MAX },
|
||||
[EXTREME_RANGE_INT32MIN_TO_0] = { INT32_MIN, 0 },
|
||||
[EXTREME_RANGE_NEGHALF_TO_POSHALF] = { -(INT32_MAX / 2),
|
||||
INT32_MAX / 2 },
|
||||
};
|
||||
struct input_absinfo absinfo[] = {
|
||||
{ ABS_X, ranges[idx].min, ranges[idx].max, 0, 0, 0 },
|
||||
{ ABS_Y, 0, 1000, 0, 0, 0 },
|
||||
{ -1, -1, -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
_litest_context_destroy_ struct libinput *li = litest_create_context();
|
||||
litest_disable_log_handler(li);
|
||||
/* clang-format off */
|
||||
uinput = litest_create_uinput_abs_device("test device", NULL,
|
||||
absinfo,
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_RIGHT,
|
||||
-1);
|
||||
/* clang-format on */
|
||||
device = libinput_path_add_device(li, libevdev_uinput_get_devnode(uinput));
|
||||
litest_restore_log_handler(li);
|
||||
litest_assert_ptr_null(device);
|
||||
|
||||
libevdev_uinput_destroy(uinput);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(abs_device_negative_resolution)
|
||||
{
|
||||
struct libevdev_uinput *uinput;
|
||||
struct libinput_device *device;
|
||||
struct input_absinfo absinfo[] = {
|
||||
{ ABS_X, 0, 1000, 0, 0, -1 }, /* negative resolution */
|
||||
{ ABS_Y, 0, 1000, 0, 0, -1 }, /* negative resolution */
|
||||
{ -1, -1, -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
_litest_context_destroy_ struct libinput *li = litest_create_context();
|
||||
litest_disable_log_handler(li);
|
||||
/* clang-format off */
|
||||
uinput = litest_create_uinput_abs_device("test device", NULL,
|
||||
absinfo,
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_RIGHT,
|
||||
-1);
|
||||
/* clang-format on */
|
||||
device = libinput_path_add_device(li, libevdev_uinput_get_devnode(uinput));
|
||||
litest_restore_log_handler(li);
|
||||
/* Device should be rejected */
|
||||
litest_assert_ptr_null(device);
|
||||
|
||||
libevdev_uinput_destroy(uinput);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
TEST_COLLECTION(device)
|
||||
{
|
||||
/* clang-format off */
|
||||
|
|
@ -1713,6 +1784,13 @@ TEST_COLLECTION(device)
|
|||
|
||||
litest_add(device_wheel_only, LITEST_WHEEL, LITEST_RELATIVE|LITEST_ABSOLUTE|LITEST_TABLET);
|
||||
litest_add_no_device(device_accelerometer);
|
||||
litest_with_parameters(params, "range", 'I', 3,
|
||||
litest_named_i32(EXTREME_RANGE_0_TO_INT32MAX, "0-to-INT32MAX"),
|
||||
litest_named_i32(EXTREME_RANGE_INT32MIN_TO_0, "INT32MIN-to-0"),
|
||||
litest_named_i32(EXTREME_RANGE_NEGHALF_TO_POSHALF, "-INT32MAX/2-to-INT32MAX/2")) {
|
||||
litest_add_parametrized_no_device(abs_device_extreme_axis_range, params);
|
||||
}
|
||||
litest_add_no_device(abs_device_negative_resolution);
|
||||
|
||||
litest_add(device_udev_tag_wacom_tablet, LITEST_TABLET, LITEST_TOTEM);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue