[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <8a4eb6b0-f640-4207-9f05-83e06080410b@rowland.harvard.edu>
Date: Thu, 17 Jul 2025 22:33:01 -0400
From: Alan Stern <stern@...land.harvard.edu>
To: Benjamin Tissoires <bentiss@...nel.org>
Cc: syzbot <syzbot+b63d677d63bcac06cf90@...kaller.appspotmail.com>,
jikos@...nel.org, linux-input@...r.kernel.org,
linux-kernel@...r.kernel.org, linux-usb@...r.kernel.org,
syzkaller-bugs@...glegroups.com
Subject: [PATCH] HID: core: Reject report fields with a size or count of 0
Testing by the syzbot fuzzer showed that the HID core gets a
shift-out-of-bounds exception when it tries to convert a 32-bit
quantity to a 0-bit quantity. This is hardly an unexpected result,
but it means that we should not accept report fields that have a size
of zero bits. Similarly, there's no reason to accept report fields
with a count of zero; either type of item is completely meaningless
since no information can be conveyed in zero bits.
Reject fields with a size or count of zero, and reject reports
containing such fields.
Signed-off-by: Alan Stern <stern@...land.harvard.edu>
Reported-by: syzbot+b63d677d63bcac06cf90@...kaller.appspotmail.com
Closes: https://lore.kernel.org/linux-usb/68753a08.050a0220.33d347.0008.GAE@google.com/
Tested-by: syzbot+b63d677d63bcac06cf90@...kaller.appspotmail.com
Fixes: dde5845a529f ("[PATCH] Generic HID layer - code split")
Cc: stable@...r.kernel.org
---
The commit listed in the Fixes tag is not really the right one. But
code motion made tracking it back any further more difficult than I
wanted to deal with, so I stopped there. That commit is from 2006,
which is already far enough in the past.
drivers/hid/hid-core.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
Index: usb-devel/drivers/hid/hid-core.c
===================================================================
--- usb-devel.orig/drivers/hid/hid-core.c
+++ usb-devel/drivers/hid/hid-core.c
@@ -313,7 +313,14 @@ static int hid_add_field(struct hid_pars
}
offset = report->size;
- report->size += parser->global.report_size * parser->global.report_count;
+ i = parser->global.report_size * parser->global.report_count;
+ if (i == 0) {
+ dbg_hid("invalid field size/count 0x%x 0x%x\n",
+ parser->global.report_size,
+ parser->global.report_count);
+ return -1;
+ }
+ report->size += i;
if (parser->device->ll_driver->max_buffer_size)
max_buffer_size = parser->device->ll_driver->max_buffer_size;
@@ -464,7 +471,8 @@ static int hid_parser_global(struct hid_
case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
parser->global.report_size = item_udata(item);
- if (parser->global.report_size > 256) {
+ if (parser->global.report_size > 256 ||
+ parser->global.report_size == 0) {
hid_err(parser->device, "invalid report_size %d\n",
parser->global.report_size);
return -1;
@@ -473,7 +481,8 @@ static int hid_parser_global(struct hid_
case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
parser->global.report_count = item_udata(item);
- if (parser->global.report_count > HID_MAX_USAGES) {
+ if (parser->global.report_count > HID_MAX_USAGES ||
+ parser->global.report_count == 0) {
hid_err(parser->device, "invalid report_count %d\n",
parser->global.report_count);
return -1;
Powered by blists - more mailing lists