β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-4425

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4425 Β· 5 files
FileTypeDescriptionSize
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, ...).

VERDICT.md
↓ download 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, ...).


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_testable
baseline no→ patch + rebuild →patched clean

not_testable: baseline untriggerable on this rig (QEMU validates num-queues > 0)

↓ fix.diffper-fix-DF-4425

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.