mirror of
https://github.com/hathach/tinyusb.git
synced 2026-08-18 11:02:16 +00:00
improve validation structure
Signed-off-by: HiFiPhile <admin@hifiphile.com>
This commit is contained in:
@ -715,18 +715,10 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t
|
||||
// Enumeration
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Descriptor-walk hardening gated by CFG_TUH_VALIDATION_LEVEL: at NONE the guards collapse to a pass so
|
||||
// trusted-device setups pay no code size; at BASIC (default) the walk stays inside the enumeration buffer.
|
||||
#if CFG_TUH_VALIDATION_LEVEL >= TUSB_VALIDATION_BASIC
|
||||
#define TU_DESC_VALIDATE(_cond) (_cond)
|
||||
#else
|
||||
#define TU_DESC_VALIDATE(_cond) (true)
|
||||
#endif
|
||||
|
||||
static bool open_ep_stream_pair(cdch_interface_t *p_cdc, tusb_desc_endpoint_t const *desc_ep) {
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
// pin bLength so tu_desc_next() below cannot walk the second endpoint past a caller-checked bound
|
||||
TU_ASSERT(TU_DESC_VALIDATE(sizeof(tusb_desc_endpoint_t) == desc_ep->bLength) &&
|
||||
TU_ASSERT(TUH_VALIDATE_BASIC(sizeof(tusb_desc_endpoint_t) == desc_ep->bLength) &&
|
||||
TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer,
|
||||
0);
|
||||
TU_ASSERT(tuh_edpt_open(p_cdc->daddr, desc_ep));
|
||||
@ -1024,7 +1016,7 @@ static uint16_t acm_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, u
|
||||
const uint8_t *p_desc = (const uint8_t *)itf_desc;
|
||||
const uint8_t *desc_end = p_desc + max_len;
|
||||
|
||||
TU_ASSERT(TU_DESC_VALIDATE(tu_desc_len(p_desc) <= max_len), 0);
|
||||
TU_ASSERT(TUH_VALIDATE_BASIC(tu_desc_len(p_desc) <= max_len), 0);
|
||||
|
||||
cdch_interface_t *p_cdc = make_new_itf(daddr, itf_desc);
|
||||
TU_VERIFY(p_cdc, 0);
|
||||
@ -1036,11 +1028,13 @@ static uint16_t acm_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, u
|
||||
// Communication Functional Descriptors
|
||||
// need the 3-byte header (bLength/bDescriptorType/bDescriptorSubType) in bounds before reading it, and a
|
||||
// fully contained bLength >= 3 both keeps those reads valid and stops a zero-length descriptor from spinning
|
||||
while ((p_desc < desc_end) && TU_DESC_VALIDATE((size_t)(desc_end - p_desc) >= 3) &&
|
||||
TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && TU_DESC_VALIDATE(tu_desc_len(p_desc) >= 3) &&
|
||||
TU_DESC_VALIDATE(tu_desc_len(p_desc) <= (size_t)(desc_end - p_desc))) {
|
||||
while ((p_desc < desc_end) &&
|
||||
TUH_VALIDATE_BASIC((size_t)(desc_end - p_desc) >= 3) &&
|
||||
TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) &&
|
||||
TUH_VALIDATE_BASIC(tu_desc_len(p_desc) >= 3) &&
|
||||
TUH_VALIDATE_BASIC(tu_desc_len(p_desc) <= (size_t)(desc_end - p_desc))) {
|
||||
if (CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) &&
|
||||
TU_DESC_VALIDATE(tu_desc_len(p_desc) >= sizeof(cdc_desc_func_acm_t))) {
|
||||
TUH_VALIDATE_BASIC(tu_desc_len(p_desc) >= sizeof(cdc_desc_func_acm_t))) {
|
||||
// save ACM bmCapabilities
|
||||
p_cdc->acm.capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities;
|
||||
}
|
||||
@ -1051,7 +1045,7 @@ static uint16_t acm_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, u
|
||||
// Open notification endpoint of control interface if any
|
||||
if (itf_desc->bNumEndpoints == 1) {
|
||||
// whole endpoint descriptor must fit: tuh_edpt_open reads the full struct regardless of bLength
|
||||
TU_ASSERT(TU_DESC_VALIDATE((size_t)(desc_end - p_desc) >= sizeof(tusb_desc_endpoint_t)), 0);
|
||||
TU_ASSERT(TUH_VALIDATE_BASIC((size_t)(desc_end - p_desc) >= sizeof(tusb_desc_endpoint_t)), 0);
|
||||
TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc), 0);
|
||||
const tusb_desc_endpoint_t *desc_ep = (const tusb_desc_endpoint_t *)p_desc;
|
||||
TU_ASSERT(tuh_edpt_open(daddr, desc_ep), 0);
|
||||
@ -1062,15 +1056,15 @@ static uint16_t acm_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, u
|
||||
}
|
||||
|
||||
//------------- Data Interface (if any) -------------//
|
||||
if (TU_DESC_VALIDATE((size_t)(desc_end - p_desc) >= sizeof(tusb_desc_interface_t)) &&
|
||||
if (TUH_VALIDATE_BASIC((size_t)(desc_end - p_desc) >= sizeof(tusb_desc_interface_t)) &&
|
||||
TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) {
|
||||
const tusb_desc_interface_t *data_itf = (const tusb_desc_interface_t *)p_desc;
|
||||
if (data_itf->bInterfaceClass == TUSB_CLASS_CDC_DATA) {
|
||||
p_desc += sizeof(tusb_desc_interface_t); // fixed struct size to endpoint descriptor, not device bLength
|
||||
|
||||
// open_ep_stream_pair consumes exactly two endpoints; require that count and that both fit before reading them
|
||||
TU_ASSERT(TU_DESC_VALIDATE(data_itf->bNumEndpoints == 2), 0);
|
||||
TU_ASSERT(TU_DESC_VALIDATE((size_t)(desc_end - p_desc) >= 2 * sizeof(tusb_desc_endpoint_t)), 0);
|
||||
TU_ASSERT(TUH_VALIDATE_BASIC(data_itf->bNumEndpoints == 2), 0);
|
||||
TU_ASSERT(TUH_VALIDATE_BASIC((size_t)(desc_end - p_desc) >= 2 * sizeof(tusb_desc_endpoint_t)), 0);
|
||||
TU_ASSERT(open_ep_stream_pair(p_cdc, (const tusb_desc_endpoint_t *)p_desc), 0);
|
||||
p_desc += 2 * sizeof(tusb_desc_endpoint_t);
|
||||
}
|
||||
|
||||
@ -240,13 +240,14 @@
|
||||
#define OPT_MODE_SPEED_MASK 0xff00u
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Descriptor Validation Level
|
||||
// How much the stack hardens itself against mal-configured or hostile devices, traded against code size.
|
||||
// Higher levels add more checks; set CFG_TUD_VALIDATION_LEVEL / CFG_TUH_VALIDATION_LEVEL to pick one.
|
||||
// Validation Level
|
||||
// Optional validation of data received from the USB peer, traded against code size. Coverage is parser-specific
|
||||
// and expanded incrementally. CFG_TUSB_VALIDATION_LEVEL sets the default for both device and host; use the
|
||||
// CFG_TUD_VALIDATION_LEVEL / CFG_TUH_VALIDATION_LEVEL overrides when the roles need different policies.
|
||||
//--------------------------------------------------------------------+
|
||||
#define TUSB_VALIDATION_NONE 0 ///< trusted devices only, minimal code size
|
||||
#define TUSB_VALIDATION_BASIC 1 ///< default: mal-configured devices, no OOB reads / zero-length loops
|
||||
#define TUSB_VALIDATION_STRICT 2 ///< reject malformed/hostile descriptors, stricter class validation
|
||||
#define TUSB_VALIDATION_NONE 0 ///< trusted peers, minimal code size
|
||||
#define TUSB_VALIDATION_BASIC 1 ///< structural memory-safety checks where supported
|
||||
#define TUSB_VALIDATION_STRICT 2 ///< additional USB and class-specific conformance checks
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Include tusb_config.h
|
||||
@ -261,6 +262,46 @@
|
||||
|
||||
#include "common/tusb_mcu.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Validation Options
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
#ifndef CFG_TUSB_VALIDATION_LEVEL
|
||||
#define CFG_TUSB_VALIDATION_LEVEL TUSB_VALIDATION_BASIC
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUD_VALIDATION_LEVEL
|
||||
#define CFG_TUD_VALIDATION_LEVEL CFG_TUSB_VALIDATION_LEVEL
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUH_VALIDATION_LEVEL
|
||||
#define CFG_TUH_VALIDATION_LEVEL CFG_TUSB_VALIDATION_LEVEL
|
||||
#endif
|
||||
|
||||
#if (CFG_TUSB_VALIDATION_LEVEL < TUSB_VALIDATION_NONE) || \
|
||||
(CFG_TUSB_VALIDATION_LEVEL > TUSB_VALIDATION_STRICT)
|
||||
#error "CFG_TUSB_VALIDATION_LEVEL must be TUSB_VALIDATION_NONE, TUSB_VALIDATION_BASIC, or TUSB_VALIDATION_STRICT"
|
||||
#endif
|
||||
|
||||
#if (CFG_TUD_VALIDATION_LEVEL < TUSB_VALIDATION_NONE) || \
|
||||
(CFG_TUD_VALIDATION_LEVEL > TUSB_VALIDATION_STRICT)
|
||||
#error "CFG_TUD_VALIDATION_LEVEL must be TUSB_VALIDATION_NONE, TUSB_VALIDATION_BASIC, or TUSB_VALIDATION_STRICT"
|
||||
#endif
|
||||
|
||||
#if (CFG_TUH_VALIDATION_LEVEL < TUSB_VALIDATION_NONE) || \
|
||||
(CFG_TUH_VALIDATION_LEVEL > TUSB_VALIDATION_STRICT)
|
||||
#error "CFG_TUH_VALIDATION_LEVEL must be TUSB_VALIDATION_NONE, TUSB_VALIDATION_BASIC, or TUSB_VALIDATION_STRICT"
|
||||
#endif
|
||||
|
||||
// Validation conditions are short-circuited at lower levels and compile out when the result is unused.
|
||||
#define TUD_VALIDATION_CHECK(_level, _cond) ((CFG_TUD_VALIDATION_LEVEL < (_level)) || (_cond))
|
||||
#define TUH_VALIDATION_CHECK(_level, _cond) ((CFG_TUH_VALIDATION_LEVEL < (_level)) || (_cond))
|
||||
|
||||
#define TUD_VALIDATE_BASIC(_cond) TUD_VALIDATION_CHECK(TUSB_VALIDATION_BASIC, _cond)
|
||||
#define TUH_VALIDATE_BASIC(_cond) TUH_VALIDATION_CHECK(TUSB_VALIDATION_BASIC, _cond)
|
||||
#define TUD_VALIDATE_STRICT(_cond) TUD_VALIDATION_CHECK(TUSB_VALIDATION_STRICT, _cond)
|
||||
#define TUH_VALIDATE_STRICT(_cond) TUH_VALIDATION_CHECK(TUSB_VALIDATION_STRICT, _cond)
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USBIP
|
||||
//--------------------------------------------------------------------+
|
||||
@ -704,9 +745,6 @@
|
||||
#define CFG_TUH_ENUMERATION_BUFSIZE 256
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUH_VALIDATION_LEVEL
|
||||
#define CFG_TUH_VALIDATION_LEVEL TUSB_VALIDATION_BASIC
|
||||
#endif
|
||||
#endif // CFG_TUH_ENABLED
|
||||
|
||||
// Attribute to place data in accessible RAM for host controller (default: CFG_TUSB_MEM_SECTION)
|
||||
|
||||
Reference in New Issue
Block a user