[PATCH 5/5] HID: wacom: check the input devices in the Bamboo handlers
From: Jinmo Yang <hidden>
Date: 2026-09-27 04:11:59
Also in:
lkml, stable
Subsystem:
hid core layer, hid wacom driver, the rest · Maintainers:
Jiri Kosina, Benjamin Tissoires, Ping Cheng, Jason Gerecke, Linus Torvalds
wacom_bpt_touch() takes both touch_input and pad_input, and
wacom_bpt3_touch_msg() and wacom_bpt3_button_msg() take touch_input and
pad_input respectively, none of them checked. An interface that declares
only pen usages leaves touch_input and pad_input NULL on a fully
successful probe, and wacom_bpt_irq() still dispatches to these
handlers.
Four locations fault, each reproduced on linux-next 20260925 (x86_64,
KASAN) from one /dev/uhid device plus a single UHID_INPUT2 write:
wacom_wac.c:3100 wacom_bpt_touch touch_input
wacom_wac.c:3117 wacom_bpt_touch pad_input
wacom_wac.c:3130 wacom_bpt3_touch_msg touch_input
wacom_wac.c:3178 wacom_bpt3_button_msg pad_input
for example, with vendor 0x056a product 0x00D4 (BAMBOO_PEN), a pen-only
descriptor and report id 2:
BUG: KASAN: null-ptr-deref in input_event+0x44/0xb0
Read of size 8 at addr 0000000000000028
wacom_wac_irq+0x8185/0xb3f0
wacom_raw_event+0x68f/0xb60
__hid_input_report+0x398/0x4d0
uhid_char_write+0xa99/0xfc0
wacom_bpt_touch() serves touch and pad in one report, so its two blocks
are guarded separately - an interface with a pad but no touch must keep
delivering pad events. In wacom_bpt3_touch_msg() the slot lookup moves
below the check because it dereferences the input device itself.
The touch block of wacom_bpt_touch() is reindented into the new
conditional; git diff -w shows no change there beyond the two style
fixes checkpatch asks for on the lines that move.
Fixes: 2a6cdbdd4cc0 ("HID: wacom: Introduce new 'touch_input' device")
Fixes: 3116871f4273 ("Input: wacom - split out the pad device for Bamboos")
Cc: stable@vger.kernel.org
Signed-off-by: Jinmo Yang <redacted>
---
drivers/hid/wacom_wac.c | 56 +++++++++++++++++++++++++----------------
1 file changed, 34 insertions(+), 22 deletions(-)
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 11544adb74f5..dac67885f81e 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c@@ -3118,31 +3118,36 @@ static int wacom_bpt_touch(struct wacom_wac *wacom) if (data[0] != 0x02) return 0; - for (i = 0; i < 2; i++) { - int offset = (data[1] & 0x80) ? (8 * i) : (9 * i); - bool touch = report_touch_events(wacom) - && (data[offset + 3] & 0x80); - - input_mt_slot(input, i); - input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); - if (touch) { - int x = get_unaligned_be16(&data[offset + 3]) & 0x7ff; - int y = get_unaligned_be16(&data[offset + 5]) & 0x7ff; - if (features->quirks & WACOM_QUIRK_BBTOUCH_LOWRES) { - x <<= 5; - y <<= 5; + if (input) { + for (i = 0; i < 2; i++) { + int offset = (data[1] & 0x80) ? (8 * i) : (9 * i); + bool touch = report_touch_events(wacom) && + (data[offset + 3] & 0x80); + + input_mt_slot(input, i); + input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); + if (touch) { + int x = get_unaligned_be16(&data[offset + 3]) & 0x7ff; + int y = get_unaligned_be16(&data[offset + 5]) & 0x7ff; + + if (features->quirks & WACOM_QUIRK_BBTOUCH_LOWRES) { + x <<= 5; + y <<= 5; + } + input_report_abs(input, ABS_MT_POSITION_X, x); + input_report_abs(input, ABS_MT_POSITION_Y, y); } - input_report_abs(input, ABS_MT_POSITION_X, x); - input_report_abs(input, ABS_MT_POSITION_Y, y); } - } - input_mt_sync_frame(input); + input_mt_sync_frame(input); + } - input_report_key(pad_input, BTN_LEFT, (data[1] & 0x08) != 0); - input_report_key(pad_input, BTN_FORWARD, (data[1] & 0x04) != 0); - input_report_key(pad_input, BTN_BACK, (data[1] & 0x02) != 0); - input_report_key(pad_input, BTN_RIGHT, (data[1] & 0x01) != 0); + if (pad_input) { + input_report_key(pad_input, BTN_LEFT, (data[1] & 0x08) != 0); + input_report_key(pad_input, BTN_FORWARD, (data[1] & 0x04) != 0); + input_report_key(pad_input, BTN_BACK, (data[1] & 0x02) != 0); + input_report_key(pad_input, BTN_RIGHT, (data[1] & 0x01) != 0); + } wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom); return 1;
@@ -3153,8 +3158,12 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) struct wacom_features *features = &wacom->features; struct input_dev *input = wacom->touch_input; bool touch = data[1] & 0x80; - int slot = input_mt_get_slot_by_key(input, data[0]); + int slot; + if (!input) + return; + + slot = input_mt_get_slot_by_key(input, data[0]); if (slot < 0) return;
@@ -3196,6 +3205,9 @@ static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data) struct input_dev *input = wacom->pad_input; struct wacom_features *features = &wacom->features; + if (!input) + return; + if (features->type == INTUOSHT || features->type == INTUOSHT2) { input_report_key(input, BTN_LEFT, (data[1] & 0x02) != 0); input_report_key(input, BTN_BACK, (data[1] & 0x08) != 0);
--
2.53.0