⬢ DragonFlyBSD Kernel Audit
DF-4672 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4672",
  "status": "reproduced",
  "reproduced": true,
  "impact": "dos",
  "confidence": "certain",
  "verdict": "REPRODUCED. Unprivileged (uid 1001) METEORSETGEO grows through the production, unmodified video_ioctl of the stock bktr.ko (driven via the DF-1215-style KLD rig /dev/bktrig0 on the hardware-less guest) permanently leaked 52,137 wired pages (203.7 MiB) in one run and 107,297 pages (419.1 MiB) on a fresh guest, with the two DragonFly leak phases visible: silent 256 MiB low-phys DMA-reserve alist drain (wire flat), then PQ-scan allocations wired per grow and never returned (wire climbs, never drops, survives kldunload), ending in get_bktr_mem/contigmalloc exhaustion (ENOMEM). Bare kmem_free of the contigmallocd object-less region returns neither the wired pages nor the reserve block nor removes the kernel PTEs -- exactly the misuse sys/vm/vm_kern.c:311-313 warns about.",
  "exploit_chain": "open(/dev/bktr0 O_RDONLY) [0444, unpriv] -> ioctl(METEORSETGEO, strictly larger geometry) xN [no priv_check in driver] -> every grow get_bktr_mem()s a new buffer and bare-kmem_free()s the old one -> reserve blocks + wired pages permanently lost -> repeat until the 256 MiB DMA reserve and/or all reclaimable memory is wired -> system-wide allocation exhaustion DoS (verified ENOMEM from get_bktr_mem after 266 MiB of unpriv growth).",
  "evidence": "run.log: wire delta (permanent): 52137 pages (203.7 MiB) + flat->climb transition lines (WIRE CLIMB PHASE BEGINS, +28234); re-confirm on fresh guest in VERDICT.md; fix_run.log on DF467XFIX kernel: same attack, 85.3 MiB allocated, wire delta 22 pages == noise (leak gone).",
  "kernel_refs": [
    "sys/dev/video/bktr/bktr_core.c:1667",
    "sys/dev/video/bktr/bktr_core.c:1669",
    "sys/dev/video/bktr/bktr_os.c:399",
    "sys/dev/video/bktr/bktr_os.c:403",
    "sys/vm/vm_contig.c:447",
    "sys/vm/vm_contig.c:527",
    "sys/vm/vm_contig.c:588",
    "sys/vm/vm_kern.c:311",
    "sys/vm/vm_map.c:3300",
    "sys/vm/vm_page.c:2765",
    "sys/vm/vm_page.c:2858",
    "sys/vm/vm_page.c:426"
  ],
  "poc_changes": "Seed bktr_wireleak.c expected an immediate wire climb and hard-coded /dev/bktr0; rewritten as phase-aware rig PoC: /dev/bktrig0, kernel-verified strictly-larger grows, per-grow wire deltas, two-phase detection (reserve drain then PQ wire climb), exact leak prediction. Discovered en route: DragonFly contigmalloc serves from a 256 MiB low-phys DMA reserve first (vm_page.c:2765), so the seeds one-phase model was wrong on this kernel.",
  "attempts": 3,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 (baseline) / #0: Thu Oct 15 00:54:24 UTC 2026 DF467XFIX (fix)",
  "runtime_sec": 4980,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -Wall -o poc_wireleak poc_wireleak.c ; make -m /usr/src/share/mk SYSDIR=/usr/src/sys (KLD rig)",
  "run_cmd": "./run.sh  (root: rig load + RIG_INIT mirror; maxx: ./poc_wireleak 128 80)",
  "code_hash": "539bd1717e52582ec228c72039498d81e3d9c047a06d2be865eb395a0171c590",
  "notes": "Hardware-gated on real /dev/bktr0 (needs a bt848 card OR the module-loadable path with vfs.devfs rules); the production code path executed is byte-identical to hardware (production video_ioctl + get_bktr_mem/contigmalloc/kmem_free), only the initial buffer install is the rigs attach mirror (production get_bktr_mem + bzero per bktr_core.c:429-432). Residual kernel-map resident_count mistabulation from the missing pmap removal also source-proven (vm_map.c:3300-3370).",
  "recommended_fix": "Release the grow-path buffer with contigfree() (not bare kmem_free), install the new buffer before freeing the old one, and bzero the new buffer (see fix.diff).",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fixed",
  "fix_evidence": "fix_run.log: DF467XFIX kernel (bktr built in, fix applied, KERN_RC=0/INST_RC=0, booted #0 Oct 15 00:54:24 UTC 2026): same unpriv grow storm, 85.3 MiB of frame buffers allocated, permanent wire delta 22 pages (== idle noise of 288) vs +52,137 pages baseline; reserve no longer drains (grow KVA reuse safe)."
}