Thread (14 messages) 14 messages, 4 authors, 3d ago
WARM3d

[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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help