* [PATCH] HID: wacom: fix NULL pointer dereference in wacom_intuos_pad()
@ 2026-05-23 15:01 Jinmo Yang
2026-05-23 15:06 ` [PATCH v2] " Jinmo Yang
0 siblings, 1 reply; 11+ messages in thread
From: Jinmo Yang @ 2026-05-23 15:01 UTC (permalink / raw)
To: Ping Cheng, Jason Gerecke, Jiri Kosina, Benjamin Tissoires
Cc: linux-input, linux-kernel, Jinmo Yang
wacom_intuos_pad() dereferences wacom->pad_input without a NULL check.
When a Wacom tablet is created via UHID with parameters that route
through wacom_bpt_irq() -> wacom_intuos_irq() -> wacom_intuos_pad(),
but probe did not allocate pad_input, the call to
wacom_report_numbered_buttons() passes a NULL input_dev, causing a
general protection fault in input_get_drvdata().
Add a NULL check for pad_input at the top of wacom_intuos_pad() to
bail out early when the pad input device was not set up.
The bug was found by syzkaller and confirmed on a Pixel 9 Pro
(Android 16, kernel 6.1.124) where it causes an immediate kernel
panic and reboot via /dev/uhid without requiring root privileges:
KP: Oops: Fatal exception: comm:wacom_27qhdt
Reboot reason: 0xbaba - Kernel PANIC
Reproducer (unprivileged):
open("/dev/uhid", O_RDWR)
write(fd, UHID_CREATE2{vendor=0x056a, product=0x0020})
write(fd, UHID_INPUT2{report_id=0x0c, size=10})
Fixes: c7f0522a1ad1 ("HID: wacom: Slim down wacom_intuos_pad processing")
Signed-off-by: Jinmo Yang <jinmo44.yang@gmail.com>
---
drivers/hid/wacom_wac.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index da1f0ea85..251ddda3e 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -515,7 +515,6 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
struct wacom_features *features = &wacom->features;
unsigned char *data = wacom->data;
struct input_dev *input = wacom->pad_input;
- int i;
int buttons = 0, nbuttons = features->numbered_buttons;
int keys = 0, nkeys = 0;
int ring1 = 0, ring2 = 0;
@@ -523,6 +522,10 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
bool prox = false;
bool wrench = false, keyboard = false, mute_touch = false, menu = false,
info = false;
+ int i;
+
+ if (!input)
+ return 0;
/* pad packets. Works as a second tool and is always in prox */
if (!(data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD ||
--
2.53.0
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH v2] HID: wacom: fix NULL pointer dereference in wacom_intuos_pad() 2026-05-23 15:01 [PATCH] HID: wacom: fix NULL pointer dereference in wacom_intuos_pad() Jinmo Yang @ 2026-05-23 15:06 ` Jinmo Yang 2026-05-29 21:44 ` Dmitry Torokhov 0 siblings, 1 reply; 11+ messages in thread From: Jinmo Yang @ 2026-05-23 15:06 UTC (permalink / raw) To: Ping Cheng, Jason Gerecke, Jiri Kosina, Benjamin Tissoires Cc: linux-input, linux-kernel, Jinmo Yang wacom_intuos_pad() dereferences wacom->pad_input without a NULL check. When a Wacom tablet is created via UHID with parameters that route through wacom_bpt_irq() -> wacom_intuos_irq() -> wacom_intuos_pad(), but probe did not allocate pad_input, the call to wacom_report_numbered_buttons() passes a NULL input_dev, causing a general protection fault in input_get_drvdata(). Add a NULL check for pad_input at the top of wacom_intuos_pad() to bail out early when the pad input device was not set up. The bug was found by syzkaller on linux-next 7.1.0-rc4 (next-20260522): Oops: general protection fault, probably for non-canonical address 0xdffffc0000000052 KASAN: null-ptr-deref in range [0x0000000000000290-0x0000000000000297] RIP: 0010:input_get_drvdata include/linux/input.h:390 [inline] RIP: 0010:wacom_report_numbered_buttons+0x37/0x210 drivers/hid/wacom_wac.c:4210 Call Trace: wacom_intuos_pad drivers/hid/wacom_wac.c:643 [inline] wacom_intuos_irq+0x29a/0x32b0 drivers/hid/wacom_wac.c:1042 wacom_bpt_irq drivers/hid/wacom_wac.c:3275 [inline] wacom_wac_irq+0x12ed/0xaef0 drivers/hid/wacom_wac.c:3545 wacom_raw_event+0x677/0xa90 drivers/hid/wacom_sys.c:184 __hid_input_report.constprop.0+0x39a/0x4d0 drivers/hid/hid-core.c:2161 uhid_dev_input2 drivers/hid/uhid.c:618 [inline] uhid_char_write+0xa8a/0xfa0 drivers/hid/uhid.c:776 Also confirmed on a Pixel 9 Pro (Android 16, kernel 6.1.124) where it causes an immediate kernel panic and reboot via /dev/uhid without requiring root privileges: KP: Oops: Fatal exception: comm:wacom_27qhdt Reboot reason: 0xbaba - Kernel PANIC Reproducer (unprivileged): open("/dev/uhid", O_RDWR) write(fd, UHID_CREATE2{vendor=0x056a, product=0x0020}) write(fd, UHID_INPUT2{report_id=0x0c, size=10}) Fixes: c7f0522a1ad1 ("HID: wacom: Slim down wacom_intuos_pad processing") Signed-off-by: Jinmo Yang <jinmo44.yang@gmail.com> --- drivers/hid/wacom_wac.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index da1f0ea85..251ddda3e 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -515,7 +515,6 @@ static int wacom_intuos_pad(struct wacom_wac *wacom) struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; struct input_dev *input = wacom->pad_input; - int i; int buttons = 0, nbuttons = features->numbered_buttons; int keys = 0, nkeys = 0; int ring1 = 0, ring2 = 0; @@ -523,6 +522,10 @@ static int wacom_intuos_pad(struct wacom_wac *wacom) bool prox = false; bool wrench = false, keyboard = false, mute_touch = false, menu = false, info = false; + int i; + + if (!input) + return 0; /* pad packets. Works as a second tool and is always in prox */ if (!(data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD || -- 2.53.0 ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] HID: wacom: fix NULL pointer dereference in wacom_intuos_pad() 2026-05-23 15:06 ` [PATCH v2] " Jinmo Yang @ 2026-05-29 21:44 ` Dmitry Torokhov 2026-06-10 15:48 ` Jiri Kosina 0 siblings, 1 reply; 11+ messages in thread From: Dmitry Torokhov @ 2026-05-29 21:44 UTC (permalink / raw) To: Jinmo Yang Cc: Ping Cheng, Jason Gerecke, Jiri Kosina, Benjamin Tissoires, linux-input, linux-kernel On Sun, May 24, 2026 at 12:06:19AM +0900, Jinmo Yang wrote: > wacom_intuos_pad() dereferences wacom->pad_input without a NULL check. > When a Wacom tablet is created via UHID with parameters that route > through wacom_bpt_irq() -> wacom_intuos_irq() -> wacom_intuos_pad(), > but probe did not allocate pad_input, the call to > wacom_report_numbered_buttons() passes a NULL input_dev, causing a > general protection fault in input_get_drvdata(). > > Add a NULL check for pad_input at the top of wacom_intuos_pad() to > bail out early when the pad input device was not set up. > > The bug was found by syzkaller on linux-next 7.1.0-rc4 (next-20260522): > > Oops: general protection fault, probably for non-canonical address 0xdffffc0000000052 > KASAN: null-ptr-deref in range [0x0000000000000290-0x0000000000000297] > RIP: 0010:input_get_drvdata include/linux/input.h:390 [inline] > RIP: 0010:wacom_report_numbered_buttons+0x37/0x210 drivers/hid/wacom_wac.c:4210 > Call Trace: > wacom_intuos_pad drivers/hid/wacom_wac.c:643 [inline] > wacom_intuos_irq+0x29a/0x32b0 drivers/hid/wacom_wac.c:1042 > wacom_bpt_irq drivers/hid/wacom_wac.c:3275 [inline] > wacom_wac_irq+0x12ed/0xaef0 drivers/hid/wacom_wac.c:3545 > wacom_raw_event+0x677/0xa90 drivers/hid/wacom_sys.c:184 > __hid_input_report.constprop.0+0x39a/0x4d0 drivers/hid/hid-core.c:2161 > uhid_dev_input2 drivers/hid/uhid.c:618 [inline] > uhid_char_write+0xa8a/0xfa0 drivers/hid/uhid.c:776 > > Also confirmed on a Pixel 9 Pro (Android 16, kernel 6.1.124) where > it causes an immediate kernel panic and reboot via /dev/uhid without > requiring root privileges: > > KP: Oops: Fatal exception: comm:wacom_27qhdt > Reboot reason: 0xbaba - Kernel PANIC > > Reproducer (unprivileged): > open("/dev/uhid", O_RDWR) > write(fd, UHID_CREATE2{vendor=0x056a, product=0x0020}) > write(fd, UHID_INPUT2{report_id=0x0c, size=10}) > > Fixes: c7f0522a1ad1 ("HID: wacom: Slim down wacom_intuos_pad processing") > Signed-off-by: Jinmo Yang <jinmo44.yang@gmail.com> > --- > drivers/hid/wacom_wac.c | 5 ++++- > 1 file changed, 4 insertions(+), 1 deletion(-) > > diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c > index da1f0ea85..251ddda3e 100644 > --- a/drivers/hid/wacom_wac.c > +++ b/drivers/hid/wacom_wac.c > @@ -515,7 +515,6 @@ static int wacom_intuos_pad(struct wacom_wac *wacom) > struct wacom_features *features = &wacom->features; > unsigned char *data = wacom->data; > struct input_dev *input = wacom->pad_input; > - int i; > int buttons = 0, nbuttons = features->numbered_buttons; > int keys = 0, nkeys = 0; > int ring1 = 0, ring2 = 0; > @@ -523,6 +522,10 @@ static int wacom_intuos_pad(struct wacom_wac *wacom) > bool prox = false; > bool wrench = false, keyboard = false, mute_touch = false, menu = false, > info = false; > + int i; > + > + if (!input) > + return 0; > > /* pad packets. Works as a second tool and is always in prox */ > if (!(data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD || I think there are many more places in the driver where it used wacom->pad_input without verifying that it exists. Thanks. -- Dmitry ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] HID: wacom: fix NULL pointer dereference in wacom_intuos_pad() 2026-05-29 21:44 ` Dmitry Torokhov @ 2026-06-10 15:48 ` Jiri Kosina 2026-09-26 18:37 ` Jinmo Yang 2026-09-27 4:11 ` [PATCH 0/5] HID: wacom: check input devices in the report handlers Jinmo Yang 0 siblings, 2 replies; 11+ messages in thread From: Jiri Kosina @ 2026-06-10 15:48 UTC (permalink / raw) To: Dmitry Torokhov Cc: Jinmo Yang, Ping Cheng, Jason Gerecke, Benjamin Tissoires, linux-input, linux-kernel On Fri, 29 May 2026, Dmitry Torokhov wrote: > I think there are many more places in the driver where it used > wacom->pad_input without verifying that it exists. Absolutely correct observation, thanks :) Jinmo, are you planning to submit extended version of the patch, please? -- Jiri Kosina SUSE Labs ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] HID: wacom: fix NULL pointer dereference in wacom_intuos_pad() 2026-06-10 15:48 ` Jiri Kosina @ 2026-09-26 18:37 ` Jinmo Yang 2026-09-27 4:11 ` [PATCH 0/5] HID: wacom: check input devices in the report handlers Jinmo Yang 1 sibling, 0 replies; 11+ messages in thread From: Jinmo Yang @ 2026-09-26 18:37 UTC (permalink / raw) To: Jiri Kosina, Dmitry Torokhov Cc: Jinmo Yang, Ping Cheng, Jason Gerecke, Benjamin Tissoires, linux-input, linux-kernel On Wed, 10 Jun 2026, Jiri Kosina wrote: > Jinmo, are you planning to submit extended version of the patch, please? Yes - sorry for the long delay. Dmitry's observation turned out to be broader than pad_input, so I audited the whole driver before replying. The check already exists in three places, just not everywhere: wacom_wac.c:1807/1815 wacom_tpc_irq pen, touch wacom_wac.c:1210 wacom_intuos_bt_process_data pad wacom_wac.c:2192 wacom_wac_pad_event (HID_GENERIC) so the inconsistency is inside the legacy dispatch. The clearest case is two adjacent lines in wacom_intuos_bt_process_data(), one checked and one not: input_sync(wacom->pen_input); /* :1209 */ if (wacom->pad_input) /* :1210 */ input_sync(wacom->pad_input); The pointers can be NULL on a fully successful probe: the handler is chosen by features.type from the id table (wacom_sys.c:2945), while the input devices are allocated from what the descriptor declares. When wacom_setup_{pen,touch,pad}_input_capabilities() returns -ENODEV, wacom_setup_inputs() frees that input, NULLs the pointer and still returns 0 (wacom_sys.c:2172-2196) - "no pen in use on this interface". wacom_wac_irq() then still routes reports to a handler that dereferences it. No error injection is needed; a descriptor declaring only touch usages is enough. 15 locations, each reproduced as a KASAN NULL-pointer dereference on linux-next 20260925, x86_64, from one /dev/uhid device plus a single UHID_INPUT2 write: wacom_wac.c:137 wacom_penpartner_irq pen_input wacom_wac.c:227 wacom_pl_irq pen_input wacom_wac.c:244 wacom_ptu_irq pen_input wacom_wac.c:303 wacom_dtus_irq pad_input wacom_wac.c:326 wacom_dtus_irq pen_input wacom_wac.c:391 wacom_graphire_irq pen_input wacom_wac.c:444 wacom_graphire_irq pad_input wacom_wac.c:594 wacom_intuos_pad pad_input wacom_wac.c:1209 wacom_intuos_bt_process_data pen_input wacom_wac.c:1232 wacom_intuos_bt_irq pen_input (dev_warn) 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 wacom_wac.c:4229 wacom_report_numbered_buttons pad_input Jason, your review of my earlier series ("HID: wacom: add report length validation in irq handlers", 17 May) asked for the length checks to move into the sub-functions with len passed in, plus WACOM_PKGLEN_* names. Eight handlers already take len and eight do not, and six of those eight are also on the list above - so I would like to fold the two together and do one edit per handler: take len, use a named constant, and check the input device in the same place. On the shape of the fix: I plan to put a check where each pointer is taken, as wacom_tpc_irq() already does. A per-features.type table of required inputs would be one place instead of ~15, but a handler's needs vary by report id - wacom_graphire_irq() takes pen_input on one branch and pad_input on another - so the mask would have to demand every input the handler might touch, and would then reject reports that work today on a pen-only interface, which the "no pen in use on this interface" case says is legitimate. Say the word if you would rather have that anyway. I will post it as a series split by device family shortly, with the shared helpers (wacom_report_numbered_buttons(), wacom_wac_finger_count_touches()) guarded once each, since several handlers converge on them. Thanks, Jinmo ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 0/5] HID: wacom: check input devices in the report handlers 2026-06-10 15:48 ` Jiri Kosina 2026-09-26 18:37 ` Jinmo Yang @ 2026-09-27 4:11 ` Jinmo Yang 2026-09-27 4:11 ` [PATCH 1/5] HID: wacom: check the input device in the shared report helpers Jinmo Yang ` (4 more replies) 1 sibling, 5 replies; 11+ messages in thread From: Jinmo Yang @ 2026-09-27 4:11 UTC (permalink / raw) To: ping.cheng, jason.gerecke, jikos, bentiss Cc: dmitry.torokhov, linux-input, linux-kernel, Jinmo Yang This is the extended version Jiri asked for in <579o8so3-09o3-o312-4sq0-0qp6n672q46p@xreary.bet>, after Dmitry's observation that "there are many more places in the driver where it used wacom->pad_input without verifying that it exists". The audit turned out broader than pad_input. Of the 155 lines in wacom_wac.c that reference pen_input, touch_input or pad_input, three places already test the pointer first: wacom_wac.c:1807/1815 wacom_tpc_irq pen, touch wacom_wac.c:1210 wacom_intuos_bt_process_data pad wacom_wac.c:2192 wacom_wac_pad_event (HID_GENERIC) so the inconsistency is inside the legacy dispatch rather than between it and the HID_GENERIC path. The clearest illustration is two adjacent lines in wacom_intuos_bt_process_data(), one checked and one not: input_sync(wacom->pen_input); /* :1209 */ if (wacom->pad_input) /* :1210 */ input_sync(wacom->pad_input); Why the pointers can be NULL on a *successful* probe ==================================================== For a non-HID_GENERIC device the report handler is selected by features.type, which comes from the id table (wacom_sys.c:2945), while the three input devices are allocated from what the report descriptor declares. When wacom_setup_{pen,touch,pad}_input_capabilities() returns -ENODEV, wacom_setup_inputs() frees that input device, sets the pointer to NULL and still returns 0 (wacom_sys.c:2172-2196) - the "no pen in use on this interface" case. wacom_wac_irq() then still routes reports to a handler that dereferences it. No error injection is needed. A descriptor declaring only touch usages leaves pen_input and pad_input NULL; one declaring only pen usages leaves touch_input and pad_input NULL. What the series fixes ===================== 15 locations, each reproduced as a KASAN NULL-pointer dereference from one /dev/uhid device plus a single UHID_INPUT2 write, with no privilege beyond access to /dev/uhid: patch file:line function pointer 1 wacom_wac.c:4229 wacom_report_numbered_buttons pad 2 wacom_wac.c:137 wacom_penpartner_irq pen 2 wacom_wac.c:227 wacom_pl_irq pen 2 wacom_wac.c:244 wacom_ptu_irq pen 2 wacom_wac.c:303 wacom_dtus_irq pad 2 wacom_wac.c:326 wacom_dtus_irq pen 2 wacom_wac.c:391 wacom_graphire_irq pen 2 wacom_wac.c:444 wacom_graphire_irq pad 3 wacom_wac.c:594 wacom_intuos_pad pad 4 wacom_wac.c:1209 wacom_intuos_bt_process_data pen 4 wacom_wac.c:1232 wacom_intuos_bt_irq pen (both covered by one check at wacom_intuos_bt_irq() entry) 5 wacom_wac.c:3100 wacom_bpt_touch touch 5 wacom_wac.c:3117 wacom_bpt_touch pad 5 wacom_wac.c:3130 wacom_bpt3_touch_msg touch 5 wacom_wac.c:3178 wacom_bpt3_button_msg pad Patch 1 also guards wacom_wac_finger_count_touches(), and patch 2 also guards wacom_dtu_irq(); both are reachable with a NULL pointer but their only dereference is in a dev_dbg(), so they do not fault with CONFIG_DYNAMIC_DEBUG=n. Dereferences that are reached only through dev_dbg() are otherwise out of scope here. A few remain, on unknown-report paths in wacom_dtus_irq(), wacom_graphire_irq() and wacom_intuos_irq(); guarding those needs a separate look at what a pen-only or pad-only interface should still report, so I have left them for a follow-up rather than mixing them in. Approach ======== A check where each pointer is taken, which is what wacom_tpc_irq() already does. Where a handler serves both pen and pad reports - wacom_dtus_irq(), wacom_graphire_irq(), wacom_bpt_touch() - the checks are per branch rather than at function entry, so an interface that has a pad but no pen keeps delivering pad events. A per-features.type table of required input devices would be one place instead of 15, but a handler's needs vary by report id, so such a mask would have to demand every input the handler might touch and would then reject reports that work today on a partial interface. I am happy to build that instead if you would rather have it. Testing ======= linux-next 20260925 (7.3.0-rc4-next-20260925-gf5f84daefcd9), x86_64, CONFIG_KASAN_GENERIC=y, CONFIG_DYNAMIC_DEBUG=n. 27 uhid reproducer cases covering the sites above plus the dev_dbg-only ones, one fresh VM per case because the oops leaves driver_input_lock held: before after KASAN faults 17 0 probe failures 0 0 hidraw nodes created 26 26 input devices registered 25 25 and the set of input devices registered is identical in all 27 cases, so the checks remove the faults without changing what a device exposes. The one case that creates no device is a product whose table entry sets .check_for_hid_type, which uhid cannot satisfy; it behaves the same before and after. Each patch builds standalone with no new warnings, and checkpatch --strict reports 0 errors, 0 warnings and 0 checks for all five. Not in this series ================== Jason, your review of "HID: wacom: add report length validation in irq handlers" (17 May) asked for the length checks to move into the sub-functions with len passed in, plus WACOM_PKGLEN_* names. Eight handlers already take len and eight do not, and six of those eight are also on the list above, so that work overlaps this series closely. I have kept it out here because I have only reproduced and verified the input-device faults; I would rather send the length revision once it has the same evidence behind it, on top of this series. Jinmo Yang (5): HID: wacom: check the input device in the shared report helpers HID: wacom: check the input devices in the legacy irq handlers HID: wacom: check the input device in wacom_intuos_pad() HID: wacom: check the input device in wacom_intuos_bt_irq() HID: wacom: check the input devices in the Bamboo handlers drivers/hid/wacom_wac.c | 97 +++++++++++++++++++++++++++++------------ 1 file changed, 70 insertions(+), 27 deletions(-) base-commit: f5f84daefcd92d7a630066635ecea1433ed5eac7 -- 2.53.0 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/5] HID: wacom: check the input device in the shared report helpers 2026-09-27 4:11 ` [PATCH 0/5] HID: wacom: check input devices in the report handlers Jinmo Yang @ 2026-09-27 4:11 ` Jinmo Yang 2026-09-27 4:11 ` [PATCH 2/5] HID: wacom: check the input devices in the legacy irq handlers Jinmo Yang ` (3 subsequent siblings) 4 siblings, 0 replies; 11+ messages in thread From: Jinmo Yang @ 2026-09-27 4:11 UTC (permalink / raw) To: ping.cheng, jason.gerecke, jikos, bentiss Cc: dmitry.torokhov, linux-input, linux-kernel, Jinmo Yang, stable wacom_report_numbered_buttons() and wacom_wac_finger_count_touches() are reached from several report handlers and use the input device they are given without checking it. Both can see a NULL input device on a fully successful probe. The report handler is selected by features.type from the id table, while the three input devices are allocated from what the report descriptor declares. When wacom_setup_{pen,touch,pad}_input_capabilities() returns -ENODEV, wacom_setup_inputs() frees that input device, sets the pointer to NULL and still returns 0 - the "no pen in use on this interface" case. wacom_wac_irq() then still routes reports to a handler that passes the NULL pointer down. Reproduced on linux-next 20260925 (x86_64, KASAN) from one /dev/uhid device plus a single UHID_INPUT2 write: BUG: KASAN: null-ptr-deref in range [0x290-0x297] RIP: 0010:wacom_report_numbered_buttons+0x37/0x210 wacom_intuos_irq+0x29e/0x3300 wacom_wac_irq+0x1b59/0xb3f0 wacom_raw_event+0x68f/0xb60 __hid_input_report+0x398/0x4d0 uhid_char_write+0xa99/0xfc0 Check the pointer in both helpers, following the convention the driver already uses in wacom_tpc_irq() and wacom_wac_pad_event(). Fixes: 10059cdc0ad0 ("Input: wacom - split out the pad device for Intuos/Cintiq") Fixes: 2a6cdbdd4cc0 ("HID: wacom: Introduce new 'touch_input' device") Cc: stable@vger.kernel.org Signed-off-by: Jinmo Yang <jinmo44.yang@gmail.com> --- drivers/hid/wacom_wac.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index c4cd87b781c4..177a1e09fd05 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1263,6 +1263,9 @@ static int wacom_wac_finger_count_touches(struct wacom_wac *wacom) int count = 0; int i; + if (!input) + return 0; + if (!touch_max) return 0; @@ -4226,9 +4229,14 @@ static void wacom_update_led(struct wacom *wacom, int button_count, int mask, static void wacom_report_numbered_buttons(struct input_dev *input_dev, int button_count, int mask) { - struct wacom *wacom = input_get_drvdata(input_dev); + struct wacom *wacom; int i; + if (!input_dev) + return; + + wacom = input_get_drvdata(input_dev); + for (i = 0; i < wacom->led.count; i++) wacom_update_led(wacom, button_count, mask, i); -- 2.53.0 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2/5] HID: wacom: check the input devices in the legacy irq handlers 2026-09-27 4:11 ` [PATCH 0/5] HID: wacom: check input devices in the report handlers Jinmo Yang 2026-09-27 4:11 ` [PATCH 1/5] HID: wacom: check the input device in the shared report helpers Jinmo Yang @ 2026-09-27 4:11 ` Jinmo Yang 2026-09-27 4:11 ` [PATCH 3/5] HID: wacom: check the input device in wacom_intuos_pad() Jinmo Yang ` (2 subsequent siblings) 4 siblings, 0 replies; 11+ messages in thread From: Jinmo Yang @ 2026-09-27 4:11 UTC (permalink / raw) To: ping.cheng, jason.gerecke, jikos, bentiss Cc: dmitry.torokhov, linux-input, linux-kernel, Jinmo Yang, stable wacom_penpartner_irq(), wacom_pl_irq(), wacom_ptu_irq(), wacom_dtu_irq(), wacom_dtus_irq() and wacom_graphire_irq() take pen_input, and the latter two also take pad_input, without checking either. As described in "HID: wacom: check the input device in the shared report helpers", a partial interface leaves one or two of the three input devices NULL on a fully successful probe, and wacom_wac_irq() still dispatches to these handlers. Seven 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:137 wacom_penpartner_irq pen_input wacom_wac.c:227 wacom_pl_irq pen_input wacom_wac.c:244 wacom_ptu_irq pen_input wacom_wac.c:303 wacom_dtus_irq pad_input wacom_wac.c:326 wacom_dtus_irq pen_input wacom_wac.c:391 wacom_graphire_irq pen_input wacom_wac.c:444 wacom_graphire_irq pad_input for example, with vendor 0x056a product 0x0030 (PL) and report id 2: BUG: KASAN: null-ptr-deref in input_event+0x44/0xb0 Read of size 8 at addr 0000000000000028 wacom_wac_irq+0x2b27/0xb3f0 wacom_raw_event+0x68f/0xb60 __hid_input_report+0x398/0x4d0 uhid_char_write+0xa99/0xfc0 Check each pointer where it is taken. wacom_dtus_irq() and wacom_graphire_irq() serve both pen and pad reports, so the checks are placed per branch rather than at function entry: an interface that has a pad but no pen must keep delivering pad events. wacom_dtu_irq() gets a check too. Its only dereference is in a dev_dbg(), so it does not fault with CONFIG_DYNAMIC_DEBUG=n, but it is unconditional in the source. Fixes: 2a6cdbdd4cc0 ("HID: wacom: Introduce new 'touch_input' device") Fixes: 862cf5535c0c ("HID: wacom: Introduce a new WACOM_DEVICETYPE_PAD device_type") Cc: stable@vger.kernel.org Signed-off-by: Jinmo Yang <jinmo44.yang@gmail.com> --- drivers/hid/wacom_wac.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 177a1e09fd05..794c2865064a 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -128,6 +128,9 @@ static int wacom_penpartner_irq(struct wacom_wac *wacom) unsigned char *data = wacom->data; struct input_dev *input = wacom->pen_input; + if (!input) + return 0; + switch (data[0]) { case 1: if (data[5] & 0x80) { @@ -174,6 +177,9 @@ static int wacom_pl_irq(struct wacom_wac *wacom) struct input_dev *input = wacom->pen_input; int prox, pressure; + if (!input) + return 0; + if (data[0] != WACOM_REPORT_PENABLED) { dev_dbg(input->dev.parent, "%s: received unknown report #%d\n", __func__, data[0]); @@ -233,6 +239,9 @@ static int wacom_ptu_irq(struct wacom_wac *wacom) unsigned char *data = wacom->data; struct input_dev *input = wacom->pen_input; + if (!input) + return 0; + if (data[0] != WACOM_REPORT_PENABLED) { dev_dbg(input->dev.parent, "%s: received unknown report #%d\n", __func__, data[0]); @@ -263,6 +272,9 @@ static int wacom_dtu_irq(struct wacom_wac *wacom) struct input_dev *input = wacom->pen_input; int prox = data[1] & 0x20; + if (!input) + return 0; + dev_dbg(input->dev.parent, "%s: received report #%d", __func__, data[0]); @@ -299,6 +311,8 @@ static int wacom_dtus_irq(struct wacom_wac *wacom) return 0; } else if (data[0] == WACOM_REPORT_DTUSPAD) { input = wacom->pad_input; + if (!input) + return 0; input_report_key(input, BTN_0, (data[1] & 0x01)); input_report_key(input, BTN_1, (data[1] & 0x02)); input_report_key(input, BTN_2, (data[1] & 0x04)); @@ -307,6 +321,9 @@ static int wacom_dtus_irq(struct wacom_wac *wacom) data[1] & 0x0f ? PAD_DEVICE_ID : 0); return 1; } else { + if (!input) + return 0; + prox = data[1] & 0x80; if (prox) { switch ((data[1] >> 3) & 3) { @@ -363,7 +380,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) } prox = data[1] & 0x80; - if (prox || wacom->id[0]) { + if (input && (prox || wacom->id[0])) { if (prox) { switch ((data[1] >> 5) & 3) { @@ -438,7 +455,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) switch (features->type) { case WACOM_G4: prox = data[7] & 0xf8; - if (prox || wacom->id[1]) { + if (pad_input && (prox || wacom->id[1])) { wacom->id[1] = PAD_DEVICE_ID; input_report_key(pad_input, BTN_BACK, (data[7] & 0x40)); input_report_key(pad_input, BTN_FORWARD, (data[7] & 0x80)); @@ -453,7 +470,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) case WACOM_MO: prox = (data[7] & 0xf8) || data[8]; - if (prox || wacom->id[1]) { + if (pad_input && (prox || wacom->id[1])) { wacom->id[1] = PAD_DEVICE_ID; input_report_key(pad_input, BTN_BACK, (data[7] & 0x08)); input_report_key(pad_input, BTN_LEFT, (data[7] & 0x20)); @@ -468,7 +485,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) break; case GRAPHIRE_BT: prox = data[7] & 0x03; - if (prox || wacom->id[1]) { + if (pad_input && (prox || wacom->id[1])) { wacom->id[1] = PAD_DEVICE_ID; input_report_key(pad_input, BTN_0, (data[7] & 0x02)); input_report_key(pad_input, BTN_1, (data[7] & 0x01)); -- 2.53.0 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 3/5] HID: wacom: check the input device in wacom_intuos_pad() 2026-09-27 4:11 ` [PATCH 0/5] HID: wacom: check input devices in the report handlers Jinmo Yang 2026-09-27 4:11 ` [PATCH 1/5] HID: wacom: check the input device in the shared report helpers Jinmo Yang 2026-09-27 4:11 ` [PATCH 2/5] HID: wacom: check the input devices in the legacy irq handlers Jinmo Yang @ 2026-09-27 4:11 ` Jinmo Yang 2026-09-27 4:11 ` [PATCH 4/5] HID: wacom: check the input device in wacom_intuos_bt_irq() Jinmo Yang 2026-09-27 4:11 ` [PATCH 5/5] HID: wacom: check the input devices in the Bamboo handlers Jinmo Yang 4 siblings, 0 replies; 11+ messages in thread From: Jinmo Yang @ 2026-09-27 4:11 UTC (permalink / raw) To: ping.cheng, jason.gerecke, jikos, bentiss Cc: dmitry.torokhov, linux-input, linux-kernel, Jinmo Yang, stable wacom_intuos_pad() takes wacom->pad_input without checking it. An interface that declares no pad leaves the pointer NULL on a fully successful probe, and wacom_intuos_irq() still calls this function for pad report ids. Reproduced on linux-next 20260925 (x86_64, KASAN) with vendor 0x056a product 0x032A and report id 12: BUG: KASAN: null-ptr-deref in input_event+0x44/0xb0 Read of size 8 at addr 0000000000000028 wacom_intuos_irq+0x1b46/0x3300 wacom_wac_irq+0x1b59/0xb3f0 wacom_raw_event+0x68f/0xb60 __hid_input_report+0x398/0x4d0 uhid_char_write+0xa99/0xfc0 The function only ever serves pad reports, so the check goes at entry. Fixes: 10059cdc0ad0 ("Input: wacom - split out the pad device for Intuos/Cintiq") Cc: stable@vger.kernel.org Signed-off-by: Jinmo Yang <jinmo44.yang@gmail.com> --- drivers/hid/wacom_wac.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 794c2865064a..48a58a6672c2 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -553,6 +553,9 @@ static int wacom_intuos_pad(struct wacom_wac *wacom) bool wrench = false, keyboard = false, mute_touch = false, menu = false, info = false; + if (!input) + return 0; + /* pad packets. Works as a second tool and is always in prox */ if (!(data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD || data[0] == WACOM_REPORT_CINTIQPAD)) -- 2.53.0 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 4/5] HID: wacom: check the input device in wacom_intuos_bt_irq() 2026-09-27 4:11 ` [PATCH 0/5] HID: wacom: check input devices in the report handlers Jinmo Yang ` (2 preceding siblings ...) 2026-09-27 4:11 ` [PATCH 3/5] HID: wacom: check the input device in wacom_intuos_pad() Jinmo Yang @ 2026-09-27 4:11 ` Jinmo Yang 2026-09-27 4:11 ` [PATCH 5/5] HID: wacom: check the input devices in the Bamboo handlers Jinmo Yang 4 siblings, 0 replies; 11+ messages in thread From: Jinmo Yang @ 2026-09-27 4:11 UTC (permalink / raw) To: ping.cheng, jason.gerecke, jikos, bentiss Cc: dmitry.torokhov, linux-input, linux-kernel, Jinmo Yang, stable wacom_intuos_bt_irq() reaches for wacom->pen_input three ways without checking it: two dev_warn() calls on the short-report paths, a dev_dbg() on the unknown-report path, and input_sync(wacom->pen_input) inside wacom_intuos_bt_process_data(), which is called only from here. That last one is the odd one out, because the pad_input sync two lines below it is guarded: input_sync(wacom->pen_input); if (wacom->pad_input) input_sync(wacom->pad_input); An interface that declares no pen leaves the pointer NULL on a fully successful probe, as described in "HID: wacom: check the input device in the shared report helpers". Reproduced on linux-next 20260925 (x86_64, KASAN) with bus BUS_BLUETOOTH, vendor 0x056a product 0x00BD (INTUOS4WL): BUG: KASAN: null-ptr-deref in range [0x258-0x25f] RIP: 0010:wacom_wac_irq.cold+0x8f/0x16a wacom_raw_event+0x68f/0xb60 __hid_input_report+0x398/0x4d0 uhid_char_write+0xa99/0xfc0 One check at function entry covers all of them. It is safe to bail out there: this handler only runs for INTUOS4WL, and wacom_setup_device_quirks() only adds WACOM_DEVICETYPE_PAD for that range of types when WACOM_DEVICETYPE_PEN is already set, so a NULL pen_input implies a NULL pad_input and there is nothing the function can report. Every path that reaches the battery notification passes through wacom_intuos_bt_process_data() first, so no reachable work is lost. Fixes: 2a6cdbdd4cc0 ("HID: wacom: Introduce new 'touch_input' device") Cc: stable@vger.kernel.org Signed-off-by: Jinmo Yang <jinmo44.yang@gmail.com> --- drivers/hid/wacom_wac.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 48a58a6672c2..11544adb74f5 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1237,6 +1237,9 @@ static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len) int i = 1; unsigned power_raw, battery_capacity, bat_charging, ps_connected; + if (!wacom->pen_input) + return 0; + switch (data[0]) { case 0x04: if (len < 32) { -- 2.53.0 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 5/5] HID: wacom: check the input devices in the Bamboo handlers 2026-09-27 4:11 ` [PATCH 0/5] HID: wacom: check input devices in the report handlers Jinmo Yang ` (3 preceding siblings ...) 2026-09-27 4:11 ` [PATCH 4/5] HID: wacom: check the input device in wacom_intuos_bt_irq() Jinmo Yang @ 2026-09-27 4:11 ` Jinmo Yang 4 siblings, 0 replies; 11+ messages in thread From: Jinmo Yang @ 2026-09-27 4:11 UTC (permalink / raw) To: ping.cheng, jason.gerecke, jikos, bentiss Cc: dmitry.torokhov, linux-input, linux-kernel, Jinmo Yang, stable 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 <jinmo44.yang@gmail.com> --- 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 ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-09-27 4:11 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-05-23 15:01 [PATCH] HID: wacom: fix NULL pointer dereference in wacom_intuos_pad() Jinmo Yang 2026-05-23 15:06 ` [PATCH v2] " Jinmo Yang 2026-05-29 21:44 ` Dmitry Torokhov 2026-06-10 15:48 ` Jiri Kosina 2026-09-26 18:37 ` Jinmo Yang 2026-09-27 4:11 ` [PATCH 0/5] HID: wacom: check input devices in the report handlers Jinmo Yang 2026-09-27 4:11 ` [PATCH 1/5] HID: wacom: check the input device in the shared report helpers Jinmo Yang 2026-09-27 4:11 ` [PATCH 2/5] HID: wacom: check the input devices in the legacy irq handlers Jinmo Yang 2026-09-27 4:11 ` [PATCH 3/5] HID: wacom: check the input device in wacom_intuos_pad() Jinmo Yang 2026-09-27 4:11 ` [PATCH 4/5] HID: wacom: check the input device in wacom_intuos_bt_irq() Jinmo Yang 2026-09-27 4:11 ` [PATCH 5/5] HID: wacom: check the input devices in the Bamboo handlers Jinmo Yang
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®