summaryrefslogtreecommitdiff
path: root/class/hid
diff options
context:
space:
mode:
authorsakumisu <[email protected]>2026-10-22 12:41:45 +0800
committersakumisu <[email protected]>2026-10-23 18:29:36 +0800
commit2397226c48fea88bdb742651f9280f47eef3197a (patch)
tree333db0904d5d3591a93a79f564c4a859f9957ae0 /class/hid
parent26b0feb09bb58ebb7a3161b5605f8e186b96db1f (diff)
fix(security): check array overflowdev
Signed-off-by: sakumisu <[email protected]>
Diffstat (limited to 'class/hid')
-rw-r--r--class/hid/usbh_hid.c46
-rw-r--r--class/hid/usbh_hid.h7
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);