lkml.org 
[lkml]   [2020]   [Jan]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 07/28] HID: Fix slab-out-of-bounds read in hid_field_extract
    Date
    From: Alan Stern <stern@rowland.harvard.edu>

    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>

    ---
    drivers/hid/hid-core.c | 6 ++++++
    1 file changed, 6 insertions(+)

    --- a/drivers/hid/hid-core.c
    +++ b/drivers/hid/hid-core.c
    @@ -269,6 +269,12 @@ static int hid_add_field(struct hid_pars
    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;


    \
     
     \ /
      Last update: 2020-01-14 11:14    [W:2.489 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site