diff --git a/.gitignore b/.gitignore index 354a022..f7a170a 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -libinput-1.26.1.tar.bz2 +libinput-1.30.1.tar.bz2 diff --git a/0002-RHEL-map-dials-to-rings-on-the-Intuos-Pro-3rd-Gen-de.patch b/0001-RHEL-map-dials-to-rings-on-the-Intuos-Pro-3rd-Gen-de.patch similarity index 70% rename from 0002-RHEL-map-dials-to-rings-on-the-Intuos-Pro-3rd-Gen-de.patch rename to 0001-RHEL-map-dials-to-rings-on-the-Intuos-Pro-3rd-Gen-de.patch index d9ee784..d7c0c4d 100644 --- a/0002-RHEL-map-dials-to-rings-on-the-Intuos-Pro-3rd-Gen-de.patch +++ b/0001-RHEL-map-dials-to-rings-on-the-Intuos-Pro-3rd-Gen-de.patch @@ -1,6 +1,6 @@ -From 6b3b71d0ddd27207ef4c52c72080ba10b672fa5a Mon Sep 17 00:00:00 2001 +From b4b2918b2ac67ba6553d79dbf1366cfc9b669080 Mon Sep 17 00:00:00 2001 From: Peter Hutterer -Date: Tue, 22 Jul 2025 14:22:34 +1000 +Date: Wed, 17 Dec 2025 14:35:37 +1000 Subject: [PATCH] RHEL: map dials to rings on the Intuos Pro 3rd Gen devices These devices have relative dials but our userspace stack @@ -16,21 +16,21 @@ Signed-off-by: Peter Hutterer --- meson.build | 1 + quirks/30-vendor-wacom.quirks | 42 +++++++++ - src/evdev-tablet-pad.c | 89 ++++++++++++++++--- - src/evdev-tablet-pad.h | 5 ++ - src/quirks.c | 1 + + src/evdev-tablet-pad.c | 92 +++++++++++++++++-- + src/evdev-tablet-pad.h | 5 + + src/quirks.c | 3 +- src/quirks.h | 1 + - test/litest-device-wacom-intuos-pro-3rd-pad.c | 87 ++++++++++++++++++ + test/litest-device-wacom-intuos-pro-3rd-pad.c | 86 +++++++++++++++++ test/litest.h | 1 + - test/test-tablet.c | 59 ++++++++++++ - 9 files changed, 276 insertions(+), 10 deletions(-) + test/test-pad.c | 72 +++++++++++++++ + 9 files changed, 292 insertions(+), 11 deletions(-) create mode 100644 test/litest-device-wacom-intuos-pro-3rd-pad.c diff --git a/meson.build b/meson.build -index 3f0583e5879f..f7fbe8222eea 100644 +index 0db0d1da3aba..ac58c7a1d734 100644 --- a/meson.build +++ b/meson.build -@@ -822,6 +822,7 @@ if get_option('tests') +@@ -948,6 +948,7 @@ if get_option('tests') 'test/litest-device-wacom-cintiq-pro-16-pen.c', 'test/litest-device-wacom-ekr.c', 'test/litest-device-wacom-hid4800-pen.c', @@ -39,10 +39,10 @@ index 3f0583e5879f..f7fbe8222eea 100644 'test/litest-device-wacom-intuos5-finger.c', 'test/litest-device-wacom-intuos5-pad.c', diff --git a/quirks/30-vendor-wacom.quirks b/quirks/30-vendor-wacom.quirks -index 51211684c821..79c860efca39 100644 +index a7898b65ca1c..38fbc65e08ba 100644 --- a/quirks/30-vendor-wacom.quirks +++ b/quirks/30-vendor-wacom.quirks -@@ -33,3 +33,45 @@ MatchBus=usb +@@ -40,3 +40,45 @@ MatchBus=usb MatchVendor=0x2D1F MatchProduct=0x524C AttrEventCode=-ABS_TILT_X;-ABS_TILT_Y; @@ -89,10 +89,10 @@ index 51211684c821..79c860efca39 100644 +MatchProduct=0x03F5 +ModelWacomIntuosPro3rd=1 diff --git a/src/evdev-tablet-pad.c b/src/evdev-tablet-pad.c -index 90614c5dae91..64d0eae2b603 100644 +index 186def190a71..40552603f80d 100644 --- a/src/evdev-tablet-pad.c +++ b/src/evdev-tablet-pad.c -@@ -317,6 +317,30 @@ pad_strip_get_mode_group(struct pad_dispatch *pad, +@@ -354,6 +354,30 @@ pad_strip_get_mode_group(struct pad_dispatch *pad, unsigned int strip) return NULL; } @@ -123,30 +123,27 @@ index 90614c5dae91..64d0eae2b603 100644 static void pad_check_notify_axes(struct pad_dispatch *pad, struct evdev_device *device, -@@ -335,7 +359,7 @@ pad_check_notify_axes(struct pad_dispatch *pad, +@@ -372,18 +396,48 @@ pad_check_notify_axes(struct pad_dispatch *pad, /* Unlike the ring axis we don't get an event when we release * so we can't set a source */ - if (pad->changed_axes & PAD_AXIS_DIAL1) { + if (pad->changed_axes & PAD_AXIS_DIAL1 && !pad->dials.map_to_ring) { group = pad_dial_get_mode_group(pad, 0); - tablet_pad_notify_dial(base, - time, -@@ -344,7 +368,7 @@ pad_check_notify_axes(struct pad_dispatch *pad, - group); + if (group) + tablet_pad_notify_dial(base, time, 0, pad->dials.dial1, group); } - if (pad->changed_axes & PAD_AXIS_DIAL2) { + if (pad->changed_axes & PAD_AXIS_DIAL2 && !pad->dials.map_to_ring) { group = pad_dial_get_mode_group(pad, 1); - tablet_pad_notify_dial(base, - time, -@@ -353,6 +377,34 @@ pad_check_notify_axes(struct pad_dispatch *pad, - group); + if (group) + tablet_pad_notify_dial(base, time, 1, pad->dials.dial2, group); } + if (pad->changed_axes & PAD_AXIS_DIAL1 && pad->dials.map_to_ring) { -+ double degrees = pad_ring_to_dial(&pad->dials.abs_dial1_value, pad->dials.dial1); ++ double degrees = ++ pad_ring_to_dial(&pad->dials.abs_dial1_value, pad->dials.dial1); + if (device->left_handed.enabled) + degrees = fmod(degrees + 180, 360); + @@ -160,7 +157,8 @@ index 90614c5dae91..64d0eae2b603 100644 + } + + if (pad->changed_axes & PAD_AXIS_DIAL2 && pad->dials.map_to_ring) { -+ double degrees = pad_ring_to_dial(&pad->dials.abs_dial2_value, pad->dials.dial2); ++ double degrees = ++ pad_ring_to_dial(&pad->dials.abs_dial2_value, pad->dials.dial2); + if (device->left_handed.enabled) + degrees = fmod(degrees + 180, 360); + @@ -176,17 +174,18 @@ index 90614c5dae91..64d0eae2b603 100644 if (pad->changed_axes & PAD_AXIS_RING1) { value = pad_handle_ring(pad, device, ABS_WHEEL); if (send_finger_up) -@@ -780,6 +832,9 @@ pad_init(struct pad_dispatch *pad, struct evdev_device *device) - pad->status = PAD_NONE; +@@ -824,6 +878,10 @@ pad_init(struct pad_dispatch *pad, struct evdev_device *device) pad->changed_axes = PAD_AXIS_NONE; + ratelimit_init(&pad->modes.group_not_found, h2us(1), 3); + /* RHEL dial-to-ring special */ -+ pad->dials.map_to_ring = evdev_device_has_model_quirk(device, QUIRK_MODEL_WACOM_INTUOS_PRO_3RD); ++ pad->dials.map_to_ring = ++ evdev_device_has_model_quirk(device, QUIRK_MODEL_WACOM_INTUOS_PRO_3RD); + - /* We expect the kernel to either give us both axes as hires or neither. + /* We expect the kernel to either give us both axes as hires or neither. * Getting one is a kernel bug we don't need to care about */ - pad->dials.has_hires_dial = libevdev_has_event_code(device->evdev, EV_REL, REL_WHEEL_HI_RES) || -@@ -886,18 +941,15 @@ evdev_device_tablet_pad_get_num_buttons(struct evdev_device *device) + pad->dials.has_hires_dial = +@@ -890,24 +948,34 @@ evdev_device_tablet_pad_get_num_buttons(struct evdev_device *device) return pad->nbuttons; } @@ -205,12 +204,11 @@ index 90614c5dae91..64d0eae2b603 100644 + if (libevdev_has_event_code(evdev, EV_REL, REL_WHEEL) || + libevdev_has_event_code(evdev, EV_REL, REL_DIAL)) { ndials++; -- if (libevdev_has_event_code(device->evdev, -+ if (libevdev_has_event_code(evdev, - EV_REL, - REL_HWHEEL)) +- if (libevdev_has_event_code(device->evdev, EV_REL, REL_HWHEEL)) ++ if (libevdev_has_event_code(evdev, EV_REL, REL_HWHEEL)) ndials++; -@@ -906,6 +958,19 @@ evdev_device_tablet_pad_get_num_dials(struct evdev_device *device) + } + return ndials; } @@ -230,7 +228,7 @@ index 90614c5dae91..64d0eae2b603 100644 int evdev_device_tablet_pad_get_num_rings(struct evdev_device *device) { -@@ -914,6 +979,10 @@ evdev_device_tablet_pad_get_num_rings(struct evdev_device *device) +@@ -916,6 +984,10 @@ evdev_device_tablet_pad_get_num_rings(struct evdev_device *device) if (!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD)) return -1; @@ -240,12 +238,12 @@ index 90614c5dae91..64d0eae2b603 100644 + if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_WHEEL)) { nrings++; - if (libevdev_has_event_code(device->evdev, + if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_THROTTLE)) diff --git a/src/evdev-tablet-pad.h b/src/evdev-tablet-pad.h -index fe7aa8b79ff0..c9c23583c714 100644 +index 27e9fbed47c3..4c9fef3200f5 100644 --- a/src/evdev-tablet-pad.h +++ b/src/evdev-tablet-pad.h -@@ -79,6 +79,11 @@ struct pad_dispatch { +@@ -83,6 +83,11 @@ struct pad_dispatch { bool has_hires_dial; double dial1; double dial2; @@ -258,35 +256,37 @@ index fe7aa8b79ff0..c9c23583c714 100644 struct { diff --git a/src/quirks.c b/src/quirks.c -index 01065d5eaa21..1151caac1d9d 100644 +index 6364549c8708..c726e03eb131 100644 --- a/src/quirks.c +++ b/src/quirks.c -@@ -272,6 +272,7 @@ quirk_get_name(enum quirk q) - case QUIRK_MODEL_TOUCHPAD_PHANTOM_CLICKS: return "ModelTouchpadPhantomClicks"; - case QUIRK_MODEL_TRACKBALL: return "ModelTrackball"; - case QUIRK_MODEL_WACOM_TOUCHPAD: return "ModelWacomTouchpad"; -+ case QUIRK_MODEL_WACOM_INTUOS_PRO_3RD: return "ModelWacomIntuosPro3rd"; - case QUIRK_MODEL_PRESSURE_PAD: return "ModelPressurePad"; - - case QUIRK_ATTR_SIZE_HINT: return "AttrSizeHint"; +@@ -298,7 +298,8 @@ quirk_get_name(enum quirk q) + return "ModelWacomTouchpad"; + case QUIRK_MODEL_PRESSURE_PAD: + return "ModelPressurePad"; +- ++ case QUIRK_MODEL_WACOM_INTUOS_PRO_3RD: ++ return "ModelWacomIntuosPro3rd"; + case QUIRK_ATTR_SIZE_HINT: + return "AttrSizeHint"; + case QUIRK_ATTR_TOUCH_SIZE_RANGE: diff --git a/src/quirks.h b/src/quirks.h -index 340d04635b9f..ff0ac94e424f 100644 +index b6ea220a991c..22321d644f12 100644 --- a/src/quirks.h +++ b/src/quirks.h -@@ -86,6 +86,7 @@ enum quirk { +@@ -95,6 +95,7 @@ enum quirk { QUIRK_MODEL_TOUCHPAD_VISIBLE_MARKER, QUIRK_MODEL_TRACKBALL, QUIRK_MODEL_WACOM_TOUCHPAD, + QUIRK_MODEL_WACOM_INTUOS_PRO_3RD, - QUIRK_MODEL_PRESSURE_PAD, - QUIRK_MODEL_TOUCHPAD_PHANTOM_CLICKS, + + _QUIRK_LAST_MODEL_QUIRK_, /* Guard: do not modify */ diff --git a/test/litest-device-wacom-intuos-pro-3rd-pad.c b/test/litest-device-wacom-intuos-pro-3rd-pad.c new file mode 100644 -index 000000000000..d5e54d46db6b +index 000000000000..8efdcb16740b --- /dev/null +++ b/test/litest-device-wacom-intuos-pro-3rd-pad.c -@@ -0,0 +1,87 @@ +@@ -0,0 +1,86 @@ +/* + * Copyright © 2016 Red Hat, Inc. + * @@ -312,8 +312,8 @@ index 000000000000..d5e54d46db6b + +#include "config.h" + -+#include "litest.h" +#include "litest-int.h" ++#include "litest.h" + +static struct input_event down[] = { + { .type = -1, .code = -1 }, @@ -357,11 +357,11 @@ index 000000000000..d5e54d46db6b + EV_REL, REL_HWHEEL, + EV_REL, REL_WHEEL_HI_RES, + EV_REL, REL_HWHEEL_HI_RES, -+ -1, -1, ++ -1, -1, +}; + -+TEST_DEVICE("wacom-intuos3-pad", -+ .type = LITEST_WACOM_INTUOS_PRO_3RD_PAD, ++TEST_DEVICE( ++ LITEST_WACOM_INTUOS_PRO_3RD_PAD, + .features = LITEST_TABLET_PAD, /* RHEL: not LITEST_DIAL because it's special */ + .interface = &interface, + @@ -372,59 +372,61 @@ index 000000000000..d5e54d46db6b + .udev_properties = { + { "ID_INPUT_TABLET_PAD", "1" }, + { NULL }, -+ }, -+) ++ }, ) diff --git a/test/litest.h b/test/litest.h -index 6108be50a4c1..93bea19dcd3e 100644 +index 9aa76f3c27ca..fe88be22e984 100644 --- a/test/litest.h +++ b/test/litest.h -@@ -352,6 +352,7 @@ enum litest_device_type { +@@ -532,6 +532,7 @@ enum litest_device_type { + LITEST_WACOM_CINTIQ_PRO16_PEN, LITEST_WACOM_EKR, LITEST_WACOM_HID4800_PEN, - LITEST_WACOM_INTUOS, + LITEST_WACOM_INTUOS_PRO_3RD_PAD, LITEST_WACOM_INTUOS3_PAD, LITEST_WACOM_INTUOS5_PAD, - LITEST_WACOM_ISDV4, -diff --git a/test/test-tablet.c b/test/test-tablet.c -index b652dcfd5345..ae88c844be91 100644 ---- a/test/test-tablet.c -+++ b/test/test-tablet.c -@@ -6560,6 +6560,62 @@ START_TEST(tablet_smoothing) + LITEST_WACOM_INTUOS5_PEN, +diff --git a/test/test-pad.c b/test/test-pad.c +index 6c3560d6bd38..2bac2f7866f1 100644 +--- a/test/test-pad.c ++++ b/test/test-pad.c +@@ -1147,6 +1147,67 @@ START_TEST(pad_send_events_disabled) } END_TEST -+START_TEST(tablet_dial_to_ring) ++START_TEST(pad_dial_to_ring) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_tablet_pad *pev; + -+ /* The range is a bitmask of ring, direction, left-handed */ -+ int testcase = _i; /* ranged test */ -+ unsigned int ring = testcase & 0x1; -+ int direction = testcase & 0x2 ? -1 : 1; -+ bool left_handed = !!(testcase & 0x4); -+ -+ litest_assert_int_lt(testcase, 8); ++ unsigned int ring = litest_test_param_get_u32(test_env->params, "ring"); ++ int direction = litest_test_param_get_i32(test_env->params, "direction"); ++ bool left_handed = litest_test_param_get_bool(test_env->params, "left-handed"); + + const int degrees_per_detent = 15; + -+ litest_assert_int_eq(libinput_device_tablet_pad_get_num_dials(dev->libinput_device), 0); -+ litest_assert_int_eq(libinput_device_tablet_pad_get_num_rings(dev->libinput_device), 2); ++ litest_assert_int_eq( ++ libinput_device_tablet_pad_get_num_dials(dev->libinput_device), ++ 0); ++ litest_assert_int_eq( ++ libinput_device_tablet_pad_get_num_rings(dev->libinput_device), ++ 2); + + /* The dial-to-ring affected devices do not support left-handed so let's + * make sure setting left-handed a) doesn't work and b) the setting + * doesn't affect anything. + */ -+ enum libinput_config_status rc = libinput_device_config_left_handed_set(dev->libinput_device, left_handed); ++ enum libinput_config_status rc = ++ libinput_device_config_left_handed_set(dev->libinput_device, ++ left_handed); + litest_assert_int_eq(rc, (unsigned)LIBINPUT_CONFIG_STATUS_UNSUPPORTED); + + litest_drain_events(li); + + double expected = 0.0; -+ for (size_t count = 0; count < 36; count++) { /* 24 per 360 so let's do 1.5 rotations */ ++ for (size_t count = 0; count < 36; ++ count++) { /* 24 per 360 so let's do 1.5 rotations */ + if (ring == 0) { + /* REL_WHEEL is inverted to expectations */ + litest_event(dev, EV_REL, REL_WHEEL, 1 * -direction); @@ -442,7 +444,9 @@ index b652dcfd5345..ae88c844be91 100644 + expected = fmod(expected, 360); + + event = libinput_get_event(li); -+ pev = litest_is_pad_ring_event(event, ring, LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN); ++ pev = litest_is_pad_ring_event(event, ++ ring, ++ LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN); + double value = libinput_event_tablet_pad_get_ring_position(pev); + litest_assert_double_eq(value, expected); + libinput_event_destroy(event); @@ -450,17 +454,26 @@ index b652dcfd5345..ae88c844be91 100644 +} +END_TEST + - TEST_COLLECTION(tablet) + TEST_COLLECTION(pad) { - struct range with_timeout = { 0, 2 }; -@@ -6704,4 +6760,7 @@ TEST_COLLECTION(tablet) - litest_add_ranged_for_device(huion_static_btn_tool_pen_disable_quirk_on_prox_out, LITEST_HUION_TABLET, &with_timeout); + /* clang-format off */ +@@ -1192,5 +1253,16 @@ TEST_COLLECTION(pad) + litest_add(pad_keys, LITEST_TABLET_PAD, LITEST_ANY); - litest_add_for_device(tablet_smoothing, LITEST_WACOM_HID4800_PEN); + litest_add(pad_send_events_disabled, LITEST_TABLET_PAD, LITEST_ANY); + -+ struct range dial_ring_cases = { 0, 8 }; -+ litest_add_ranged_for_device(tablet_dial_to_ring, LITEST_WACOM_INTUOS_PRO_3RD_PAD, &dial_ring_cases); ++ enum { ++ CCW = -1, ++ CW = 1, ++ }; ++ litest_with_parameters(params, ++ "ring", 'u', 2, 0, 1, ++ "direction", 'I', 2, litest_named_i32(CCW), litest_named_i32(CW), ++ "left-handed", 'b') { ++ litest_add_parametrized_for_device(pad_dial_to_ring, LITEST_WACOM_INTUOS_PRO_3RD_PAD, params); ++ } + /* clang-format on */ } -- -2.50.1 +2.51.1 diff --git a/0001-tablet-Remove-unnecessary-scale-factor-on-REL_HWHEEL.patch b/0001-tablet-Remove-unnecessary-scale-factor-on-REL_HWHEEL.patch deleted file mode 100644 index 482bd5a..0000000 --- a/0001-tablet-Remove-unnecessary-scale-factor-on-REL_HWHEEL.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 7ea1d8501fb5cfb4221a5f4647e8fde05092e613 Mon Sep 17 00:00:00 2001 -From: Jason Gerecke -Date: Mon, 29 Jul 2024 22:46:57 +0000 -Subject: [PATCH] tablet: Remove unnecessary scale factor on REL_HWHEEL_HI_RES - -The two high-res axes should already be scaled appropriately by the -kernel. This unnecessary scale factor causes 1 click of the dial to -produce an event delta of +-14400 rather than the expected +-120. - -Fixes: beca99812208 ("tablet: add API for relative dials") -Part-of: -(cherry picked from commit 66106b9746a46d5c1a112d8eae74acf0469a7cf6) -Signed-off-by: Peter Hutterer ---- - src/evdev-tablet-pad.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/evdev-tablet-pad.c b/src/evdev-tablet-pad.c -index 3aa92a4a4c69..90614c5dae91 100644 ---- a/src/evdev-tablet-pad.c -+++ b/src/evdev-tablet-pad.c -@@ -129,7 +129,7 @@ pad_process_relative(struct pad_dispatch *pad, - pad_set_status(pad, PAD_AXES_UPDATED); - break; - case REL_HWHEEL_HI_RES: -- pad->dials.dial2 = e->value * 120; -+ pad->dials.dial2 = e->value; - pad->changed_axes |= PAD_AXIS_DIAL2; - pad_set_status(pad, PAD_AXES_UPDATED); - break; --- -2.50.1 - diff --git a/0001-util-sanitize-control-characters-in-str_sanitize.patch b/0001-util-sanitize-control-characters-in-str_sanitize.patch new file mode 100644 index 0000000..599e169 --- /dev/null +++ b/0001-util-sanitize-control-characters-in-str_sanitize.patch @@ -0,0 +1,124 @@ +From fc2262e1c1847021239065e84f39f15492ef05cc Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Mon, 1 Jun 2026 10:12:29 +1000 +Subject: [PATCH] util: sanitize control characters in str_sanitize() + +str_sanitize() only escaped '%' characters for format string safety. +Device names from uinput devices can contain arbitrary bytes including +ANSI escape sequences (ESC, 0x1b) and other control characters. When +these strings are included in log messages and printed to a terminal, +the escape sequences are interpreted by the terminal emulator. This +could allow an attacker to manipulate terminal output (change colors, +set window title, clear screen) when an administrator views libinput +logs. + +Replace all control characters (0x00-0x1f and 0x7f) with '?' in +addition to the existing '%' escaping. This prevents terminal escape +sequence injection through device names in log output. + +Assisted-by: Claude:claude-opus-4-6 +(cherry picked from commit 71a2c5cae2a80a1e3bb29e3f3a07ccc3f3de5acb) + +Part-of: +--- + src/util-strings.h | 30 ++++++++++++++++++++++++------ + test/test-utils.c | 10 ++++++++++ + 2 files changed, 34 insertions(+), 6 deletions(-) + +diff --git a/src/util-strings.h b/src/util-strings.h +index 94236c481706..3c6626331a91 100644 +--- a/src/util-strings.h ++++ b/src/util-strings.h +@@ -538,34 +538,52 @@ strstartswith(const char *str, const char *prefix) + const char * + safe_basename(const char *filename); + + char * + trunkname(const char *filename); + + /** + * Return a copy of str with all % converted to %% to make the string +- * acceptable as printf format. ++ * acceptable as printf format, and all non-NUL control characters ++ * (bytes 0x01-0x1f, 0x7f) replaced with '?' to prevent terminal ++ * escape sequence injection. NUL bytes are excluded implicitly ++ * because the string is null-terminated. + */ + static inline char * + str_sanitize(const char *str) + { + if (!str) + return NULL; + +- if (!strchr(str, '%')) +- return strdup(str); +- + size_t slen = strlen(str); + slen = min(slen, 512); ++ ++ bool needs_sanitization = false; ++ for (size_t i = 0; i < slen; i++) { ++ unsigned char c = str[i]; ++ if (c == '%' || c < 0x20 || c == 0x7f) { ++ needs_sanitization = true; ++ break; ++ } ++ } ++ if (!needs_sanitization) ++ return strdup(str); ++ + char *sanitized = zalloc(2 * slen + 1); + const char *src = str; + char *dst = sanitized; + + for (size_t i = 0; i < slen; i++) { +- if (*src == '%') ++ unsigned char c = *src++; ++ if (c == '%') { + *dst++ = '%'; +- *dst++ = *src++; ++ *dst++ = '%'; ++ } else if (c < 0x20 || c == 0x7f) { ++ *dst++ = '?'; ++ } else { ++ *dst++ = c; ++ } + } + *dst = '\0'; + + return sanitized; + } +diff --git a/test/test-utils.c b/test/test-utils.c +index 7c938b0af8ac..ee61ba13cc9c 100644 +--- a/test/test-utils.c ++++ b/test/test-utils.c +@@ -2081,16 +2081,26 @@ START_TEST(strsanitize_test) + { "foobar", "foobar" }, + { "", "" }, + { "%", "%%" }, + { "%%%%", "%%%%%%%%" }, + { "x %s", "x %%s" }, + { "x %", "x %%" }, + { "%sx", "%%sx" }, + { "%s%s", "%%s%%s" }, ++ { "\t", "?" }, ++ { "\n", "?" }, ++ { "\r", "?" }, ++ { "\x1b[31m", "?[31m" }, ++ { "foo\tbar", "foo?bar" }, ++ { "foo\nbar", "foo?bar" }, ++ { "\x01\x1f\x7f", "???" }, ++ { "clean", "clean" }, ++ { "a\x1b[0mb", "a?[0mb" }, ++ { "%\n", "%%?" }, + { NULL, NULL }, + }; + /* clang-format on */ + + for (struct strsanitize_test *t = tests; t->string; t++) { + char *sanitized = str_sanitize(t->string); + litest_assert_str_eq(sanitized, t->expected); + free(sanitized); +-- +2.54.0 + diff --git a/0002-libinput-device-group-sanitize-phys-before-printing-.patch b/0002-libinput-device-group-sanitize-phys-before-printing-.patch new file mode 100644 index 0000000..e73558e --- /dev/null +++ b/0002-libinput-device-group-sanitize-phys-before-printing-.patch @@ -0,0 +1,116 @@ +From b2bde9504d42a5976d76e1f27c640dc561fbd99b Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Mon, 1 Jun 2026 10:48:24 +1000 +Subject: [PATCH] libinput-device-group: sanitize phys before printing it + +A malicious uinput device could set the phys value (via UI_SET_PHYS) +to contain a '\n'. When the value is printed as part of the device group +the udev rules will interpret it as separate property. + +Depending on the property this can cause local privilege escalation. + +Closes #1296 + +Found-by: Csome +(cherry picked from commit 76f0d8a7f57e2868882864b4611281f12f704b55) + +Part-of: +--- + udev/libinput-device-group.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/udev/libinput-device-group.c b/udev/libinput-device-group.c +index cdb38c0beb98..f9188406d4de 100644 +--- a/udev/libinput-device-group.c ++++ b/udev/libinput-device-group.c +@@ -102,61 +102,63 @@ wacom_handle_ekr(struct udev_device *device, + udev = udev_device_get_udev(device); + e = udev_enumerate_new(udev); + udev_enumerate_add_match_subsystem(e, "input"); + udev_enumerate_add_match_sysname(e, "input*"); + udev_enumerate_scan_devices(e); + + udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { + struct udev_device *d; +- const char *path, *phys; ++ _autofree_ char *phys = NULL; ++ const char *path; + const char *pidstr, *vidstr; + int pid, vid, dist; + + /* Find and use the closest Wacom device on the system, + * relying on wacom_handle_paired() to fix our ID later + * if needed. + */ + path = udev_list_entry_get_name(entry); + d = udev_device_new_from_syspath(udev, path); + if (!d) + continue; + + vidstr = udev_device_get_property_value(d, "ID_VENDOR_ID"); + pidstr = udev_device_get_property_value(d, "ID_MODEL_ID"); +- phys = udev_device_get_sysattr_value(d, "phys"); ++ phys = str_sanitize(udev_device_get_sysattr_value(d, "phys")); + + if (vidstr && pidstr && phys && safe_atoi_base(vidstr, &vid, 16) && + safe_atoi_base(pidstr, &pid, 16) && vid == VENDOR_ID_WACOM && + pid != PRODUCT_ID_WACOM_EKR) { + dist = find_tree_distance(device, d); + if (dist > 0 && (dist < best_dist || best_dist < 0)) { + *vendor_id = vid; + *product_id = pid; + best_dist = dist; + + free(*phys_attr); +- *phys_attr = safe_strdup(phys); ++ *phys_attr = steal(&phys); + } + } + + udev_device_unref(d); + } + + udev_enumerate_unref(e); + } + #endif + + int + main(int argc, char **argv) + { + int rc = 1; + struct udev *udev = NULL; + struct udev_device *device = NULL; +- const char *syspath, *phys = NULL; ++ _autofree_ char *phys = NULL; ++ const char *syspath = NULL; + const char *product; + int bustype, vendor_id, product_id, version; + char group[1024]; + char *str; + + if (argc != 2) + return 1; + +@@ -170,18 +172,17 @@ main(int argc, char **argv) + if (!device) + goto out; + + /* Find the first parent with ATTRS{phys} set. For tablets that + * value looks like usb-0000:00:14.0-1/input1. Drop the /input1 + * bit and use the remainder as device group identifier */ + while (device != NULL) { + struct udev_device *parent; +- +- phys = udev_device_get_sysattr_value(device, "phys"); ++ phys = str_sanitize(udev_device_get_sysattr_value(device, "phys")); + if (phys) + break; + + parent = udev_device_get_parent(device); + udev_device_ref(parent); + udev_device_unref(device); + device = parent; + } +-- +2.54.0 + diff --git a/0003-quirks-add-quirk-for-Dell-Haptics-Touchpad.patch b/0003-quirks-add-quirk-for-Dell-Haptics-Touchpad.patch deleted file mode 100644 index 13cc985..0000000 --- a/0003-quirks-add-quirk-for-Dell-Haptics-Touchpad.patch +++ /dev/null @@ -1,38 +0,0 @@ -From ac3b94975742c06bbe1eb614edb251f2465b2dbb Mon Sep 17 00:00:00 2001 -From: Marge Yang -Date: Tue, 21 Jan 2025 07:26:41 +0000 -Subject: [PATCH] quirks: add quirk for Dell Haptics Touchpad. - -This Touchpad is a pressure pad and needs the pressure -handling disable. - -Part-of: -(cherry picked from commit af0e9a23c32d086fece58a95cb720994ad02d0b4) -Signed-off-by: Peter Hutterer ---- - quirks/50-system-dell.quirks | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/quirks/50-system-dell.quirks b/quirks/50-system-dell.quirks -index f46ab2b3c50e..a3492eb40e75 100644 ---- a/quirks/50-system-dell.quirks -+++ b/quirks/50-system-dell.quirks -@@ -141,3 +141,15 @@ MatchProduct=0x1063 - MatchUdevType=touchpad - MatchDMIModalias=dmi:*svnDellInc.:pnPrecision5480* - ModelTouchpadVisibleMarker=0 -+ -+[Dell laptop 14 Synaptics touchpad] -+MatchBus=i2c -+MatchVendor=0x06CB -+MatchProduct=0xCFF8 -+ModelPressurePad=1 -+ -+[Dell laptop 16 Synaptics touchpad] -+MatchBus=i2c -+MatchVendor=0x06CB -+MatchProduct=0xCFF9 -+ModelPressurePad=1 --- -2.50.1 - diff --git a/0003-util-fix-possible-return-of-unsanitized-input-in-str.patch b/0003-util-fix-possible-return-of-unsanitized-input-in-str.patch new file mode 100644 index 0000000..8e71678 --- /dev/null +++ b/0003-util-fix-possible-return-of-unsanitized-input-in-str.patch @@ -0,0 +1,38 @@ +From a487280e095e376a40354e69c01593153d61f126 Mon Sep 17 00:00:00 2001 +From: Josiah Vehrs +Date: Wed, 10 Jun 2026 18:17:53 -0700 +Subject: [PATCH] util: fix possible return of unsanitized input in + str_sanitize + +Fixes: 71a2c5cae2a8 ("util: sanitize control characters in str_sanitize()") +Part-of: +--- + src/util-strings.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/util-strings.h b/src/util-strings.h +index 6186c16784d5..a6ff440bd24b 100644 +--- a/src/util-strings.h ++++ b/src/util-strings.h +@@ -567,17 +567,17 @@ str_sanitize(const char *str) + for (size_t i = 0; i < slen; i++) { + unsigned char c = str[i]; + if (c == '%' || c < 0x20 || c == 0x7f) { + needs_sanitization = true; + break; + } + } + if (!needs_sanitization) +- return strdup(str); ++ return strndup(str, slen); + + char *sanitized = zalloc(2 * slen + 1); + const char *src = str; + char *dst = sanitized; + + for (size_t i = 0; i < slen; i++) { + unsigned char c = *src++; + if (c == '%') { +-- +2.54.0 + diff --git a/0004-quirks-add-quirks-for-Dell-laptop-with-Goodix-Touchp.patch b/0004-quirks-add-quirks-for-Dell-laptop-with-Goodix-Touchp.patch deleted file mode 100644 index a26f1d1..0000000 --- a/0004-quirks-add-quirks-for-Dell-laptop-with-Goodix-Touchp.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 54bbba8b2e35b6ceefed3ca0fe8c18e5b9a0759b Mon Sep 17 00:00:00 2001 -From: wangyafei -Date: Tue, 21 Jan 2025 17:17:05 +0800 -Subject: [PATCH] quirks: add quirks for Dell laptop with Goodix Touchpad. - -This touchpad is a pressure pad and needs the pressure -handling disable. - -Signed-off-by: Charles Wang -Part-of: -(cherry picked from commit 3cf6c91fff5b84757792810c4016144443581da6) -Signed-off-by: Peter Hutterer ---- - quirks/50-system-dell.quirks | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/quirks/50-system-dell.quirks b/quirks/50-system-dell.quirks -index a3492eb40e75..8110651e466f 100644 ---- a/quirks/50-system-dell.quirks -+++ b/quirks/50-system-dell.quirks -@@ -153,3 +153,15 @@ MatchBus=i2c - MatchVendor=0x06CB - MatchProduct=0xCFF9 - ModelPressurePad=1 -+ -+[Dell laptop 14 Goodix touchpad] -+MatchBus=i2c -+MatchVendor=0x27C6 -+MatchProduct=0x0F61 -+ModelPressurePad=1 -+ -+[Dell laptop 16 Goodix touchpad] -+MatchBus=i2c -+MatchVendor=0x27C6 -+MatchProduct=0x0F62 -+ModelPressurePad=1 --- -2.50.1 - diff --git a/libinput.spec b/libinput.spec index 5fcd69b..7e018aa 100644 --- a/libinput.spec +++ b/libinput.spec @@ -4,8 +4,8 @@ %global gitversion 58abea394 Name: libinput -Version: 1.26.1 -Release: 5%{?gitdate:.%{gitdate}git%{gitversion}}%{?dist} +Version: 1.30.1 +Release: 2%{?gitdate:.%{gitdate}git%{gitversion}}%{?dist} Summary: Input device library # SPDX @@ -19,10 +19,11 @@ Source2: commitid Source0: https://gitlab.freedesktop.org/libinput/libinput/-/archive/%{version}/libinput-%{version}.tar.bz2 %endif -Patch0001: 0001-tablet-Remove-unnecessary-scale-factor-on-REL_HWHEEL.patch -Patch0002: 0002-RHEL-map-dials-to-rings-on-the-Intuos-Pro-3rd-Gen-de.patch -Patch0003: 0003-quirks-add-quirk-for-Dell-Haptics-Touchpad.patch -Patch0004: 0004-quirks-add-quirks-for-Dell-laptop-with-Goodix-Touchp.patch +Patch0002: 0001-RHEL-map-dials-to-rings-on-the-Intuos-Pro-3rd-Gen-de.patch +# CVE-2026-50292 (RHEL-182371) +Patch0003: 0001-util-sanitize-control-characters-in-str_sanitize.patch +Patch0004: 0002-libinput-device-group-sanitize-phys-before-printing-.patch +Patch0005: 0003-util-fix-possible-return-of-unsanitized-input-in-str.patch BuildRequires: git-core BuildRequires: gcc @@ -79,6 +80,7 @@ intended to be run by users. -Ddocumentation=false \ -Dtests=true \ -Dinstall-tests=true \ + -Dlua-plugins=disabled \ -Dudev-dir=%{udevdir} %meson_build @@ -124,6 +126,7 @@ intended to be run by users. %{_libexecdir}/libinput/libinput-analyze-recording %{_libexecdir}/libinput/libinput-analyze-touch-down-state %{_libexecdir}/libinput/libinput-debug-tablet +%{_libexecdir}/libinput/libinput-debug-tablet-pad %{_libexecdir}/libinput/libinput-list-kernel-devices %{_libexecdir}/libinput/libinput-measure %{_libexecdir}/libinput/libinput-measure-fuzz @@ -140,6 +143,7 @@ intended to be run by users. %{_mandir}/man1/libinput-analyze-recording.1* %{_mandir}/man1/libinput-analyze-touch-down-state.1* %{_mandir}/man1/libinput-debug-tablet.1* +%{_mandir}/man1/libinput-debug-tablet-pad.1* %{_mandir}/man1/libinput-list-kernel-devices.1* %{_mandir}/man1/libinput-measure.1* %{_mandir}/man1/libinput-measure-fuzz.1* @@ -162,6 +166,18 @@ intended to be run by users. %changelog +* Fri Jun 12 2026 Peter Hutterer - 1.30.1-2 +- CVE-2026-50292: sanitize phys before printing it in libinput-device-group + Resolves: RHEL-182371 + +* Wed Dec 17 2025 Peter Hutterer - 1.30.1-1 +- libinput 1.30.1 + Resolves: RHEL-136390 + +* Wed Nov 05 2025 Florian Müllner - 1.28.1-1 +- libinput 1.28.1 + Resolves: RHEL-126613 + * Fri Aug 01 2025 Peter Hutterer - 1.26.1-5 - Add quirks for four Dell pressure pads (RHEL-106932) diff --git a/sources b/sources index f1d177e..b53b11e 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (libinput-1.26.1.tar.bz2) = d4611fc75ee6091f3139134f348db79d710560c27a936c7a8c0dc50657d6e1bdbdb1b44fb4c2c668a5b45934d91d3aef336d4096806807354472b25e298cdab6 +SHA512 (libinput-1.30.1.tar.bz2) = 6d9bb5653dfeb0e30c64e92f8146a8908233162ef39f89114f619605b7f0de3f9e0f344412d91c809d3c1dc3d4b836a5709373a80191484db3c6d0a8f69c4f82