FOTG210 USB Device Controller: slab out-of-bounds via attacker-controlled wIndex
Overview
The FOTG210 USB device controller processes USB SETUP packets from a fully untrusted USB host.
Endpoint selection is derived directly from the wIndex field without validating against the endpoint table size.
The index derivation is:
ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK
This produces values in the range 0–15, while the endpoint array size is fixed at 5.
Memory layout mismatch
#define FOTG210_MAX_NUM_EP 5 struct fotg210_ep *ep[5];
Valid index range: 0–4
Heap layout constraint:
ep[] starts at offset 952 in struct fotg210_udc kmalloc-1k boundary at 1024 bytes
- 0–4 → valid endpoints
- 5–8 → intra-object overwrite region
- 9–15 → slab out-of-bounds access
Attack surface
USB SETUP packets are read directly from hardware FIFO and copied into driver state:
fotg210_rdsetupp() → ioread32(FOTG210_CXPORT) → ctrl structure populated → dispatched to request handlers
No validation is performed on wIndex before it is used in endpoint selection.
Vulnerability 1 - clear_feature OOB dereference
ep = fotg210->ep[ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK]; ep->wedged
The pointer is derived from an unchecked index and immediately dereferenced.
BUG: KASAN: slab-out-of-bounds in fotg210_clear_feature+0x2ba/0x2d0 Read of size 8 at addr ffff888008d9ec30 by task insmod/61 fotg210_clear_feature+0x2ba/0x2d0 poc_init+0x1a7/0xff0 The buggy address is located 120 bytes beyond a 952-byte allocation
Secondary failure:
KASAN: null-ptr-deref in range [0x0000000000000060-0x0000000000000067] RIP: fotg210_clear_feature+0x158/0x2d0 RBP: 0x0000000000000000
Vulnerability 2 - set_feature MMIO corruption chain
ep = fotg210->ep[epnum]; fotg210_set_epnstall(ep);
Fields from the OOB endpoint pointer are used to compute MMIO register addresses, allowing heap corruption to influence hardware register access.
BUG: KASAN: slab-out-of-bounds in fotg210_set_feature+0x274/0x2a0 Read of size 8 at addr ffff888008d9d430 by task insmod/62 fotg210_set_feature+0x274/0x2a0 poc_init+0x1a7/0xff0
Secondary crash:
KASAN: null-ptr-deref in range [0x0000000000000048-0x000000000000004f] RIP: fotg210_set_epnstall+0x26/0x230 RDI: 0x0000000000000048
Vulnerability 3 - get_status information leak path
fotg210_is_epnstall(fotg210->ep[epnum]);
OOB-derived endpoint fields influence MMIO reads and are propagated back into USB responses.
BUG: KASAN: slab-out-of-bounds in fotg210_get_status+0x465/0x4a0 Read of size 8 at addr ffff888008d87c30 by task insmod/63 fotg210_get_status+0x465/0x4a0 poc_init+0x1a6/0xff0
Secondary crash:
KASAN: null-ptr-deref in range [0x0000000000000048-0x000000000000004f] RIP: fotg210_get_status+0x21b/0x4a0 RDI: 0x0000000000000048
Impact
- Slab out-of-bounds reads in kernel heap
- Cross-object memory interpretation via struct pointer reuse
- Indirect MMIO register manipulation via corrupted endpoint fields
- Information disclosure via USB control response path
Root cause
The driver assumes that:
(wIndex & 0x0f) is always a valid endpoint index
This assumption breaks because the mask does not enforce the actual array bounds:
FOTG210_MAX_NUM_EP = 5
No secondary validation exists before dereferencing fotg210->ep[].
Fix
u8 epnum = ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK;
if (epnum >= FOTG210_MAX_NUM_EP) {
fotg210_request_error(fotg210);
return;
}
struct fotg210_ep *ep = fotg210->ep[epnum];
All endpoint accesses must validate the derived index before dereferencing.
Author
Pavitra Jha
Offensive Security Researcher
Kernel / Driver Exploitation Research