diff options
| author | sakumisu <[email protected]> | 2026-10-22 12:41:45 +0800 |
|---|---|---|
| committer | sakumisu <[email protected]> | 2026-10-23 18:29:36 +0800 |
| commit | 2397226c48fea88bdb742651f9280f47eef3197a (patch) | |
| tree | 333db0904d5d3591a93a79f564c4a859f9957ae0 /class/hid | |
| parent | 26b0feb09bb58ebb7a3161b5605f8e186b96db1f (diff) | |
fix(security): check array overflowdev
Signed-off-by: sakumisu <[email protected]>
Diffstat (limited to 'class/hid')
| -rw-r--r-- | class/hid/usbh_hid.c | 46 | ||||
| -rw-r--r-- | class/hid/usbh_hid.h | 7 |
2 files changed, 33 insertions, 20 deletions
diff --git a/class/hid/usbh_hid.c b/class/hid/usbh_hid.c index f8b89786..61d0d7ee 100644 --- a/class/hid/usbh_hid.c +++ b/class/hid/usbh_hid.c @@ -208,21 +208,18 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf) hport->config.intf[intf].priv = hid_class; p = hport->raw_config_desc; - while (p[DESC_bLength]) { + while (desc_len < hport->config.config_desc.wTotalLength) { switch (p[DESC_bDescriptorType]) { case USB_DESCRIPTOR_TYPE_INTERFACE: cur_iface = p[INTF_DESC_bInterfaceNumber]; - if (cur_iface == intf) { - hid_class->protocol = p[7]; - struct usb_hid_descriptor *desc = (struct usb_hid_descriptor *)(p + 9); - - if (desc->bDescriptorType != HID_DESCRIPTOR_TYPE_HID) { - USB_LOG_ERR("HID descriptor not found\r\n"); - return -USB_ERR_INVAL; - } + hid_class->protocol = p[7]; + break; + case HID_DESCRIPTOR_TYPE_HID: + if ((cur_iface == intf) && (p[DESC_bLength] >= sizeof(struct usb_hid_descriptor))) { + struct usb_hid_descriptor *desc = (struct usb_hid_descriptor *)p; if (desc->subdesc[0].bDescriptorType != HID_DESCRIPTOR_TYPE_HID_REPORT) { - USB_LOG_ERR("HID report descriptor not found\r\n"); + USB_LOG_ERR("invalid bDescriptorType\r\n"); return -USB_ERR_INVAL; } @@ -237,19 +234,20 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf) /* skip to next descriptor */ desc_len += p[DESC_bLength]; p += p[DESC_bLength]; - - if (desc_len > hport->config.config_desc.wTotalLength) { - return -USB_ERR_INVAL; - } } if (found == false) { - USB_LOG_ERR("HID interface not found\r\n"); + USB_LOG_ERR("HID report descriptor not found\r\n"); return -USB_ERR_INVAL; } found: for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) { ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc; + + if (USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes) != USB_ENDPOINT_TYPE_INTERRUPT) { + return -USB_ERR_INVAL; + } + if (ep_desc->bEndpointAddress & 0x80) { USBH_EP_INIT(hid_class->intin, ep_desc); } else { @@ -445,19 +443,29 @@ err: return -1; } -int usbh_hid_report_convert(struct usbh_hid_report_item *item, const uint8_t *report_buf, uint32_t *output1, uint8_t **output2, uint32_t *output_len) +int usbh_hid_report_convert(struct usbh_hid_report_item *item, + const uint8_t *report_buf, + uint16_t report_len, + uint32_t *output1, + uint8_t **output2, + uint32_t *output_len) { const uint8_t *src; - uint32_t bits_len = item->attribute.report_size * item->attribute.report_count; - if (bits_len == 0) { + if (!item || !report_buf || !report_len || !output1 || !output2 || !output_len) { return -1; } - if (item->report_flags & HID_MAINITEM_CONSTANT) { + uint32_t bits_len = item->attribute.report_size * item->attribute.report_count; + + if (bits_len == 0 || item->report_flags & HID_MAINITEM_CONSTANT) { return -1; } + if ((item->report_bit_offset + bits_len) > report_len * 8) { + return -USB_ERR_NOMEM; + } + if (item->attribute.report_id > 0) { if (report_buf[0] != item->attribute.report_id) { return -2; /* report id mismatch */ diff --git a/class/hid/usbh_hid.h b/class/hid/usbh_hid.h index 26b22555..23d66335 100644 --- a/class/hid/usbh_hid.h +++ b/class/hid/usbh_hid.h @@ -70,7 +70,12 @@ int usbh_hid_set_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t int usbh_hid_get_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t report_id, uint8_t *buffer, uint32_t buflen); int usbh_hid_parse_report_descriptor(const uint8_t *report_data, uint32_t report_size, struct usbh_hid_report_info *report_info); -int usbh_hid_report_convert(struct usbh_hid_report_item *item, const uint8_t *report_buf, uint32_t *output1, uint8_t **output2, uint32_t *output_len); +int usbh_hid_report_convert(struct usbh_hid_report_item *item, + const uint8_t *report_buf, + uint16_t report_len, + uint32_t *output1, + uint8_t **output2, + uint32_t *output_len); void usbh_hid_run(struct usbh_hid *hid_class); void usbh_hid_stop(struct usbh_hid *hid_class); |
