Skip to content

Commit 86c3638

Browse files
Merge pull request #413 from espressif/fix/CVE-UNTRUST-002
fix(host): Limit max endpoints in interface to 32
2 parents a1b7172 + c546816 commit 86c3638

File tree

4 files changed

+55
-5
lines changed

4 files changed

+55
-5
lines changed

host/usb/include/usb/usb_helpers.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -79,7 +79,7 @@ int usb_parse_interface_number_of_alternate(const usb_config_desc_t *config_desc
7979
* @param[in] bInterfaceNumber Interface number
8080
* @param[in] bAlternateSetting Alternate setting number
8181
* @param[out] offset Byte offset of the interface descriptor relative to the start of the configuration descriptor. Can be NULL.
82-
* @return const usb_intf_desc_t* Pointer to interface descriptor, NULL if not found.
82+
* @return const usb_intf_desc_t* Pointer to interface descriptor, NULL if not found or invalid (e.g., too many endpoints) descriptor
8383
*/
8484
const usb_intf_desc_t *usb_parse_interface_descriptor(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, int *offset);
8585

host/usb/include/usb/usb_types_ch9.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -432,6 +432,11 @@ ESP_STATIC_ASSERT(sizeof(usb_iad_desc_t) == USB_IAD_DESC_SIZE, "Size of usb_iad_
432432
*/
433433
#define USB_INTF_DESC_SIZE 9
434434

435+
/**
436+
* @brief Maximum number of endpoints in a USB interface descriptor
437+
*/
438+
#define USB_MAX_ENDPOINTS_PER_INTERFACE 32 // 16 IN and 16 OUT
439+
435440
/**
436441
* @brief Structure representing a USB interface descriptor
437442
*

host/usb/src/usb_helpers.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,16 @@ const usb_intf_desc_t *usb_parse_interface_descriptor(const usb_config_desc_t *c
107107
// Get the next interface descriptor
108108
next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp);
109109
}
110-
if (next_intf_desc != NULL && offset != NULL) {
111-
*offset = offset_temp;
110+
111+
if (next_intf_desc != NULL) {
112+
// In case offset was provided, set it
113+
if (offset != NULL) {
114+
*offset = offset_temp;
115+
}
116+
// Check if the interface descriptor has too many endpoints
117+
if (next_intf_desc->bNumEndpoints > USB_MAX_ENDPOINTS_PER_INTERFACE) {
118+
return NULL; // Too many endpoints, invalid descriptor
119+
}
112120
}
113121
return next_intf_desc;
114122
}

host/usb/test/host_test/usb_host_layer_test/main/usb_helpers_descriptor_parsing_test.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,3 +477,40 @@ TEST_CASE("USB descriptor parsing with bLength=0", "[helpers]")
477477
}
478478
}
479479
}
480+
481+
TEST_CASE("USB descriptor parsing with interface that has too many endpoints", "[helpers]")
482+
{
483+
// Minimal config descriptor containing an interface with bNumEndpoints > USB_MAX_ENDPOINTS_PER_INTERFACE (32)
484+
static const uint8_t bad_config_desc_bytes[] = {
485+
// Configuration Descriptor (9 bytes)
486+
0x09, // bLength = 9
487+
0x02, // bDescriptorType = Configuration
488+
0x12, 0x00, // wTotalLength = 18
489+
0x01, // bNumInterfaces = 1
490+
0x01, // bConfigurationValue = 1
491+
0x00, // iConfiguration = 0
492+
0x80, // bmAttributes
493+
0x32, // bMaxPower = 100mA
494+
// Interface Descriptor (9 bytes) with bNumEndpoints = 33 (> 32)
495+
0x09, // bLength = 9
496+
0x04, // bDescriptorType = Interface
497+
0x00, // bInterfaceNumber = 0
498+
0x00, // bAlternateSetting = 0
499+
0x21, // bNumEndpoints = 33 <-- exceeds USB_MAX_ENDPOINTS_PER_INTERFACE
500+
0xFF, 0x00, 0x00, 0x00, // bInterfaceClass, SubClass, Protocol, iInterface
501+
};
502+
503+
const auto *config_desc = reinterpret_cast<const usb_config_desc_t *>(bad_config_desc_bytes);
504+
505+
GIVEN("A configuration descriptor with an interface declaring too many endpoints") {
506+
int offset = 0;
507+
508+
WHEN("Parsing the interface descriptor by number and alternate setting") {
509+
const auto *intf_desc = usb_parse_interface_descriptor(config_desc, 0, 0, &offset);
510+
511+
THEN("The parser returns NULL and rejects the invalid descriptor") {
512+
REQUIRE(intf_desc == nullptr);
513+
}
514+
}
515+
}
516+
}

0 commit comments

Comments
 (0)