[PATCH libinput] evdev: reject devices with a min == max axis range

Hans de Goede hdegoede at redhat.com
Mon Mar 23 04:05:52 PDT 2015


Hi,

On 23-03-15 05:29, Peter Hutterer wrote:
> Except for a few axes where this may be correct, a min == max axis range
> indicates a broken kernel driver. To avoid potential divisions by zero when
> scaling this axis later, reject such a device outright.
>
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

Looks good:

Reviewed-by: Hans de Goede <hdegoede at redhat.com>

Regards,

Hans


> ---
>   src/evdev.c   | 34 +++++++++++++++++++++++++
>   test/device.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>   2 files changed, 116 insertions(+)
>
> diff --git a/src/evdev.c b/src/evdev.c
> index bcaf338..52b89d3 100644
> --- a/src/evdev.c
> +++ b/src/evdev.c
> @@ -1452,10 +1452,32 @@ evdev_fix_android_mt(struct evdev_device *device)
>   		      libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y));
>   }
>
> +static inline int
> +evdev_check_min_max(struct evdev_device *device, unsigned int code)
> +{
> +	struct libevdev *evdev = device->evdev;
> +	const struct input_absinfo *absinfo;
> +
> +	if (!libevdev_has_event_code(evdev, EV_ABS, code))
> +		return 0;
> +
> +	absinfo = libevdev_get_abs_info(evdev, code);
> +	if (absinfo->minimum == absinfo->maximum) {
> +		log_bug_kernel(device->base.seat->libinput,
> +			       "Device '%s' has min == max on %s\n",
> +			       device->devname,
> +			       libevdev_event_code_get_name(EV_ABS, code));
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
>   static int
>   evdev_reject_device(struct evdev_device *device)
>   {
>   	struct libevdev *evdev = device->evdev;
> +	unsigned int code;
>
>   	if (libevdev_has_event_code(evdev, EV_ABS, ABS_X) ^
>   	    libevdev_has_event_code(evdev, EV_ABS, ABS_Y))
> @@ -1465,6 +1487,18 @@ evdev_reject_device(struct evdev_device *device)
>   	    libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y))
>   		return -1;
>
> +	for (code = 0; code < ABS_CNT; code++) {
> +		switch (code) {
> +		case ABS_MISC:
> +		case ABS_MT_SLOT:
> +		case ABS_MT_TOOL_TYPE:
> +			break;
> +		default:
> +			if (evdev_check_min_max(device, code) == -1)
> +				return -1;
> +		}
> +	}
> +
>   	return 0;
>   }
>
> diff --git a/test/device.c b/test/device.c
> index a18ec82..c9d5255 100644
> --- a/test/device.c
> +++ b/test/device.c
> @@ -814,6 +814,86 @@ START_TEST(abs_mt_device_no_absx)
>   }
>   END_TEST
>
> +START_TEST(abs_device_no_range)
> +{
> +	struct libevdev_uinput *uinput;
> +	struct libinput *li;
> +	struct libinput_device *device;
> +	int code;
> +	/* set x/y so libinput doesn't just reject for missing axes */
> +	struct input_absinfo absinfo[] = {
> +		{ ABS_X, 0, 10, 0, 0, 0 },
> +		{ ABS_Y, 0, 10, 0, 0, 0 },
> +		{ -1, 0, 0, 0, 0, 0 },
> +		{ -1, -1, -1, -1, -1, -1 }
> +	};
> +
> +	li = litest_create_context();
> +	litest_disable_log_handler(li);
> +
> +	for (code = 0; code < ABS_MT_SLOT; code++) {
> +		if (code == ABS_MISC)
> +			continue;
> +		absinfo[2].value = code;
> +		uinput = litest_create_uinput_abs_device("test device", NULL,
> +							 absinfo,
> +							 EV_KEY, BTN_LEFT,
> +							 EV_KEY, BTN_RIGHT,
> +							 -1);
> +		device = libinput_path_add_device(li,
> +						  libevdev_uinput_get_devnode(uinput));
> +		ck_assert(device == NULL);
> +		libevdev_uinput_destroy(uinput);
> +	}
> +
> +	litest_restore_log_handler(li);
> +	libinput_unref(li);
> +}
> +END_TEST
> +
> +START_TEST(abs_mt_device_no_range)
> +{
> +	struct libevdev_uinput *uinput;
> +	struct libinput *li;
> +	struct libinput_device *device;
> +	int code;
> +	/* set x/y so libinput doesn't just reject for missing axes */
> +	struct input_absinfo absinfo[] = {
> +		{ ABS_X, 0, 10, 0, 0, 0 },
> +		{ ABS_Y, 0, 10, 0, 0, 0 },
> +		{ ABS_MT_SLOT, 0, 10, 0, 0, 0 },
> +		{ ABS_MT_TRACKING_ID, 0, 255, 0, 0, 0 },
> +		{ ABS_MT_POSITION_X, 0, 10, 0, 0, 0 },
> +		{ ABS_MT_POSITION_Y, 0, 10, 0, 0, 0 },
> +		{ -1, 0, 0, 0, 0, 0 },
> +		{ -1, -1, -1, -1, -1, -1 }
> +	};
> +
> +	li = litest_create_context();
> +	litest_disable_log_handler(li);
> +
> +	for (code = ABS_MT_SLOT + 1; code < ABS_CNT; code++) {
> +		if (code == ABS_MT_TOOL_TYPE ||
> +		    code == ABS_MT_TRACKING_ID) /* kernel overrides it */
> +			continue;
> +
> +		absinfo[6].value = code;
> +		uinput = litest_create_uinput_abs_device("test device", NULL,
> +							 absinfo,
> +							 EV_KEY, BTN_LEFT,
> +							 EV_KEY, BTN_RIGHT,
> +							 -1);
> +		device = libinput_path_add_device(li,
> +						  libevdev_uinput_get_devnode(uinput));
> +		ck_assert(device == NULL);
> +		libevdev_uinput_destroy(uinput);
> +	}
> +
> +	litest_restore_log_handler(li);
> +	libinput_unref(li);
> +}
> +END_TEST
> +
>   int main (int argc, char **argv)
>   {
>   	litest_add("device:sendevents", device_sendevents_config, LITEST_ANY, LITEST_TOUCHPAD);
> @@ -846,6 +926,8 @@ int main (int argc, char **argv)
>   	litest_add_no_device("device:invalid devices", abs_device_no_absy);
>   	litest_add_no_device("device:invalid devices", abs_mt_device_no_absx);
>   	litest_add_no_device("device:invalid devices", abs_mt_device_no_absy);
> +	litest_add_no_device("device:invalid devices", abs_device_no_range);
> +	litest_add_no_device("device:invalid devices", abs_mt_device_no_range);
>
>   	return litest_run(argc, argv);
>   }
>


More information about the wayland-devel mailing list