⬢ DragonFlyBSD Kernel Audit
DF-4424 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4424",
  "status": "not_reproduced",
  "reproduced": 0,
  "impact": "none",
  "confidence": "likely",
  "verdict": "not_reproduced: triggering requires a virtio-blk device advertising SEG_MAX in [3,34]; QEMU 7.2.22 (this rig) provides no way to set seg_max, and the guests real vtblk0 advertises a large value, so the precondition cannot be constructed. The code path is traced line-by-line and is deterministic once the precondition holds: vtblk_maximum_segments (virtio_blk.c:582-586) accepts small seg_max, the :282 check only rejects <=2, si_iosize_max stays MAXPHYS (:753), a MAXPHYS bio needs up to 35 segments (header+33 pages+ack), sglist_append returns EFBIG (subr_sglist.c splits per page), and the failures are only KASSERTed (virtio_blk.c:864/870/878). On INVARIANTS kernels (stock X86_64_GENERIC, verified present on the audit guest) this panics on first large I/O; on production kernels (KASSERT no-op, systm.h:117) a truncated/mislabeled descriptor chain is enqueued (no ack descriptor -> vbr_ack stays 0xFF -> spurious EIO; write path marks the last data page as status target -> 1-byte clobber). Device-controlled DoS/data-integrity break, same malicious-device family as DF-1603/1604.",
  "exploit_chain": "",
  "evidence": "VERDICT.md trace; sys/kern/subr_sglist.c _sglist_append_buf (per-page split, EFBIG at capacity); sys/sys/systm.h:95 vs :117 (KASSERT compiled out without INVARIANTS); guest /usr/src/sys/config/X86_64_GENERIC contains options INVARIANTS.",
  "kernel_refs": [
    "sys/dev/virtual/virtio/block/virtio_blk.c:582",
    "sys/dev/virtual/virtio/block/virtio_blk.c:282",
    "sys/dev/virtual/virtio/block/virtio_blk.c:753",
    "sys/dev/virtual/virtio/block/virtio_blk.c:862",
    "sys/dev/virtual/virtio/block/virtio_blk.c:864",
    "sys/dev/virtual/virtio/block/virtio_blk.c:870",
    "sys/dev/virtual/virtio/block/virtio_blk.c:878"
  ],
  "poc_changes": "n/a (no runnable PoC possible: QEMU offers no seg_max control; documented monitor probe)",
  "attempts": 2,
  "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": 600,
  "guest_dirty": 0,
  "build_cmd": "n/a",
  "run_cmd": "n/a (requires host-controlled virtio device config)",
  "code_hash": "",
  "notes": "Fix is one line: clamp si_iosize_max to (max_nsegs-2)*PAGE_SIZE or reject small seg_max at attach.",
  "recommended_fix": "si_iosize_max = min(MAXPHYS, (sc->vtblk_max_nsegs - VTBLK_MIN_SEGMENTS) * PAGE_SIZE) in vtblk_alloc_disk, or EINVAL at attach when negotiated seg_max cannot cover a MAXPHYS transfer",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "not_testable: baseline itself untriggerable on this rig (no seg_max control in QEMU 7.2.22)",
  "fix_evidence": ""
}