From: Greg Kroah-Hartman Date: Tue, 17 Jun 2025 13:20:14 +0000 (+0200) Subject: 6.1-stable patches X-Git-Tag: v6.6.94~43 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=217bb21577f2e24e276043d9929e06c76268c74c;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: hid-usbhid-eliminate-recurrent-out-of-bounds-bug-in-usbhid_parse.patch --- diff --git a/queue-6.1/hid-usbhid-eliminate-recurrent-out-of-bounds-bug-in-usbhid_parse.patch b/queue-6.1/hid-usbhid-eliminate-recurrent-out-of-bounds-bug-in-usbhid_parse.patch new file mode 100644 index 0000000000..a6c193e87c --- /dev/null +++ b/queue-6.1/hid-usbhid-eliminate-recurrent-out-of-bounds-bug-in-usbhid_parse.patch @@ -0,0 +1,165 @@ +From fe7f7ac8e0c708446ff017453add769ffc15deed Mon Sep 17 00:00:00 2001 +From: Terry Junge +Date: Wed, 12 Mar 2025 15:23:31 -0700 +Subject: HID: usbhid: Eliminate recurrent out-of-bounds bug in usbhid_parse() + +From: Terry Junge + +commit fe7f7ac8e0c708446ff017453add769ffc15deed upstream. + +Update struct hid_descriptor to better reflect the mandatory and +optional parts of the HID Descriptor as per USB HID 1.11 specification. +Note: the kernel currently does not parse any optional HID class +descriptors, only the mandatory report descriptor. + +Update all references to member element desc[0] to rpt_desc. + +Add test to verify bLength and bNumDescriptors values are valid. + +Replace the for loop with direct access to the mandatory HID class +descriptor member for the report descriptor. This eliminates the +possibility of getting an out-of-bounds fault. + +Add a warning message if the HID descriptor contains any unsupported +optional HID class descriptors. + +Reported-by: syzbot+c52569baf0c843f35495@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=c52569baf0c843f35495 +Fixes: f043bfc98c19 ("HID: usbhid: fix out-of-bounds bug") +Cc: stable@vger.kernel.org +Signed-off-by: Terry Junge +Reviewed-by: Michael Kelley +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hid/hid-hyperv.c | 4 ++-- + drivers/hid/usbhid/hid-core.c | 25 ++++++++++++++----------- + drivers/usb/gadget/function/f_hid.c | 12 ++++++------ + include/linux/hid.h | 3 ++- + 4 files changed, 24 insertions(+), 20 deletions(-) + +--- a/drivers/hid/hid-hyperv.c ++++ b/drivers/hid/hid-hyperv.c +@@ -200,7 +200,7 @@ static void mousevsc_on_receive_device_i + goto cleanup; + + input_device->report_desc_size = le16_to_cpu( +- desc->desc[0].wDescriptorLength); ++ desc->rpt_desc.wDescriptorLength); + if (input_device->report_desc_size == 0) { + input_device->dev_info_status = -EINVAL; + goto cleanup; +@@ -218,7 +218,7 @@ static void mousevsc_on_receive_device_i + + memcpy(input_device->report_desc, + ((unsigned char *)desc) + desc->bLength, +- le16_to_cpu(desc->desc[0].wDescriptorLength)); ++ le16_to_cpu(desc->rpt_desc.wDescriptorLength)); + + /* Send the ack */ + memset(&ack, 0, sizeof(struct mousevsc_prt_msg)); +--- a/drivers/hid/usbhid/hid-core.c ++++ b/drivers/hid/usbhid/hid-core.c +@@ -982,12 +982,11 @@ static int usbhid_parse(struct hid_devic + struct usb_host_interface *interface = intf->cur_altsetting; + struct usb_device *dev = interface_to_usbdev (intf); + struct hid_descriptor *hdesc; ++ struct hid_class_descriptor *hcdesc; + u32 quirks = 0; + unsigned int rsize = 0; + char *rdesc; +- int ret, n; +- int num_descriptors; +- size_t offset = offsetof(struct hid_descriptor, desc); ++ int ret; + + quirks = hid_lookup_quirk(hid); + +@@ -1009,20 +1008,19 @@ static int usbhid_parse(struct hid_devic + return -ENODEV; + } + +- if (hdesc->bLength < sizeof(struct hid_descriptor)) { +- dbg_hid("hid descriptor is too short\n"); ++ if (!hdesc->bNumDescriptors || ++ hdesc->bLength != sizeof(*hdesc) + ++ (hdesc->bNumDescriptors - 1) * sizeof(*hcdesc)) { ++ dbg_hid("hid descriptor invalid, bLen=%hhu bNum=%hhu\n", ++ hdesc->bLength, hdesc->bNumDescriptors); + return -EINVAL; + } + + hid->version = le16_to_cpu(hdesc->bcdHID); + hid->country = hdesc->bCountryCode; + +- num_descriptors = min_t(int, hdesc->bNumDescriptors, +- (hdesc->bLength - offset) / sizeof(struct hid_class_descriptor)); +- +- for (n = 0; n < num_descriptors; n++) +- if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT) +- rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength); ++ if (hdesc->rpt_desc.bDescriptorType == HID_DT_REPORT) ++ rsize = le16_to_cpu(hdesc->rpt_desc.wDescriptorLength); + + if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) { + dbg_hid("weird size of report descriptor (%u)\n", rsize); +@@ -1050,6 +1048,11 @@ static int usbhid_parse(struct hid_devic + goto err; + } + ++ if (hdesc->bNumDescriptors > 1) ++ hid_warn(intf, ++ "%u unsupported optional hid class descriptors\n", ++ (int)(hdesc->bNumDescriptors - 1)); ++ + hid->quirks |= quirks; + + return 0; +--- a/drivers/usb/gadget/function/f_hid.c ++++ b/drivers/usb/gadget/function/f_hid.c +@@ -114,8 +114,8 @@ static struct hid_descriptor hidg_desc = + .bcdHID = cpu_to_le16(0x0101), + .bCountryCode = 0x00, + .bNumDescriptors = 0x1, +- /*.desc[0].bDescriptorType = DYNAMIC */ +- /*.desc[0].wDescriptorLenght = DYNAMIC */ ++ /*.rpt_desc.bDescriptorType = DYNAMIC */ ++ /*.rpt_desc.wDescriptorLength = DYNAMIC */ + }; + + /* Super-Speed Support */ +@@ -724,8 +724,8 @@ static int hidg_setup(struct usb_functio + struct hid_descriptor hidg_desc_copy = hidg_desc; + + VDBG(cdev, "USB_REQ_GET_DESCRIPTOR: HID\n"); +- hidg_desc_copy.desc[0].bDescriptorType = HID_DT_REPORT; +- hidg_desc_copy.desc[0].wDescriptorLength = ++ hidg_desc_copy.rpt_desc.bDescriptorType = HID_DT_REPORT; ++ hidg_desc_copy.rpt_desc.wDescriptorLength = + cpu_to_le16(hidg->report_desc_length); + + length = min_t(unsigned short, length, +@@ -966,8 +966,8 @@ static int hidg_bind(struct usb_configur + * We can use hidg_desc struct here but we should not relay + * that its content won't change after returning from this function. + */ +- hidg_desc.desc[0].bDescriptorType = HID_DT_REPORT; +- hidg_desc.desc[0].wDescriptorLength = ++ hidg_desc.rpt_desc.bDescriptorType = HID_DT_REPORT; ++ hidg_desc.rpt_desc.wDescriptorLength = + cpu_to_le16(hidg->report_desc_length); + + hidg_hs_in_ep_desc.bEndpointAddress = +--- a/include/linux/hid.h ++++ b/include/linux/hid.h +@@ -703,8 +703,9 @@ struct hid_descriptor { + __le16 bcdHID; + __u8 bCountryCode; + __u8 bNumDescriptors; ++ struct hid_class_descriptor rpt_desc; + +- struct hid_class_descriptor desc[1]; ++ struct hid_class_descriptor opt_descs[]; + } __attribute__ ((packed)); + + #define HID_DEVICE(b, g, ven, prod) \ diff --git a/queue-6.1/series b/queue-6.1/series index 12a4356941..b9ddcabf18 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -275,3 +275,4 @@ perf-ensure-bpf_perf_link-path-is-properly-serialize.patch bio-fix-bio_first_folio-for-sparsemem-without-vmemma.patch tools-resolve_btfids-fix-build-when-cross-compiling-kernel-with-clang.patch alsa-usb-audio-add-implicit-feedback-quirk-for-rode-ai-1.patch +hid-usbhid-eliminate-recurrent-out-of-bounds-bug-in-usbhid_parse.patch