DF-5120 / verdict.json
{ "finding_id": "DF-5120", "status": "untested", "verdict": "Mechanism code-certain: vtrnd_harvest() calls virtqueue_poll() (virtio_random.c:215), which is an unbounded busy-wait (virtqueue.c:578-579), from the periodic 5s softclock callout (virtio_random.c:142,229). If the host entropy backend never advances the used ring (stalling EGD chardev, wedged vhost backend, out-of-band device reset), the softclock thread spins forever - permanent guest hang, no panic, no watchdog. Not reproduced: the audit guest has no virtio-rng device (vm.sh attaches only virtio-blk/virtio-net) and the trigger is host-side fault injection, outside the guest-attacker model; filed as Low hardening/robustness.", "reproduced": false, "impact": "none", "confidence": "likely", "exploit_chain": "", "evidence": "README.md (mechanism + trigger model); VERDICT.md (source trace virtio_random.c:142,205-215,229 and virtqueue.c:572-580; negative results incl. callout_terminate sync semantics kern_timeout.c:1041-1075 killing the detach-UAF hypothesis); fix.diff (bounded ~10ms wait, degrades to no-harvest via the existing virtqueue_empty() gate); guest dmesg shows no vtrnd (only vtnet0/vtblk0)", "kernel_refs": [ "sys/dev/virtual/virtio/random/virtio_random.c:215", "sys/dev/virtual/virtio/random/virtio_random.c:142", "sys/dev/virtual/virtio/random/virtio_random.c:229", "sys/dev/virtual/virtio/virtio/virtqueue.c:578" ], "poc_changes": "No runnable PoC authored: trigger is host-side (stalled entropy backend), not guest-local; the audit guest lacks a virtio-rng device entirely.", "attempts": 0, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 0, "guest_dirty": 0, "build_cmd": "", "run_cmd": "", "code_hash": "", "notes": "Guest untouched (read-only probes). Virtio threat model treats the host as trusted - not guest-attacker-reachable; severity Low. Related negative results in VERDICT.md cover the OOB/size hunt item (sglist 1x4 bytes bounded, used-ring length ignored via NULL len), attach unwind, callout/detach UAF (killed by synchronous callout_terminate), entropy source indexing (all masked to 256-entry arrays), and module state. Side observation for a future kern_nrandom.c audit: add_buffer_randomness_src() mis-splits buffers >256 bytes (passes full remaining length while advancing by 256), unreachable from vtrnd (always 4 bytes).", "recommended_fix": "Bound the poll in vtrnd_harvest() (~10ms via virtqueue_pending()+DELAY loop); on timeout return with the descriptor still queued so the existing virtqueue_empty() gate permanently disables harvest instead of hanging softclock", "fix_status": "not_testable", "fix_baseline_reproduced": false, "fix_patched_reproduced": false, "fix_verdict": "Fix kernel not built/run: the finding is unverified Low severity, the guest has no virtio-rng device, and the fault under test is host-side; the diff is minimal and confined to virtio_random.c (uses DELAY already declared in sys/systm.h).", "fix_evidence": "fix.diff" } |