From fe71720c1d6286db6aaf11470dadfed7b72438d3 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 8 Aug 2025 09:08:51 +0800 Subject: [PATCH 1/3] HID: core: ensure the allocated report buffer can contain the reserved report ID stable inclusion from stable-v6.6.100 commit fcda39a9c5b834346088c14b1374336b079466c1 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ICPD1U CVE: CVE-2025-38495 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=fcda39a9c5b834346088c14b1374336b079466c1 -------------------------------- commit 4f15ee98304b96e164ff2340e1dfd6181c3f42aa upstream. When the report ID is not used, the low level transport drivers expect the first byte to be 0. However, currently the allocated buffer not account for that extra byte, meaning that instead of having 8 guaranteed bytes for implement to be working, we only have 7. Reported-by: Alan Stern Closes: https://lore.kernel.org/linux-input/c75433e0-9b47-4072-bbe8-b1d14ea97b13@rowland.harvard.edu/ Cc: stable@vger.kernel.org Suggested-by: Alan Stern Link: https://patch.msgid.link/20250710-report-size-null-v2-1-ccf922b7c4e5@kernel.org Signed-off-by: Benjamin Tissoires Signed-off-by: Greg Kroah-Hartman Signed-off-by: Pan Taixi --- drivers/hid/hid-core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 8f156a69912c..04fafe95e9d1 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1873,9 +1873,12 @@ u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags) /* * 7 extra bytes are necessary to achieve proper functionality * of implement() working on 8 byte chunks + * 1 extra byte for the report ID if it is null (not used) so + * we can reserve that extra byte in the first position of the buffer + * when sending it to .raw_request() */ - u32 len = hid_report_len(report) + 7; + u32 len = hid_report_len(report) + 7 + (report->id == 0); return kzalloc(len, flags); } -- Gitee From 598f7d16da43e57d3d1aba86ab616cc64efc204b Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 8 Aug 2025 09:08:52 +0800 Subject: [PATCH 2/3] HID: core: ensure __hid_request reserves the report ID as the first byte stable inclusion from stable-v6.6.100 commit a1c0b87b76824d14979ec7634fc3126b1b64c25a category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ICPD1U CVE: CVE-2025-38495 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=a1c0b87b76824d14979ec7634fc3126b1b64c25a -------------------------------- commit 0d0777ccaa2d46609d05b66ba0096802a2746193 upstream. The low level transport driver expects the first byte to be the report ID, even when the report ID is not use (in which case they just shift the buffer). However, __hid_request() whas not offsetting the buffer it used by one in this case, meaning that the raw_request() callback emitted by the transport driver would be stripped of the first byte. Note: this changes the API for uhid devices when a request is made through hid_hw_request. However, several considerations makes me think this is fine: - every request to a HID device made through hid_hw_request() would see that change, but every request made through hid_hw_raw_request() already has the new behaviour. So that means that the users are already facing situations where they might have or not the first byte being the null report ID when it is 0. We are making things more straightforward in the end. - uhid is mainly used for BLE devices - uhid is also used for testing, but I don't see that change a big issue - for BLE devices, we can check which kernel module is calling hid_hw_request() - and in those modules, we can check which are using a Bluetooth device - and then we can check if the command is used with a report ID or not. - surprise: none of the kernel module are using a report ID 0 - and finally, bluez, in its function set_report()[0], does the same shift if the report ID is 0 and the given buffer has a size > 0. [0] https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/profiles/input/hog-lib.c#n879 Reported-by: Alan Stern Closes: https://lore.kernel.org/linux-input/c75433e0-9b47-4072-bbe8-b1d14ea97b13@rowland.harvard.edu/ Reported-by: syzbot+8258d5439c49d4c35f43@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=8258d5439c49d4c35f43 Tested-by: syzbot+8258d5439c49d4c35f43@syzkaller.appspotmail.com Fixes: 4fa5a7f76cc7 ("HID: core: implement generic .request()") Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20250710-report-size-null-v2-2-ccf922b7c4e5@kernel.org Signed-off-by: Benjamin Tissoires Signed-off-by: Greg Kroah-Hartman Signed-off-by: Pan Taixi --- drivers/hid/hid-core.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 04fafe95e9d1..5d2fc2f403f0 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1941,7 +1941,7 @@ static struct hid_report *hid_get_report(struct hid_report_enum *report_enum, int __hid_request(struct hid_device *hid, struct hid_report *report, enum hid_class_request reqtype) { - char *buf; + char *buf, *data_buf; int ret; u32 len; @@ -1949,10 +1949,17 @@ int __hid_request(struct hid_device *hid, struct hid_report *report, if (!buf) return -ENOMEM; + data_buf = buf; len = hid_report_len(report); + if (report->id == 0) { + /* reserve the first byte for the report ID */ + data_buf++; + len++; + } + if (reqtype == HID_REQ_SET_REPORT) - hid_output_report(report, buf); + hid_output_report(report, data_buf); ret = hid->ll_driver->raw_request(hid, report->id, buf, len, report->type, reqtype); -- Gitee From 5cd708ec25971f429dc7590a3f14ef0ea8ac4516 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 8 Aug 2025 09:08:53 +0800 Subject: [PATCH 3/3] HID: core: do not bypass hid_hw_raw_request stable inclusion from stable-v6.6.100 commit 0e5017d84d650ca0eeaf4a3fe9264c5dbc886b81 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ICPD1U CVE: CVE-2025-38495 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=0e5017d84d650ca0eeaf4a3fe9264c5dbc886b81 -------------------------------- commit c2ca42f190b6714d6c481dfd3d9b62ea091c946b upstream. hid_hw_raw_request() is actually useful to ensure the provided buffer and length are valid. Directly calling in the low level transport driver function bypassed those checks and allowed invalid paramto be used. Reported-by: Alan Stern Closes: https://lore.kernel.org/linux-input/c75433e0-9b47-4072-bbe8-b1d14ea97b13@rowland.harvard.edu/ Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20250710-report-size-null-v2-3-ccf922b7c4e5@kernel.org Signed-off-by: Benjamin Tissoires Signed-off-by: Greg Kroah-Hartman Signed-off-by: Pan Taixi --- drivers/hid/hid-core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 5d2fc2f403f0..266cd56dec50 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1961,8 +1961,7 @@ int __hid_request(struct hid_device *hid, struct hid_report *report, if (reqtype == HID_REQ_SET_REPORT) hid_output_report(report, data_buf); - ret = hid->ll_driver->raw_request(hid, report->id, buf, len, - report->type, reqtype); + ret = hid_hw_raw_request(hid, report->id, buf, len, report->type, reqtype); if (ret < 0) { dbg_hid("unable to complete request: %d\n", ret); goto out; -- Gitee