CVE-2026-15923: Infinite loop denial of service in Zephyr SDIO byte-I/O from a card-supplied zero max_blk_size
The Zephyr SDIO subsystem function sdioiorwextendedhelper() in subsys/sd/sdio.c finishes transfers with a byte-I/O loop that uses size = MIN(remaining, func->cis.maxblksize) as the per-iteration step. The value func->cis.maxblksize is decoded directly from the SDIO card's CIS FUNCE tuple in sdiodecodecis() and is not validated. When a card reports a maximum block size of zero, size is always 0, remaining never decreases, and the loop spins forever.
The loop is reached from the public SDIO client API used by drivers, including sdioreadfifo(), sdiowritefifo(), and the incrementing register read/write helpers, each of which enters the loop while holding the per-card mutex func->card->lock. A card advertising maxblksize == 0 therefore hangs the calling thread permanently on its first non-block-aligned transfer and never releases the mutex, denying service to the SDIO peripheral (and any subsystem such as Wi-Fi that depends on it) until the device is reset.
The malicious value must come from the SDIO card itself, so the defect is exploitable where a removable SDIO/combo card slot lets an attacker insert a crafted or malfunctioning card (a physical attack vector); on boards with a soldered SDIO peripheral it is not attacker-influenceable. There is no memory-safety, confidentiality, or integrity impact — only a permanent availability loss. The fix returns -EIO when func->cis.maxblksize is zero, before the loop is entered.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Configuration
Add validation so that when the SDIO card reports max_blk_size == 0 in the CIS FUNCE tuple, sdio_io_rw_extended_helper() returns -EIO prior to the MIN(remaining, func->cis.max_blk_size) byte-I/O loop (prevents size==0 infinite loop while holding func->card->lock).
Zephyr SDIO CIS decoding (sdio_decode_cis()) func->cis.max_blk_size validation = reject/handle zero max_blk_size by returning -EIO before entering the loop
Event History
Frequently Asked Questions
Which deployments are realistically exposed?
Deployments with a removable SDIO or combo-card slot are exposed when an attacker can insert a crafted card, or when a malfunctioning card is present. The card must advertise a maximum block size of zero in its CIS FUNCE tuple.
What must occur to trigger the denial of service?
A driver must issue a non-block-aligned transfer through the public SDIO client API, such as FIFO read or write or an incrementing register read or write helper. With a card-reported maximum block size of zero, the transfer loop makes no progress and spins indefinitely.
What is the operational impact once triggered?
The calling thread hangs permanently while holding the per-card mutex. This denies access to the SDIO peripheral and can also disrupt dependent subsystems, such as Wi-Fi, until the device is reset.
Are only applications using a specific SDIO API affected?
The affected loop is reachable through multiple public SDIO client APIs used by drivers, including sdio_read_fifo(), sdio_write_fifo(), and incrementing register read and write helpers. Any such call that reaches a non-block-aligned byte-I/O transfer can trigger the condition with the malicious card.