DF-4223 / verdict.json
{ "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)" } |