summaryrefslogtreecommitdiff
path: root/drivers/hid
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2019-12-10 16:26:11 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-01-14 20:04:26 +0100
commit2aa4a4c5098ee7fa7fc6c4adafc0e86be9def5a6 (patch)
treedac5ce7ac00f580de970e5bd44db1ac6edd2d1f9 /drivers/hid
parent5cd0449a27b56a4686f48b5ba1c51bc87299f7e5 (diff)
HID: Fix slab-out-of-bounds read in hid_field_extract
commit 8ec321e96e056de84022c032ffea253431a83c3c upstream. The syzbot fuzzer found a slab-out-of-bounds bug in the HID report handler. The bug was caused by a report descriptor which included a field with size 12 bits and count 4899, for a total size of 7349 bytes. The usbhid driver uses at most a single-page 4-KB buffer for reports. In the test there wasn't any problem about overflowing the buffer, since only one byte was received from the device. Rather, the bug occurred when the HID core tried to extract the data from the report fields, which caused it to try reading data beyond the end of the allocated buffer. This patch fixes the problem by rejecting any report whose total length exceeds the HID_MAX_BUFFER_SIZE limit (minus one byte to allow for a possible report index). In theory a device could have a report longer than that, but if there was such a thing we wouldn't handle it correctly anyway. Reported-and-tested-by: syzbot+09ef48aa58261464b621@syzkaller.appspotmail.com Signed-off-by: Alan Stern <stern@rowland.harvard.edu> CC: <stable@vger.kernel.org> Signed-off-by: Jiri Kosina <jkosina@suse.cz> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/hid-core.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index c89eb3c3965c..e382d6f23097 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -269,6 +269,12 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
offset = report->size;
report->size += parser->global.report_size * parser->global.report_count;
+ /* Total size check: Allow for possible report index byte */
+ if (report->size > (HID_MAX_BUFFER_SIZE - 1) << 3) {
+ hid_err(parser->device, "report is too long\n");
+ return -1;
+ }
+
if (!parser->local.usage_index) /* Ignore padding fields */
return 0;