| ▲ | NooneAtAll3 5 days ago | |
> The DesignWare USB controller stores up to three consecutive Setup packets in memory. > Upon receiving a fourth Setup transaction, the DMA base address gets reset to its starting position before writing, akin to a ring buffer mechanism. > After writing each received packet, the controller increments DOEPDMA by the size of data written. The reset operation is implemented by decrementing DOEPDMA by 24. > The core issue arises because the controller also accepts smaller packets (though always stores in 4-byte chunks). > Since the pointer increment does not match the fixed decrement amount, we end up with a buffer underflow primitive in 12-byte steps. so the problem is directly in the hardware, not in driver what kind of defense would work against such bugs? ==== wait, am I understanding it right that DMA access was given directly to the stack?? | ||
| ▲ | summa_tech 6 hours ago | parent | next [-] | |
On most modern Apple SoCs, including these two, there's an IOMMU dedicated to the USB complex (called the USB DART, perhaps DMA Address Remapping Table). However, Boot ROM on these two chips does not program it; Apple probably felt that it was an unnecessary technical risk to do so. The Boot ROM code was well-verified and unlikely to contain bugs like buffer overflows. But nobody expected a hardware bug :) | ||
| ▲ | Graziano_M 4 hours ago | parent | prev [-] | |
The DMA buffer points to the heap. The USB controller has access to it, but it only increments it and decrements. By sending multiple packets that are smaller than typical, we can trick the USB controller to decrement the base pointer by more than it should, getting to underflow. It so happens that on A12, the DMA buffer is after the USB task stack, so getting it to decrement by enough will get it to point to the task stack, where we can then write to LR and control where some function on the stack will eventually return to. | ||