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 <dmitry.torokhov@gmail.com>
Fixes: 5e013ad206 ("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>
This commit is contained in:
Jinmo Yang 2026-05-29 02:59:45 +09:00 committed by Benjamin Tissoires
parent e6f4f084ec
commit 6b3014ec0e

View 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,