VIRTIO_BLK_F_MQ with device-reported num_queues=0: modulo-by-zero panic in vtblk_attach before any validation
Summary
The driver offers VIRTIO_BLK_F_MQ; a device reporting num_queues=0 drives vtblk_nqs to 0 and the vqmap loop executes i % vtblk_nqs on its first iteration - integer divide exception, boot-time panic when the boot disk presents this config (DF-1603/1604 family). QEMU rejects num-queues=0 at device_add so not constructible on this rig; trace dead-certain. Validate-num_queues fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4425 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.1 KB | β raw | |
| VERDICT.md | β | 1.8 KB | β raw | |
| fix.diff | β | 453 B | view raw | |
| manifest.json | β | 573 B | view raw | |
| verdict.json | β | 1.8 KB | view raw |
DF-4425 β VIRTIO_BLK_F_MQ with num_queues=0: modulo-by-zero panic in vtblk_attach
virtio_blk.c:289-298: sc->vtblk_nqs = min(blkcfg.num_queues, ncpus); / 0 if device says 0 / ... sc->vtblk_nqs = min(sc->vtblk_nqs, sc->vtblk_nintrs); virtio_blk.c:323-326: for (i = 0; i < ncpus; i++) sc->vtblk_vqmap[i] = i % sc->vtblk_nqs; / idiv #DE -> panic /
A device that negotiates VIRTIO_BLK_F_MQ (offered by VTBLK_FEATURES) and reports num_queues = 0 (u32 config field) drives nqs to 0; the first loop iteration executes 0 % 0 -> integer divide exception -> kernel panic during attach (boot-time panic when the boot disk does this).
Live verification attempt: QEMU 7.2.22 monitor device_add virtio-blk-pci,drive=hd2,id=vtq0,num-queues=0 -> "Error: num-queues property must be larger than 0" so mainstream QEMU cannot construct the malicious device; the code path remains trivially reachable by any other VMM or a crafted/emulated device. Same malicious-device family as DF-1603/DF-1604; distinct site (MQ path).
Fix: validate blkcfg.num_queues >= 1 when MQ is negotiated (return EINVAL), or clamp nqs = max(1, ...).
DF-4425 β VIRTIO_BLK_F_MQ with num_queues=0: modulo-by-zero panic in vtblk_attach
virtio_blk.c:289-298: sc->vtblk_nqs = min(blkcfg.num_queues, ncpus); / 0 if device says 0 / ... sc->vtblk_nqs = min(sc->vtblk_nqs, sc->vtblk_nintrs); virtio_blk.c:323-326: for (i = 0; i < ncpus; i++) sc->vtblk_vqmap[i] = i % sc->vtblk_nqs; / idiv #DE -> panic /
A device that negotiates VIRTIO_BLK_F_MQ (offered by VTBLK_FEATURES) and reports num_queues = 0 (u32 config field) drives nqs to 0; the first loop iteration executes 0 % 0 -> integer divide exception -> kernel panic during attach (boot-time panic when the boot disk does this).
Live verification attempt: QEMU 7.2.22 monitor device_add virtio-blk-pci,drive=hd2,id=vtq0,num-queues=0 -> "Error: num-queues property must be larger than 0" so mainstream QEMU cannot construct the malicious device; the code path remains trivially reachable by any other VMM or a crafted/emulated device. Same malicious-device family as DF-1603/DF-1604; distinct site (MQ path).
Fix: validate blkcfg.num_queues >= 1 when MQ is negotiated (return EINVAL), or clamp nqs = max(1, ...).
verdict: not_reproduced β tooling cannot construct the device (QEMU validates
num-queues > 0 at device creation; monitor probe output above). Code path is
certain: :292 min(0, ncpus)=0, :325 i % 0 executes before any later guard
(nintrs also becomes 0 but the vqmap loop runs first). Severity Low
(device-controlled boot/attach panic only, no memory-safety impact).
Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
Fix verification
not_testablenot_testable: baseline untriggerable on this rig (QEMU validates num-queues > 0)
Confirmed kernel references
Detail
Evidence (decisive lines)
README.md (trace + live QEMU rejection output); virtio_blk.c:289-298, :323-326.
PoC changes
n/a
Verified recommended fix
if (virtio_with_feature(dev, VIRTIO_BLK_F_MQ) && blkcfg.num_queues < 1) return EINVAL; before the vqmap loop
Verdict
not_reproduced: QEMU 7.2.22 refuses to construct the device (monitor probe: 'num-queues property must be larger than 0'), so the trigger cannot be built with available tooling. The code path itself is certain: with VIRTIO_BLK_F_MQ negotiated (offered by VTBLK_FEATURES) and blkcfg.num_queues=0, virtio_blk.c:292 sets vtblk_nqs = min(0, ncpus) = 0 and :298 min(nqs, nintrs)=0; the vqmap loop at :323-326 then executes i % sc->vtblk_nqs = 0 % 0 on its first iteration -> integer divide exception -> kernel panic in vtblk_attach (boot-time panic when the boot disk presents this config). Device-controlled DoS, no memory-safety impact.
No comments yet.