]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 20 Jun 2025 15:50:12 +0000 (17:50 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 20 Jun 2025 15:50:12 +0000 (17:50 +0200)
added patches:
hid-usbhid-eliminate-recurrent-out-of-bounds-bug-in-usbhid_parse.patch

queue-5.10/hid-usbhid-eliminate-recurrent-out-of-bounds-bug-in-usbhid_parse.patch [new file with mode: 0644]
queue-5.10/series

diff --git a/queue-5.10/hid-usbhid-eliminate-recurrent-out-of-bounds-bug-in-usbhid_parse.patch b/queue-5.10/hid-usbhid-eliminate-recurrent-out-of-bounds-bug-in-usbhid_parse.patch
new file mode 100644 (file)
index 0000000..930c9d4
--- /dev/null
@@ -0,0 +1,167 @@
+From fe7f7ac8e0c708446ff017453add769ffc15deed Mon Sep 17 00:00:00 2001
+From: Terry Junge <linuxhid@cosmicgizmosystems.com>
+Date: Wed, 12 Mar 2025 15:23:31 -0700
+Subject: HID: usbhid: Eliminate recurrent out-of-bounds bug in usbhid_parse()
+
+From: Terry Junge <linuxhid@cosmicgizmosystems.com>
+
+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 <linuxhid@cosmicgizmosystems.com>
+Reviewed-by: Michael Kelley <mhklinux@outlook.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Terry Junge <linuxhid@cosmicgizmosystems.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-hyperv.c            |    5 +++--
+ drivers/hid/usbhid/hid-core.c       |   25 ++++++++++++++-----------
+ drivers/usb/gadget/function/f_hid.c |   12 ++++++------
+ include/linux/hid.h                 |    3 ++-
+ 4 files changed, 25 insertions(+), 20 deletions(-)
+
+--- a/drivers/hid/hid-hyperv.c
++++ b/drivers/hid/hid-hyperv.c
+@@ -199,7 +199,8 @@ static void mousevsc_on_receive_device_i
+       if (!input_device->hid_desc)
+               goto cleanup;
+-      input_device->report_desc_size = desc->desc[0].wDescriptorLength;
++      input_device->report_desc_size = le16_to_cpu(
++                                      desc->rpt_desc.wDescriptorLength);
+       if (input_device->report_desc_size == 0) {
+               input_device->dev_info_status = -EINVAL;
+               goto cleanup;
+@@ -217,7 +218,7 @@ static void mousevsc_on_receive_device_i
+       memcpy(input_device->report_desc,
+              ((unsigned char *)desc) + desc->bLength,
+-             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
+@@ -984,12 +984,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);
+@@ -1011,20 +1010,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);
+@@ -1052,6 +1050,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
+@@ -674,8 +674,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)                                   \
index fbb5007d73f25864d54bde999a433331665ec138..5b0e4edd05640daf1eca1b36ffa20f491ec14db7 100644 (file)
@@ -291,3 +291,4 @@ scsi-s390-zfcp-ensure-synchronous-unit_add.patch
 udmabuf-use-sgtable-based-scatterlist-wrappers.patch
 selinux-fix-selinux_xfrm_alloc_user-to-set-correct-ctx_len.patch
 atm-revert-atm_account_tx-if-copy_from_iter_full-fails.patch
+hid-usbhid-eliminate-recurrent-out-of-bounds-bug-in-usbhid_parse.patch