* [PATCH 1/9] Bluetooth: HIDP: Fix GET_REPORT and SET_REPORT for unnumbered reports
2026-10-13 3:42 [PATCH 0/9] HID: Hardening report validation and unnumbered report handling Dmitry Torokhov
@ 2026-10-13 3:42 ` Dmitry Torokhov
2026-10-13 3:57 ` sashiko-bot
2026-10-13 3:42 ` [PATCH 2/9] HID: core: Fix GET_REPORT input processing " Dmitry Torokhov
` (7 subsequent siblings)
8 siblings, 1 reply; 14+ messages in thread
From: Dmitry Torokhov @ 2026-10-13 3:42 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, David Rheinsberg,
Frank Praznik, Jiri Kosina, Benjamin Tissoires, Even Xu,
Xinpeng Sun, Roderick Colenbrander
Cc: linux-bluetooth, linux-kernel, linux-input, Shashikirana H K
Internally, the kernel HID subsystem expects that report buffers for
both numbered and unnumbered raw report requests begin with a report ID
byte, using report ID 0 for unnumbered reports.
Adjust Bluetooth HIDP transport callbacks to adhere to this convention.
When fetching an unnumbered report, request the report without a report
ID over the control channel, prepend the report ID 0 byte to the
received data, and account for it in the returned length. Similarly,
when setting an unnumbered report, strip the leading dummy report ID
before sending the transfer while including it in the reported transfer
count.
Fixes: 0a7f364e8122 ("HID: Add the transport-driver functions to the HIDP driver.")
Assisted-by: LLM
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
net/bluetooth/hidp/core.c | 29 +++++++++++++++++++++++------
1 file changed, 23 insertions(+), 6 deletions(-)
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index f5bdf9f1ca63..004a8eed51fb 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -248,7 +248,6 @@ static int hidp_get_raw_report(struct hid_device *hid,
struct hidp_session *session = hid->driver_data;
struct sk_buff *skb;
size_t len;
- int numbered_reports = hid->report_enum[report_type].numbered;
int ret;
if (atomic_read(&session->terminate))
@@ -273,10 +272,11 @@ static int hidp_get_raw_report(struct hid_device *hid,
/* Set up our wait, and send the report request to the device. */
session->waiting_report_type = report_type & HIDP_DATA_RTYPE_MASK;
- session->waiting_report_number = numbered_reports ? report_number : -1;
+ session->waiting_report_number = report_number ? report_number : -1;
set_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
+
data[0] = report_number;
- ret = hidp_send_ctrl_message(session, report_type, data, 1);
+ ret = hidp_send_ctrl_message(session, report_type, data, !!report_number);
if (ret < 0)
goto err;
@@ -302,11 +302,25 @@ static int hidp_get_raw_report(struct hid_device *hid,
}
}
+ /*
+ * In case of unnumbered reports the response from the device will
+ * not have the report ID that the upper layers expect, so we need
+ * to stash it in the buffer ourselves and adjust the data size.
+ */
+ if (!report_number) {
+ data[0] = 0;
+ data++;
+ count--;
+ }
+
skb = session->report_return;
if (skb) {
- len = skb->len < count ? skb->len : count;
+ len = min_t(size_t, skb->len, count);
memcpy(data, skb->data, len);
+ if (!report_number && len)
+ len++;
+
kfree_skb(skb);
session->report_return = NULL;
} else {
@@ -350,9 +364,12 @@ static int hidp_set_raw_report(struct hid_device *hid, unsigned char reportnum,
return -ERESTARTSYS;
/* Set up our wait, and send the report request to the device. */
- data[0] = reportnum;
+ if (reportnum)
+ data[0] = reportnum;
+
set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
- ret = hidp_send_ctrl_message(session, report_type, data, count);
+ ret = hidp_send_ctrl_message(session, report_type,
+ data + !reportnum, count - !reportnum);
if (ret < 0)
goto err;
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH 1/9] Bluetooth: HIDP: Fix GET_REPORT and SET_REPORT for unnumbered reports
2026-10-13 3:42 ` [PATCH 1/9] Bluetooth: HIDP: Fix GET_REPORT and SET_REPORT for unnumbered reports Dmitry Torokhov
@ 2026-10-13 3:57 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-10-13 3:57 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] bluetooth: hidp: skb memory leak on timeout in hidp_get_raw_report()
--
commit 9c135d466dcba28a7f3598e00e865c9ade48ff0c
Author: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Bluetooth: HIDP: Fix GET_REPORT and SET_REPORT for unnumbered reports
Adjust Bluetooth HIDP transport callbacks to adhere to the kernel HID
subsystem convention of using report ID 0 for unnumbered reports. When
fetching or setting an unnumbered report, the report ID is appended or
stripped to ensure correct lengths and formatting over the control channel.
> diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
> index f5bdf9f1ca638..004a8eed51fb1 100644
> --- a/net/bluetooth/hidp/core.c
> +++ b/net/bluetooth/hidp/core.c
[ ... ]
> @@ -302,11 +302,25 @@ static int hidp_get_raw_report(struct hid_device *hid,
> }
> }
>
[Severity: Medium]
Does this code leak the sk_buff if a timeout or signal occurs concurrently
with the device response?
If wait_event_interruptible_timeout() in hidp_get_raw_report() times out or is
interrupted by a signal, it proceeds to the err label, which clears the
HIDP_WAITING_FOR_RETURN flag and unlocks the mutex without freeing
session->report_return.
Concurrently, if the device response arrives and is processed by
hidp_recv_ctrl_frame(), it can set session->report_return right as the timeout
occurs:
hidp_recv_ctrl_frame() {
...
/* hidp_get_raw_report() is waiting on this report. */
session->report_return = skb;
done_with_skb = 0;
clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
wake_up_interruptible(&session->report_queue);
}
Because the error path does not check or free session->report_return, the
sk_buff is permanently leaked as subsequent requests will overwrite
session->report_return without freeing the old one.
> + /*
> + * In case of unnumbered reports the response from the device will
> + * not have the report ID that the upper layers expect, so we need
> + * to stash it in the buffer ourselves and adjust the data size.
> + */
> + if (!report_number) {
> + data[0] = 0;
> + data++;
> + count--;
> + }
> +
> skb = session->report_return;
> if (skb) {
> - len = skb->len < count ? skb->len : count;
> + len = min_t(size_t, skb->len, count);
> memcpy(data, skb->data, len);
>
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261012-hid-core-report-validation-v1-0-e0dd5cb60b2e@gmail.com?part=1
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 2/9] HID: core: Fix GET_REPORT input processing for unnumbered reports
2026-10-13 3:42 [PATCH 0/9] HID: Hardening report validation and unnumbered report handling Dmitry Torokhov
2026-10-13 3:42 ` [PATCH 1/9] Bluetooth: HIDP: Fix GET_REPORT and SET_REPORT for unnumbered reports Dmitry Torokhov
@ 2026-10-13 3:42 ` Dmitry Torokhov
2026-10-13 4:00 ` sashiko-bot
2026-10-13 3:42 ` [PATCH 3/9] HID: core: Reject mixing numbered and " Dmitry Torokhov
` (6 subsequent siblings)
8 siblings, 1 reply; 14+ messages in thread
From: Dmitry Torokhov @ 2026-10-13 3:42 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, David Rheinsberg,
Frank Praznik, Jiri Kosina, Benjamin Tissoires, Even Xu,
Xinpeng Sun, Roderick Colenbrander
Cc: linux-bluetooth, linux-kernel, linux-input, Shashikirana H K
When emulating report retrieval requests in the HID core, low-level
transport drivers store a dummy report ID of 0 at the start of the
buffer for unnumbered reports, with the actual report payload placed
after the initial byte.
Passing the raw transfer buffer and total returned length directly to
the input layer causes unnumbered reports to be processed with an
extraneous leading byte and an incorrect payload length. Offset the
buffer past the leading byte and deduct the dummy report ID from the
length when forwarding unnumbered reports to the input layer.
Fixes: 0d0777ccaa2d ("HID: core: ensure __hid_request reserves the report ID as the first byte")
Assisted-by: LLM
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/hid/hid-core.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index ec7c2860c93e..a33e864a25f9 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -2033,8 +2033,13 @@ int __hid_request(struct hid_device *hid, struct hid_report *report,
return ret;
}
- if (reqtype == HID_REQ_GET_REPORT)
- hid_input_report(hid, report->type, buf, ret, 0);
+ if (reqtype == HID_REQ_GET_REPORT) {
+ if (report->id == 0)
+ ret--;
+
+ if (ret > 0)
+ hid_input_report(hid, report->type, data_buf, ret, 0);
+ }
return 0;
}
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH 2/9] HID: core: Fix GET_REPORT input processing for unnumbered reports
2026-10-13 3:42 ` [PATCH 2/9] HID: core: Fix GET_REPORT input processing " Dmitry Torokhov
@ 2026-10-13 4:00 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-10-13 4:00 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] hid: core: uhid unnumbered GET_REPORT payload truncation
--
commit c28ca1033fab3989e7f3d67f52364f0621a32b6d
Author: Dmitry Torokhov <dmitry.torokhov@gmail.com>
HID: core: Fix GET_REPORT input processing for unnumbered reports
This commit offsets the buffer and deducts the dummy report ID from the length
when forwarding unnumbered reports to the input layer in __hid_request.
> diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
> index ec7c2860c93ef..a33e864a25f92 100644
> --- a/drivers/hid/hid-core.c
> +++ b/drivers/hid/hid-core.c
> @@ -2033,8 +2033,13 @@ int __hid_request(struct hid_device *hid, struct hid_report *report,
> return ret;
> }
>
> - if (reqtype == HID_REQ_GET_REPORT)
> - hid_input_report(hid, report->type, buf, ret, 0);
> + if (reqtype == HID_REQ_GET_REPORT) {
> + if (report->id == 0)
> + ret--;
> +
> + if (ret > 0)
> + hid_input_report(hid, report->type, data_buf, ret, 0);
[Severity: High]
Does this unconditional stripping of the first byte truncate the payload for
unnumbered reports on uhid devices?
The commit message notes that low-level transport drivers store a dummy
report ID of 0 for unnumbered reports. While true for drivers like usbhid
and i2c-hid, uhid handles this differently.
According to the uhid ABI, userspace replies to UHID_GET_REPORT via
UHID_GET_REPORT_REPLY and places the exact raw payload in req->data without
a dummy report ID.
In drivers/hid/uhid.c:uhid_hid_get_report(), the payload is copied exactly
as provided by userspace:
ret = min3(count, (size_t)req->size, (size_t)UHID_DATA_MAX);
memcpy(buf, req->data, ret);
Since uhid does not prepend a dummy 0 byte, decrementing ret and passing
data_buf (which was advanced by one earlier in __hid_request) to
hid_input_report() appears to strip the first byte of the actual payload,
corrupting the data.
> + }
>
> return 0;
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261012-hid-core-report-validation-v1-0-e0dd5cb60b2e@gmail.com?part=2
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 3/9] HID: core: Reject mixing numbered and unnumbered reports
2026-10-13 3:42 [PATCH 0/9] HID: Hardening report validation and unnumbered report handling Dmitry Torokhov
2026-10-13 3:42 ` [PATCH 1/9] Bluetooth: HIDP: Fix GET_REPORT and SET_REPORT for unnumbered reports Dmitry Torokhov
2026-10-13 3:42 ` [PATCH 2/9] HID: core: Fix GET_REPORT input processing " Dmitry Torokhov
@ 2026-10-13 3:42 ` Dmitry Torokhov
2026-10-13 3:42 ` [PATCH 4/9] HID: core: Validate GET_REPORT report ID centrally Dmitry Torokhov
` (5 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Dmitry Torokhov @ 2026-10-13 3:42 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, David Rheinsberg,
Frank Praznik, Jiri Kosina, Benjamin Tissoires, Even Xu,
Xinpeng Sun, Roderick Colenbrander
Cc: linux-bluetooth, linux-kernel, linux-input, Shashikirana H K
According to the Device Class Definition for HID, if any report of a
given type includes a Report ID tag, all reports of that type must
include a Report ID tag. Mixing numbered and unnumbered reports within
the same report enumeration is invalid and causes confusion when sizing
and parsing incoming and outgoing transfers.
Reject descriptors that attempt to mix numbered and unnumbered reports
within the same report enumeration by warning and aborting report
registration.
Assisted-by: LLM
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/hid/hid-core.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index a33e864a25f9..3a9bd56dbf85 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -96,6 +96,12 @@ struct hid_report *hid_register_report(struct hid_device *device,
if (report_enum->report_id_hash[id])
return report_enum->report_id_hash[id];
+ if ((id == 0 && report_enum->numbered) ||
+ (id != 0 && report_enum->report_id_hash[0])) {
+ hid_warn(device, "not allowed to mix numbered and unnumbered reports\n");
+ return NULL;
+ }
+
report = kzalloc_obj(struct hid_report);
if (!report)
return NULL;
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 4/9] HID: core: Validate GET_REPORT report ID centrally
2026-10-13 3:42 [PATCH 0/9] HID: Hardening report validation and unnumbered report handling Dmitry Torokhov
` (2 preceding siblings ...)
2026-10-13 3:42 ` [PATCH 3/9] HID: core: Reject mixing numbered and " Dmitry Torokhov
@ 2026-10-13 3:42 ` Dmitry Torokhov
2026-10-13 4:00 ` sashiko-bot
2026-10-13 3:42 ` [PATCH 5/9] HID: i2c-hid: Drop redundant report ID validation Dmitry Torokhov
` (4 subsequent siblings)
8 siblings, 1 reply; 14+ messages in thread
From: Dmitry Torokhov @ 2026-10-13 3:42 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, David Rheinsberg,
Frank Praznik, Jiri Kosina, Benjamin Tissoires, Even Xu,
Xinpeng Sun, Roderick Colenbrander
Cc: linux-bluetooth, linux-kernel, linux-input, Shashikirana H K
Several transport drivers and device drivers individually check whether
a successful report retrieval response returns the expected report ID.
Centralize this check in the core HID raw request path so that all
report retrieval requests verify that the start of the returned buffer
matches the requested report ID. Introduce a new quirk,
HID_QUIRK_IGNORE_REPORT_ID_MISMATCH, for hardware with buggy firmware
(such as the ASUS ROG Flow Z13 touchpad) that returns mismatched report
IDs on feature fetches.
Assisted-by: LLM
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/hid/hid-core.c | 11 ++++++++++-
drivers/hid/hid-quirks.c | 2 ++
include/linux/hid.h | 2 ++
3 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 3a9bd56dbf85..cd099a420b9b 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -2565,8 +2565,17 @@ int __hid_hw_raw_request(struct hid_device *hdev,
if (ret)
return ret;
- return hdev->ll_driver->raw_request(hdev, reportnum, buf, len,
+ ret = hdev->ll_driver->raw_request(hdev, reportnum, buf, len,
rtype, reqtype);
+ if (ret > 0 && reqtype == HID_REQ_GET_REPORT &&
+ !(hdev->quirks & HID_QUIRK_IGNORE_REPORT_ID_MISMATCH) &&
+ buf[0] != reportnum) {
+ hid_warn(hdev, "mismatched report ID %u (expected %u)\n",
+ buf[0], reportnum);
+ return -EINVAL;
+ }
+
+ return ret;
}
/**
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index 96a36c5ba04f..0ea592d1c9e7 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -37,6 +37,8 @@ static const struct hid_device_id hid_quirks[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD), HID_QUIRK_BADPAD },
{ HID_USB_DEVICE(USB_VENDOR_ID_AMI, USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI), HID_QUIRK_ALWAYS_POLL },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_Z13_FOLIO),
+ HID_QUIRK_IGNORE_REPORT_ID_MISMATCH },
{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM), HID_QUIRK_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC), HID_QUIRK_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM), HID_QUIRK_NOGET },
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 8d17b741638c..8f5e485b1351 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -388,6 +388,7 @@ struct hid_item {
* | @HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE:
* | @HID_QUIRK_IGNORE_SPECIAL_DRIVER
* | @HID_QUIRK_POWER_ON_AFTER_BACKLIGHT
+ * | @HID_QUIRK_IGNORE_REPORT_ID_MISMATCH:
* | @HID_QUIRK_FULLSPEED_INTERVAL:
* | @HID_QUIRK_NO_INIT_REPORTS:
* | @HID_QUIRK_NO_IGNORE:
@@ -416,6 +417,7 @@ struct hid_item {
#define HID_QUIRK_NOINVERT BIT(21)
#define HID_QUIRK_IGNORE_SPECIAL_DRIVER BIT(22)
#define HID_QUIRK_POWER_ON_AFTER_BACKLIGHT BIT(23)
+#define HID_QUIRK_IGNORE_REPORT_ID_MISMATCH BIT(24)
#define HID_QUIRK_FULLSPEED_INTERVAL BIT(28)
#define HID_QUIRK_NO_INIT_REPORTS BIT(29)
#define HID_QUIRK_NO_IGNORE BIT(30)
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH 4/9] HID: core: Validate GET_REPORT report ID centrally
2026-10-13 3:42 ` [PATCH 4/9] HID: core: Validate GET_REPORT report ID centrally Dmitry Torokhov
@ 2026-10-13 4:00 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-10-13 4:00 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] hid: bpf: HID-BPF cannot fix invalid report IDs due to centralized validation
- [High] hid: __hid_hw_raw_request() breaks uhid unnumbered GET_REPORT
- [Medium] hid: core: un-ratelimited mismatched report ID warning allows log flooding DoS
- [Medium] hid: uninitialized memory read in __hid_hw_raw_request() on timeout
--
commit d5fcafe8cdb215ca55eba80f821711e3f7748edf
Author: Dmitry Torokhov <dmitry.torokhov@gmail.com>
HID: core: Validate GET_REPORT report ID centrally
This commit centralizes the check for whether a report retrieval response
returns the expected report ID into the core HID raw request path. It also
introduces a new quirk, HID_QUIRK_IGNORE_REPORT_ID_MISMATCH, to handle
hardware with buggy firmware.
> diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
> index 3a9bd56dbf85e..cd099a420b9b6 100644
> --- a/drivers/hid/hid-core.c
> +++ b/drivers/hid/hid-core.c
> @@ -2565,8 +2565,17 @@ int __hid_hw_raw_request(struct hid_device *hdev,
> if (ret)
> return ret;
>
> - return hdev->ll_driver->raw_request(hdev, reportnum, buf, len,
> + ret = hdev->ll_driver->raw_request(hdev, reportnum, buf, len,
> rtype, reqtype);
> + if (ret > 0 && reqtype == HID_REQ_GET_REPORT &&
> + !(hdev->quirks & HID_QUIRK_IGNORE_REPORT_ID_MISMATCH) &&
> + buf[0] != reportnum) {
[Severity: High]
Does this validation break uhid unnumbered GET_REPORT requests?
When __hid_hw_raw_request() in drivers/hid/hid-core.c is called for an
unnumbered report (reportnum == 0) on a uhid device, this check expects buf[0]
to contain the report ID (0).
However, the uhid driver copies the userspace response verbatim into the
buffer:
drivers/hid/uhid.c:uhid_hid_get_report() {
...
req = &uhid->report_buf.u.get_report_reply;
if (req->err) {
ret = -EIO;
} else {
ret = min3(count, (size_t)req->size, (size_t)UHID_DATA_MAX);
memcpy(buf, req->data, ret);
}
...
}
Because uhid does not prepend a dummy 0x00 report ID like usbhid does, buf[0]
contains the first byte of the data payload. Unless the payload happens to
start with a 0, this check will fail and spuriously reject valid reports.
[Severity: Medium]
Could this read uninitialized memory?
If a userspace application issues a GET_REPORT request via hidraw, it passes
an uninitialized kmalloc buffer down to __hid_hw_raw_request():
drivers/hid/hidraw.c:hidraw_get_report() {
...
buf = kmalloc(count, GFP_KERNEL);
...
}
If a transport driver like ishtp_raw_request() in
drivers/hid/intel-ish-hid/ishtp-hid.c times out waiting for the device, but
returns the length without populating the buffer:
drivers/hid/intel-ish-hid/ishtp-hid.c:ishtp_raw_request() {
...
hid_hw_wait(hid);
return len;
}
This validation check will evaluate the uninitialized memory and leak one
byte of kernel heap memory via the warning.
> + hid_warn(hdev, "mismatched report ID %u (expected %u)\n",
> + buf[0], reportnum);
[Severity: Medium]
Could this warning cause a log flooding denial of service?
Any local user with read/write access to the hidraw node can synchronously
trigger this warning in a tight loop by issuing HIDIOCGFEATURE ioctls on a
device that returns a mismatched report ID.
Because hid_warn() expands to dev_warn() without rate limiting, this can be
exploited to flood the kernel log.
> + return -EINVAL;
[Severity: High]
Does this prevent HID-BPF programs from fixing invalid report IDs?
When a BPF program calls hid_bpf_hw_request() to fetch a feature report from
the hardware, if the hardware returns an incorrect report ID in buf[0], this
check intercepts the response and immediately returns -EINVAL.
The BPF program receives -EINVAL instead of the raw data buffer, leaving it
unable to read the buggy buffer or apply a fixup, forcing the use of hardcoded
kernel quirks instead.
> + }
> +
> + return ret;
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261012-hid-core-report-validation-v1-0-e0dd5cb60b2e@gmail.com?part=4
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 5/9] HID: i2c-hid: Drop redundant report ID validation
2026-10-13 3:42 [PATCH 0/9] HID: Hardening report validation and unnumbered report handling Dmitry Torokhov
` (3 preceding siblings ...)
2026-10-13 3:42 ` [PATCH 4/9] HID: core: Validate GET_REPORT report ID centrally Dmitry Torokhov
@ 2026-10-13 3:42 ` Dmitry Torokhov
2026-10-13 3:42 ` [PATCH 6/9] HID: goodix-spi: " Dmitry Torokhov
` (3 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Dmitry Torokhov @ 2026-10-13 3:42 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, David Rheinsberg,
Frank Praznik, Jiri Kosina, Benjamin Tissoires, Even Xu,
Xinpeng Sun, Roderick Colenbrander
Cc: linux-bluetooth, linux-kernel, linux-input, Shashikirana H K
Now that the core HID request handling validates returned report IDs
for report retrieval requests centrally, the report ID mismatch check
in the I2C-HID transport driver is redundant. Drop it.
Assisted-by: LLM
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/hid/i2c-hid/i2c-hid-core.c | 7 -------
1 file changed, 7 deletions(-)
diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
index a8a9854854f5..d8ed7bb8e80c 100644
--- a/drivers/hid/i2c-hid/i2c-hid-core.c
+++ b/drivers/hid/i2c-hid/i2c-hid-core.c
@@ -311,13 +311,6 @@ static int i2c_hid_get_report(struct i2c_hid *ihid,
recv_len = min(recv_len, ret_count - sizeof(__le16));
memcpy(recv_buf, ihid->rawbuf + sizeof(__le16), recv_len);
- if (report_id && recv_len != 0 && recv_buf[0] != report_id) {
- dev_err(&ihid->client->dev,
- "device returned incorrect report (%d vs %d expected)\n",
- recv_buf[0], report_id);
- return -EINVAL;
- }
-
return recv_len;
}
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 6/9] HID: goodix-spi: Drop redundant report ID validation
2026-10-13 3:42 [PATCH 0/9] HID: Hardening report validation and unnumbered report handling Dmitry Torokhov
` (4 preceding siblings ...)
2026-10-13 3:42 ` [PATCH 5/9] HID: i2c-hid: Drop redundant report ID validation Dmitry Torokhov
@ 2026-10-13 3:42 ` Dmitry Torokhov
2026-10-13 3:42 ` [PATCH 7/9] HID: intel-thc-hid: Drop redundant report ID validation in quicki2c Dmitry Torokhov
` (2 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Dmitry Torokhov @ 2026-10-13 3:42 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, David Rheinsberg,
Frank Praznik, Jiri Kosina, Benjamin Tissoires, Even Xu,
Xinpeng Sun, Roderick Colenbrander
Cc: linux-bluetooth, linux-kernel, linux-input, Shashikirana H K
Now that the core HID request handling validates returned report IDs
for report retrieval requests centrally, the report ID check in the
Goodix SPI transport driver is redundant. Drop it.
Assisted-by: LLM
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/hid/hid-goodix-spi.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/drivers/hid/hid-goodix-spi.c b/drivers/hid/hid-goodix-spi.c
index 03d549efbdce..81603581ae40 100644
--- a/drivers/hid/hid-goodix-spi.c
+++ b/drivers/hid/hid-goodix-spi.c
@@ -461,11 +461,6 @@ static int goodix_hid_get_raw_report(struct hid_device *hid,
return error;
}
- if (buf[0] != reportnum) {
- dev_err(ts->dev, "incorrect report (%d vs %d expected)",
- buf[0], reportnum);
- return -EINVAL;
- }
return len;
}
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 7/9] HID: intel-thc-hid: Drop redundant report ID validation in quicki2c
2026-10-13 3:42 [PATCH 0/9] HID: Hardening report validation and unnumbered report handling Dmitry Torokhov
` (5 preceding siblings ...)
2026-10-13 3:42 ` [PATCH 6/9] HID: goodix-spi: " Dmitry Torokhov
@ 2026-10-13 3:42 ` Dmitry Torokhov
2026-10-13 3:57 ` sashiko-bot
2026-10-13 3:42 ` [PATCH 8/9] HID: multitouch: Drop redundant report ID validation in mt_get_feature Dmitry Torokhov
2026-10-13 3:42 ` [PATCH 9/9] HID: playstation: Drop redundant report ID validation in ps_get_report Dmitry Torokhov
8 siblings, 1 reply; 14+ messages in thread
From: Dmitry Torokhov @ 2026-10-13 3:42 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, David Rheinsberg,
Frank Praznik, Jiri Kosina, Benjamin Tissoires, Even Xu,
Xinpeng Sun, Roderick Colenbrander
Cc: linux-bluetooth, linux-kernel, linux-input, Shashikirana H K
Now that the core HID request handling validates returned report IDs
for report retrieval requests centrally, the report ID check in the
Intel QuickI2C driver is redundant. Drop it while retaining packet
length validation.
Assisted-by: LLM
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c b/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c
index 41271301215a..7a362a2ebe2b 100644
--- a/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c
+++ b/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c
@@ -160,9 +160,9 @@ int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type,
return ret;
}
- if (HIDI2C_DATA_LEN(le16_to_cpu(rpt->len)) != buf_len || rpt->data[0] != reportnum) {
- dev_err_once(qcdev->dev, "Invalid packet, len (%d vs %zu) report id (%d vs %d)\n",
- le16_to_cpu(rpt->len), buf_len, rpt->data[0], reportnum);
+ if (HIDI2C_DATA_LEN(le16_to_cpu(rpt->len)) != buf_len) {
+ dev_err_once(qcdev->dev, "Invalid packet length (%d vs %zu)\n",
+ le16_to_cpu(rpt->len), buf_len);
return -EINVAL;
}
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH 7/9] HID: intel-thc-hid: Drop redundant report ID validation in quicki2c
2026-10-13 3:42 ` [PATCH 7/9] HID: intel-thc-hid: Drop redundant report ID validation in quicki2c Dmitry Torokhov
@ 2026-10-13 3:57 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-10-13 3:57 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] hid: intel-thc-hid: hidraw GET_REPORT fails if buffer size exceeds report size
- [Medium] HID: intel-thc-hid: information leak via short DMA read
--
commit 75e0494a01241a3ea09c387003f59cc3e7199dc8
Author: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Subject: HID: intel-thc-hid: Drop redundant report ID validation in quicki2c
This commit removes the report ID validation from the Intel QuickI2C driver's
report retrieval path, as the core HID layer now handles this centrally. It
leaves the packet length validation intact.
> diff --git a/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c b/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c
> index 41271301215ab..7a362a2ebe2b3 100644
> --- a/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c
> +++ b/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c
[ ... ]
> @@ -160,9 +160,9 @@ int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type,
> return ret;
> }
>
> - if (HIDI2C_DATA_LEN(le16_to_cpu(rpt->len)) != buf_len || rpt->data[0] != reportnum) {
> - dev_err_once(qcdev->dev, "Invalid packet, len (%d vs %zu) report id (%d vs %d)\n",
> - le16_to_cpu(rpt->len), buf_len, rpt->data[0], reportnum);
> + if (HIDI2C_DATA_LEN(le16_to_cpu(rpt->len)) != buf_len) {
[Severity: High]
Does requiring an exact match for buf_len break the hidraw API? If a
userspace application calls HIDIOCGFEATURE with a standard oversized buffer
(e.g., HID_MAX_BUFFER_SIZE), buf_len will be larger than the actual report
size, causing this check to fail with -EINVAL.
[Severity: Medium]
Is there a risk of leaking stale data on a short DMA read?
If thc_swdma_read() successfully performs a short read, it returns 0 and
sets read_len to a value smaller than expected, leaving the rest of the DMA
buffer stale. Because this check exclusively relies on rpt->len instead of
the updated read_len, a stale rpt->len matching buf_len will pass this
validation.
This would lead to the memcpy() further down in quicki2c_get_report()
copying stale kernel memory into the buffer.
> + dev_err_once(qcdev->dev, "Invalid packet length (%d vs %zu)\n",
> + le16_to_cpu(rpt->len), buf_len);
> return -EINVAL;
> }
>
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261012-hid-core-report-validation-v1-0-e0dd5cb60b2e@gmail.com?part=7
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 8/9] HID: multitouch: Drop redundant report ID validation in mt_get_feature
2026-10-13 3:42 [PATCH 0/9] HID: Hardening report validation and unnumbered report handling Dmitry Torokhov
` (6 preceding siblings ...)
2026-10-13 3:42 ` [PATCH 7/9] HID: intel-thc-hid: Drop redundant report ID validation in quicki2c Dmitry Torokhov
@ 2026-10-13 3:42 ` Dmitry Torokhov
2026-10-13 3:42 ` [PATCH 9/9] HID: playstation: Drop redundant report ID validation in ps_get_report Dmitry Torokhov
8 siblings, 0 replies; 14+ messages in thread
From: Dmitry Torokhov @ 2026-10-13 3:42 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, David Rheinsberg,
Frank Praznik, Jiri Kosina, Benjamin Tissoires, Even Xu,
Xinpeng Sun, Roderick Colenbrander
Cc: linux-bluetooth, linux-kernel, linux-input, Shashikirana H K
Now that the core HID layer validates returned report IDs centrally and
provides a quirk for devices with mismatched responses, remove the
per-driver report ID check in the multitouch driver.
Also drop the dedicated class and device entry for the ASUS ROG Flow
Z13 touchpad, as the device now falls back cleanly to the generic Win 8
multitouch entry.
Assisted-by: LLM
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/hid/hid-multitouch.c | 32 --------------------------------
1 file changed, 32 deletions(-)
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 4e19a0c4d238..69f770a5c430 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -79,7 +79,6 @@ MODULE_LICENSE("GPL");
#define MT_QUIRK_APPLE_TOUCHBAR BIT(23)
#define MT_QUIRK_YOGABOOK9I BIT(24)
#define MT_QUIRK_KEEP_LATENCY_ON_CLOSE BIT(25)
-#define MT_QUIRK_IGNORE_FEATURE_ID_MISMATCH BIT(26)
#define MT_INPUTMODE_TOUCHSCREEN 0x02
#define MT_INPUTMODE_TOUCHPAD 0x03
@@ -236,7 +235,6 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app);
#define MT_CLS_APPLE_TOUCHBAR 0x0114
#define MT_CLS_YOGABOOK9I 0x0115
#define MT_CLS_EGALAX_P80H84 0x0116
-#define MT_CLS_ASUS_ROG_Z13_FOLIO 0x0117
#define MT_CLS_SIS 0x0457
#define MT_DEFAULT_MAXCONTACT 10
@@ -407,16 +405,6 @@ static const struct mt_class mt_classes[] = {
.quirks = MT_QUIRK_ALWAYS_VALID |
MT_QUIRK_CONTACT_CNT_ACCURATE |
MT_QUIRK_ASUS_CUSTOM_UP },
- { .name = MT_CLS_ASUS_ROG_Z13_FOLIO,
- .quirks = MT_QUIRK_ALWAYS_VALID |
- MT_QUIRK_IGNORE_DUPLICATES |
- MT_QUIRK_HOVERING |
- MT_QUIRK_CONTACT_CNT_ACCURATE |
- MT_QUIRK_STICKY_FINGERS |
- MT_QUIRK_WIN8_PTP_BUTTONS |
- MT_QUIRK_CONFIDENCE |
- MT_QUIRK_IGNORE_FEATURE_ID_MISMATCH,
- .export_all_inputs = true },
{ .name = MT_CLS_VTL,
.quirks = MT_QUIRK_ALWAYS_VALID |
MT_QUIRK_CONTACT_CNT_ACCURATE |
@@ -519,7 +507,6 @@ static const struct attribute_group mt_attribute_group = {
static void mt_get_feature(struct hid_device *hdev, struct hid_report *report)
{
- struct mt_device *td = hid_get_drvdata(hdev);
int ret;
u32 size = hid_report_len(report);
u8 *buf;
@@ -541,25 +528,12 @@ static void mt_get_feature(struct hid_device *hdev, struct hid_report *report)
dev_warn(&hdev->dev, "failed to fetch feature %d\n",
report->id);
} else {
- /*
- * The report ID in the request and the response should match.
- * Some firmware (e.g. the ASUS ROG Z13 Folio
- * touchpad) returns a mismatched ID on this specific fetch;
- * tolerate it only for devices explicitly flagged as such.
- */
- if (report->id != buf[0] &&
- !(td->mtclass.quirks & MT_QUIRK_IGNORE_FEATURE_ID_MISMATCH)) {
- hid_err(hdev, "Returned feature report did not match the request\n");
- goto free;
- }
-
ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf,
size, size, 0);
if (ret)
dev_warn(&hdev->dev, "failed to report feature\n");
}
-free:
kfree(buf);
}
@@ -2734,12 +2708,6 @@ static const struct hid_device_id mt_devices[] = {
HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288) },
- /* Asus ROG Flow Z13 (2025) GZ302EA keyboard-cover touchpad */
- { .driver_data = MT_CLS_ASUS_ROG_Z13_FOLIO,
- HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8,
- USB_VENDOR_ID_ASUSTEK,
- USB_DEVICE_ID_ASUSTEK_ROG_Z13_FOLIO) },
-
/* Generic MT device */
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) },
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 9/9] HID: playstation: Drop redundant report ID validation in ps_get_report
2026-10-13 3:42 [PATCH 0/9] HID: Hardening report validation and unnumbered report handling Dmitry Torokhov
` (7 preceding siblings ...)
2026-10-13 3:42 ` [PATCH 8/9] HID: multitouch: Drop redundant report ID validation in mt_get_feature Dmitry Torokhov
@ 2026-10-13 3:42 ` Dmitry Torokhov
8 siblings, 0 replies; 14+ messages in thread
From: Dmitry Torokhov @ 2026-10-13 3:42 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, David Rheinsberg,
Frank Praznik, Jiri Kosina, Benjamin Tissoires, Even Xu,
Xinpeng Sun, Roderick Colenbrander
Cc: linux-bluetooth, linux-kernel, linux-input, Shashikirana H K
Now that the core HID request handling validates returned report IDs
for report retrieval requests centrally, the report ID check in the
PlayStation driver is redundant. Drop it.
Assisted-by: LLM
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/hid/hid-playstation.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c
index f9dc9378cf77..de51a22ecf0c 100644
--- a/drivers/hid/hid-playstation.c
+++ b/drivers/hid/hid-playstation.c
@@ -813,11 +813,6 @@ static int ps_get_report(struct hid_device *hdev, u8 report_id, u8 *buf,
return -EINVAL;
}
- if (buf[0] != report_id) {
- hid_err(hdev, "Invalid reportID received, expected %d got %d\n", report_id, buf[0]);
- return -EINVAL;
- }
-
if (hdev->bus == BUS_BLUETOOTH && check_crc) {
/* Last 4 bytes contains crc32. */
u8 crc_offset = size - 4;
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread