From 6b3014ec0e9a390ca563030b2d7689921f0daef5 Mon Sep 17 00:00:00 2001 From: Jinmo Yang Date: Fri, 29 May 2026 02:59:45 +0900 Subject: [PATCH 1/4] HID: wacom: fix slab-out-of-bounds write in wacom_wac_queue_insert wacom_wac_queue_insert() calls kfifo_skip() in a loop when the kfifo doesn't have enough space for the incoming report. If the kfifo is empty, kfifo_skip() reads stale data left in the kmalloc'd buffer via __kfifo_peek_n() and interprets it as a record length, advancing fifo->out by that garbage value. This corrupts the internal kfifo state, causing kfifo_unused() to return a value much larger than the actual buffer size, which bypasses __kfifo_in_r()'s guard: if (len + recsize > kfifo_unused(fifo)) return 0; kfifo_copy_in() then performs an out-of-bounds memcpy, writing up to 3842 bytes past the 256-byte buffer. Add a !kfifo_is_empty() condition to the while loop so kfifo_skip() is never called on an empty fifo, and check the return value of kfifo_in() to reject reports that are too large for the fifo. Suggested-by: Dmitry Torokhov Fixes: 5e013ad20689 ("HID: wacom: Remove static WACOM_PKGLEN_MAX limit") Cc: stable@vger.kernel.org Signed-off-by: Jinmo Yang Reviewed-by: Dmitry Torokhov Signed-off-by: Benjamin Tissoires --- drivers/hid/wacom_sys.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 2220168bf116..fac75c202453 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -54,7 +54,7 @@ static void wacom_wac_queue_insert(struct hid_device *hdev, { bool warned = false; - while (kfifo_avail(fifo) < size) { + while (kfifo_avail(fifo) < size && !kfifo_is_empty(fifo)) { if (!warned) hid_warn(hdev, "%s: kfifo has filled, starting to drop events\n", __func__); warned = true; @@ -62,7 +62,9 @@ static void wacom_wac_queue_insert(struct hid_device *hdev, kfifo_skip(fifo); } - kfifo_in(fifo, raw_data, size); + if (!kfifo_in(fifo, raw_data, size)) + hid_warn_ratelimited(hdev, "%s: report is too large (%d)\n", + __func__, size); } static void wacom_wac_queue_flush(struct hid_device *hdev, From 55f1ad573e34abf9a0443c34bc5a63d74edba7d7 Mon Sep 17 00:00:00 2001 From: Jinmo Yang Date: Mon, 1 Jun 2026 22:41:23 +0900 Subject: [PATCH 2/4] HID: wacom: use GFP_ATOMIC in wacom_wac_queue_flush() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wacom_wac_queue_flush() is called via the .raw_event callback (wacom_raw_event → wacom_wac_pen_serial_enforce → wacom_wac_queue_flush). For USB HID devices, this callback is invoked from hid_irq_in(), which is a URB completion handler running in atomic context. Using GFP_KERNEL in this path can sleep, leading to a "scheduling while atomic" bug. Use GFP_ATOMIC instead. The existing code already handles allocation failure by skipping the fifo entry and continuing. Reported-by: Sashiko-bot Fixes: 5e013ad20689 ("HID: wacom: Remove static WACOM_PKGLEN_MAX limit") Cc: stable@vger.kernel.org Reviewed-by: Dmitry Torokhov Signed-off-by: Jinmo Yang Signed-off-by: Benjamin Tissoires --- drivers/hid/wacom_sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index fac75c202453..3a06be1e163a 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -76,7 +76,7 @@ static void wacom_wac_queue_flush(struct hid_device *hdev, unsigned int count; int err; - buf = kzalloc(size, GFP_KERNEL); + buf = kzalloc(size, GFP_ATOMIC); if (!buf) { kfifo_skip(fifo); continue; From cb605d48dac95b3b1258c2dcdd2d2c3617bee092 Mon Sep 17 00:00:00 2001 From: Jinmo Yang Date: Mon, 1 Jun 2026 22:41:24 +0900 Subject: [PATCH 3/4] HID: wacom: use cleanup.h for wacom_wac_queue_flush() buffer management Use __free(kfree) cleanup facility for the temporary buffer in wacom_wac_queue_flush() to simplify error paths and ensure the buffer is freed automatically when it goes out of scope. Signed-off-by: Jinmo Yang Signed-off-by: Benjamin Tissoires --- drivers/hid/wacom_sys.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 3a06be1e163a..3e3bcf695296 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -72,11 +72,10 @@ static void wacom_wac_queue_flush(struct hid_device *hdev, { while (!kfifo_is_empty(fifo)) { int size = kfifo_peek_len(fifo); - u8 *buf; + u8 *buf __free(kfree) = kzalloc(size, GFP_ATOMIC); unsigned int count; int err; - buf = kzalloc(size, GFP_ATOMIC); if (!buf) { kfifo_skip(fifo); continue; @@ -89,7 +88,6 @@ static void wacom_wac_queue_flush(struct hid_device *hdev, // to flush seems reasonable enough, however. hid_warn(hdev, "%s: removed fifo entry with unexpected size\n", __func__); - kfree(buf); continue; } err = hid_report_raw_event(hdev, HID_INPUT_REPORT, buf, size, size, false); @@ -97,8 +95,6 @@ static void wacom_wac_queue_flush(struct hid_device *hdev, hid_warn(hdev, "%s: unable to flush event due to error %d\n", __func__, err); } - - kfree(buf); } } From ec2612b8ad9e642596db011dd8b6568ef1edeaa1 Mon Sep 17 00:00:00 2001 From: Myeonghun Pak Date: Thu, 4 Jun 2026 13:56:58 +0900 Subject: [PATCH 4/4] HID: wacom: stop hardware after post-start probe failures wacom_parse_and_register() starts HID hardware before registering inputs and initializing pad LEDs/remotes. Those later steps can fail, but their error paths currently release Wacom resources without stopping the HID hardware. Route post-hid_hw_start() failures through hid_hw_stop() before releasing driver resources. This issue was identified during our ongoing static-analysis research while reviewing kernel code. Fixes: c1d6708bf0d3 ("HID: wacom: Do not register input devices until after hid_hw_start") Cc: stable@vger.kernel.org Co-developed-by: Ijae Kim Signed-off-by: Ijae Kim Signed-off-by: Myeonghun Pak Reviewed-by: Dmitry Torokhov Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 3e3bcf695296..0eafa483b7f7 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -2460,16 +2460,16 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless) error = wacom_register_inputs(wacom); if (error) - goto fail; + goto fail_hw_stop; if (wacom->wacom_wac.features.device_type & WACOM_DEVICETYPE_PAD) { error = wacom_initialize_leds(wacom); if (error) - goto fail; + goto fail_hw_stop; error = wacom_initialize_remotes(wacom); if (error) - goto fail; + goto fail_hw_stop; } if (!wireless) { @@ -2483,14 +2483,14 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless) cancel_delayed_work_sync(&wacom->init_work); _wacom_query_tablet_data(wacom); error = -ENODEV; - goto fail_quirks; + goto fail_hw_stop; } if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR) { error = hid_hw_open(hdev); if (error) { hid_err(hdev, "hw open failed\n"); - goto fail_quirks; + goto fail_hw_stop; } } @@ -2499,7 +2499,7 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless) return 0; -fail_quirks: +fail_hw_stop: hid_hw_stop(hdev); fail: wacom_release_resources(wacom);