⬢ DragonFlyBSD Kernel Audit
DF-5162 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5162",
  "status": "not_reproduced",
  "reproduced": false,
  "impact": "none",
  "confidence": "certain",
  "verdict": "Source-proven use-after-free of the bktr_mem stored-address registry: the unprivileged METEORSETGEO grow path (bktr_core.c:1667-1673) frees the attach-time frame buffer without re-storing BKTR_MEM_BUF, the registry has no invalidation mechanism (bktr_mem.c:103-138 only ever sets addresses_stored=1), and the unload/reload design that detach relies on (bktr_os.c:362-364) reinstalls the freed KVA at reload (bktr_core.c:382-390) where bktr_core.c:429-432 immediately bzeros ~3.5 MB of possibly-reallocated kernel KVA and later DMAs video into it. Not reproduced on the audit guest because no Bt848/Bt878 PCI device exists there (env.txt: NO_BT8XX_PCI_DEVICE, /dev/bktr0 ENOENT in run.log); the trigger builds cleanly. Full unpriv-to-root escalation is NOT claimed: completing the chain requires a root kldunload/kldload of bktr.ko between the plant and the harvest, hence Low severity.",
  "exploit_chain": "unpriv: open /dev/bktr0 (mode 0444, bktr_os.c:325) -> METEORSETGEO rows=1024 cols=1024 frames=2 RGB16 (1026 pages > 868 default) -> grow path kmem_free()s original bigbuf, installs new buffer, registry keeps freed KVA with addresses_stored=1; root: kldunload bktr && kldload bktr -> common_bktr_attach retrieves stale KVA -> bktr_core.c:432 bzero(freed,3.5MB) + read()/mmap()/RISC-DMA target freed range -> corruption of whatever kernel objects were reallocated there. Chain needs root mid-way (driver reload), so impact is corruption-on-admin-action, not unpriv privesc.",
  "evidence": "VERDICT.md (full line-cited chain); run.log (guest: BUILD_OK then open(/dev/bktr0): ENOENT \u2014 hardware-gated); env.txt (no Brooktree PCI device, modules present); fix.diff (re-store after grow; git apply --check clean)",
  "kernel_refs": [
    "sys/dev/video/bktr/bktr_mem.c:103",
    "sys/dev/video/bktr/bktr_mem.c:115",
    "sys/dev/video/bktr/bktr_mem.c:142",
    "sys/dev/video/bktr/bktr_core.c:415",
    "sys/dev/video/bktr/bktr_core.c:382",
    "sys/dev/video/bktr/bktr_core.c:1667",
    "sys/dev/video/bktr/bktr_core.c:1669",
    "sys/dev/video/bktr/bktr_core.c:429",
    "sys/dev/video/bktr/bktr_core.c:432",
    "sys/dev/video/bktr/bktr_os.c:325",
    "sys/dev/video/bktr/bktr_os.c:362"
  ],
  "poc_changes": "no orchestrator seed existed for this ID; trigger authored fresh in this pack (ioctl numbers/struct mirrored from sys/dev/video/meteor/ioctl_meteor.h:47-52,72)",
  "attempts": 1,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026\troot@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64",
  "runtime_sec": 45,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -Wall -o grow_stale grow_stale.c",
  "run_cmd": "./run.sh  (then, on hardware, root: sh reload_stale.sh)",
  "code_hash": "ab3e3a9c7292a48ca52e6020e275cb3f67653bb0eb0032805ec22bc2e0090679",
  "notes": "Hardware-gated on the audit QEMU guest (no Bt848 card; /dev/bktr0 absent) \u2014 consistent with pass-1 context no bktr on guest. Distinct from DF-4671/4672/4673 (same grow path, different defects: mmap fault race, wired-page leak, unzeroed pages) and DF-3789 (frames=0 guard skip): none covers the bktr_mem registry staleness across module reload. Guest /tmp artifacts removed after the attempt.",
  "recommended_fix": "Re-store the live bigbuf in the METEORSETGEO grow path: bktr_store_address(unit, BKTR_MEM_BUF, bktr->bigbuf) after the if/else at bktr_core.c:1678-1681 (see fix.diff); longer term give bktr_mem an invalidate API.",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": false,
  "fix_patched_reproduced": false,
  "fix_verdict": "Fix validation not testable on this guest: the baseline itself cannot reproduce (no Bt848 hardware -> common_bktr_attach never runs), so a patched kernel cannot be differentially exercised. fix.diff is source-verified (git apply --check clean) and provable by inspection: after it, memory_list[unit].buf always equals the live bktr->bigbuf at every point the registry is consulted.",
  "fix_evidence": "fix.diff; VERDICT.md Fix section; git apply --check output APPLIES_CLEAN recorded in the audit trail"
}