⬢ DragonFlyBSD Kernel Audit
DF-4223 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4223",
  "status": "inconclusive",
  "reproduced": 0,
  "impact": "none",
  "confidence": "certain",
  "verdict": "Source-certain attach-error-path asymmetry in pvscsi: (a) after a partial pvscsi_dma_alloc_per_hcb failure, the fail path destroys the per-hcb bus_dmamaps (pvscsi.c:615-618 -> 549-552) and pvscsi_attachs error cleanup destroys them AGAIN via pvscsi_free_all (pvscsi.c:1586) \u2014 DragonFly bus_dmamap_destroy (busdma_machdep.c:439-449) kfree()s without idempotence, so this is a double free into M_DEVBUF (heap corruption); (b) when the hcb-array kmalloc fails, pvscsi_free_all still walks pvscsi_dma_free_per_hcb(sc, sc->hcb_cnt) with sc->hcbs == NULL and hcb_cnt set before the failure (pvscsi.c:1718-1724, 541-544), calling callout_drain on NULL+i*sizeof(hcb) => panic during OOM recovery. Attach-time, OOM/resource-exhaustion-gated; driver ships in GENERIC. Not triggerable on the audit guest (no pvscsi device), so impact recorded none; realistic ceiling is boot-time DoS/heap corruption on VMware systems under memory pressure.",
  "exploit_chain": "",
  "evidence": "VERDICT.md call graphs: double destroy pvscsi.c:615-618 + pvscsi.c:1586 vs busdma_machdep.c:442-446 (kfree, NULL-tolerant but not double-tolerant); NULL-array walk pvscsi.c:1718-1724 -> 1586 -> 541-544. patch_apply.log + build.log: fix.diff (sc->hcbs_setup bookkeeping) applies and compiles on pristine guest source.",
  "kernel_refs": [
    "sys/dev/virtual/vmware/pvscsi/pvscsi.c:558-621",
    "sys/dev/virtual/vmware/pvscsi/pvscsi.c:615-618",
    "sys/dev/virtual/vmware/pvscsi/pvscsi.c:1566-1608",
    "sys/dev/virtual/vmware/pvscsi/pvscsi.c:1586",
    "sys/dev/virtual/vmware/pvscsi/pvscsi.c:1718-1724",
    "sys/dev/virtual/vmware/pvscsi/pvscsi.c:529-556",
    "sys/platform/pc64/x86_64/busdma_machdep.c:439-449",
    "sys/kern/kern_timeout.c:1047"
  ],
  "poc_changes": "no PoC source \u2014 device-gated, OOM-gated; evidence is the source trace plus on-guest fix build validation",
  "attempts": 1,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 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": 30,
  "guest_dirty": 0,
  "build_cmd": "cd /usr/src/sys && patch -p2 < fix.diff && cd /usr/src/sys/dev/virtual/vmware/pvscsi && make",
  "run_cmd": "(none \u2014 HW/vmm-gated; see run.sh)",
  "code_hash": "b655a409b09212864e7c692f7b4ba1dd55b867af9065a1597fb9ffa26362aeaf",
  "notes": "code_hash is sha256 of fix.diff. Guest kernel source restored to pristine after validation. Also noted (not fixed here): teardown ordering in pvscsi_detach frees rings before bus_teardown_intr \u2014 intr is disabled + adapter reset first, residual window negligible; and callout_stop in process_completion cannot interlock an in-flight callback (kern_timeout.c:1052-1054), but pvscsi_timeouts ccb==NULL guard bounds that to a spurious abort, not memory unsafety.",
  "recommended_fix": "Track hcbs whose per-hcb DMA resources exist (sc->hcbs_setup): set it only on full success, zero it after the partial free, and make pvscsi_free_all use it instead of hcb_cnt so freed maps are never destroyed twice and a NULL hcb array is never walked",
  "fix_status": "inconclusive",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff (sc->hcbs_setup bookkeeping) applies cleanly to the pristine guest kernel source (patch_apply.log) and the pvscsi module compiles (build.log). Runtime validation HW-gated on this guest.",
  "fix_evidence": "patch_apply.log (clean apply), build.log (module rebuild OK)"
}