]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
HID: wacom: fix slab-out-of-bounds write in wacom_wac_queue_insert
authorJinmo Yang <jinmo44.yang@gmail.com>
Thu, 28 May 2026 17:59:45 +0000 (02:59 +0900)
committerBenjamin Tissoires <bentiss@kernel.org>
Mon, 1 Jun 2026 16:37:23 +0000 (18:37 +0200)
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 <dmitry.torokhov@gmail.com>
Fixes: 5e013ad20689 ("HID: wacom: Remove static WACOM_PKGLEN_MAX limit")
Cc: stable@vger.kernel.org
Signed-off-by: Jinmo Yang <jinmo44.yang@gmail.com>
Reviewed-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
drivers/hid/wacom_sys.c

index 2220168bf1164be0a2c3665d2a18d5e43cb338a7..fac75c2024539ae1936709898fb960af92aa5f5d 100644 (file)
@@ -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,