The MAX3420 USB Device Controller driver uses the USB SETUP packet field wIndex
as an index into a fixed-size endpoint array without validating it against the array bounds.
The derived index is computed as:
id = udc->setup.wIndex & USB_ENDPOINT_NUMBER_MASK;
where USB_ENDPOINT_NUMBER_MASK = 0x0f, producing values in the range 0–15,
while the actual endpoint array size is only 4.
USB SETUP packets originate from a fully untrusted USB host and are ingested directly from hardware:
spi_rd_buf(udc, MAX3420_REG_SUDFIFO, &setup, 8); udc->setup = setup; udc->setup.wIndex = cpu_to_le16(setup.wIndex);
No validation is performed on wIndex before it is used in control flow or memory access.
Endpoint access occurs directly via:
ep = &udc->ep[udc->setup.wIndex & USB_ENDPOINT_NUMBER_MASK];
With:
struct max3420_ep ep[4];
Any value ≥ 4 results in out-of-bounds access.
The function dereferences an endpoint pointer derived from unvalidated input:
ep = &udc->ep[udc->setup.wIndex & USB_ENDPOINT_NUMBER_MASK];
If the index is out of bounds, subsequent field reads operate on unrelated kernel memory, resulting in a heap out-of-bounds read.
The same index is used for write operations:
id = udc->setup.wIndex & USB_ENDPOINT_NUMBER_MASK; ep = &udc->ep[id];
When id ≥ 4, writes target memory beyond the endpoint array,
corrupting adjacent kernel heap or struct fields.
bmRequestType = 0x02 bRequest = SET_FEATURE wValue = ENDPOINT_HALT wIndex = 0x0007 wLength = 0x0000
This produces id = 7, which is outside the valid range [0–3].
max3420_handle_irqs()
→ SUDAVIRQ
→ max3420_handle_setup()
→ spi_rd_buf(SUDFIFO)
→ max3420_getstatus() / max3420_set_clear_feature()
→ udc->ep[index] (no bounds check)
No validation occurs between packet ingestion and array indexing.
AddressSanitizer confirms out-of-bounds access in a userspace harness:
runtime error: index 7 out of bounds for type 'max3420_ep [4]' ERROR: AddressSanitizer: heap-buffer-overflow WRITE of size 1 at 0x... (168 bytes past region) #0 max3420_set_clear_feature #1 run_test #2 main
The access occurs 168 bytes past the allocated region, confirming struct adjacency corruption before heap boundary.
The driver assumes the masked USB field is safe to use as an array index:
wIndex & USB_ENDPOINT_NUMBER_MASK
However, masking does not enforce the actual array bounds (MAX3420_MAX_EPS = 4),
leading to a mismatch between protocol encoding and memory safety constraints.
id = udc->setup.wIndex & USB_ENDPOINT_NUMBER_MASK;
if (id >= MAX3420_MAX_EPS)
goto stall;
ep = &udc->ep[id];
The check must be applied consistently across all endpoint-accessing paths.
All kernels containing the MAX3420 USB Device Controller driver are affected.