HID: hid-goodix-spi: out of bounds read in goodix_hid_irq()

From: Maoyi Xie

Date: Mon Jun 22 2026 - 07:17:30 EST


Hi all,

I think goodix_hid_irq() in drivers/hid/hid-goodix-spi.c can leak kernel
memory to a hidraw reader when a malicious touchscreen reports a large
package size. I would appreciate it if you could take a look.

The handler reads a coordinate event over SPI. It then passes a device
controlled length straight to hid_input_report().

if (le16_to_cpu(pkg->size) < GOODIX_HID_PKG_LEN_SIZE) {
dev_err(ts->dev, "invalid coordinate event package size, %d",
le16_to_cpu(pkg->size));
return IRQ_HANDLED;
}
hid_input_report(ts->hid, HID_INPUT_REPORT, pkg->data,
le16_to_cpu(pkg->size) - GOODIX_HID_PKG_LEN_SIZE, 1);

pkg->size is a __le16 from the device. The only check is a lower bound.
There is no upper bound. So pkg->size can be up to 65535, while pkg->data
only holds GOODIX_HID_COOR_DATA_LEN (82) bytes read into event_buf.

The length reaches hid_input_report(), which passes it as both the buffer
size and the report size.

return __hid_input_report(hid, type, data, size, size, interrupt, ...);

Those two are equal, so the bsize < csize guard in hid_report_raw_event()
never fires. The device length then flows into the hidraw path.

if (hid->claimed & HID_CLAIMED_HIDRAW)
ret = hidraw_report_event(hid, data, size);

hidraw_report_event() does kmemdup(data, size) for each open reader. That
copies up to about 65 KB starting at pkg->data, far past the 82 valid bytes.
The bytes land in the buffer a hidraw client reads back. So it is an out of
bounds read of kernel slab memory handed to user space.

This needs a malicious or compromised Goodix SPI touchscreen and an open
/dev/hidraw node. The open node is common, since libinput and similar tools
keep one. It is not reachable from a VM or syzkaller, only from the SPI
device.

I reproduced the read on 7.1-rc7. I registered a HID device, opened a hidraw
reader, and called hid_input_report() with a small buffer and a large size.
The kmemdup copy faults.

BUG: unable to handle page fault for address ... (in memcpy_orig)
Call Trace:
kmemdup_noprof
hidraw_report_event
hid_report_raw_event
__hid_input_report

An upper bound on pkg->size before the call would close it. The driver
already has the lower bound. A matching upper bound against the bytes read
into event_buf would fit that check. The second hid_input_report() call
further down has the same shape.

Does this look like a real bug to you, and is an upper bound on pkg->size
the right fix? If so I am happy to send a proper patch with a Fixes tag and
Cc stable.

Thanks,
Maoyi
https://maoyixie.com/