⬢ DragonFlyBSD Kernel Audit
DF-3278 / verdict.json
← back to finding ↓ download raw
{
 "finding_id": "DF-3278",
 "status": "not_reproduced",
 "reproduced": 0,
 "impact": "none",
 "confidence": "likely",
 "verdict": "Code-certain double-free/UAF not fired within the guest budget. bridge_fragment() (if_bridge.c:4386-4405) frees a fragment via M_PREPEND failure semantics (macro frees the chain on M_NOWAIT alloc failure, sys/sys/mbuf.h:463-479 / uipc_mbuf.c:1508-1511), then the else m_freem(m) branch re-frees fragment #1 on every subsequent iteration while the loop increment reads m0->m_nextpkt of freed memory. The vulnerable function was driven live at scale -- 500,050 datagrams fragmented through it with ipfw pfil hooks active (verified via netstat -s and ipfw counters; MTU-600 members) -- and the mbuf cluster pool was driven to exhaustion (Warning: objcache(mbuf cluster) exhausted on cpu1..cpu5 via 8 never-read 2MB-SO_RCVBUF loopback drainers), but the precise allocation-failure instant inside the re-header loop never coincided with a zero-leading-space fragment. Both heavy attempts ended in mbuf-starvation wedge (drainer-induced DoS), not the target crash. Deterministic forcing of a per-cpu objcache failure at one allocation site is not achievable from userland; a kernel-internal fault injector would be needed.",
 "exploit_chain": "",
 "evidence": [
  "run.log: 500050 output datagrams fragmented with ipfw active; objcache-exhaustion warnings from the drainer runs",
  "VERDICT.md: line-by-line path proof with the three defect sites (A: macro-freed fragment, B: repeated m_freem(m), C: UAF loop increment)",
  "frag_flood.c: final injector with byte-wise big-endian checksum (earlier LE-word and strict-aliasing checksum bugs silently zeroed fragmentation; root-caused via netstat badsum counters)"
 ],
 "kernel_refs": [
  "sys/net/bridge/if_bridge.c:4386",
  "sys/net/bridge/if_bridge.c:4404",
  "sys/net/bridge/if_bridge.c:4115",
  "sys/sys/mbuf.h:469",
  "sys/kern/uipc_mbuf.c:1508"
 ],
 "poc_changes": "Written from scratch. ipfw must be loaded via a background shell that immediately installs allow-rules (kldload ipfw defaults to deny and cuts ssh); member MTUs must match the bridge MTU (both taps at 600); the IP checksum must be computed byte-wise big-endian -- two silent failure modes (LE-word summation; -O strict-aliasing reorder against struct ip*) were found and fixed via netstat -s badsum counters and tcpdump.",
 "attempts": 2,
 "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": 900,
 "guest_dirty": 0,
 "build_cmd": "cc -O -Wall -o frag_flood frag_flood.c",
 "run_cmd": "sh run.sh; ./frag_flood 3000000 drain",
 "code_hash": "582098f4879ecdb18d2321d446a5e4f87b3bf3486eae7ef20cc2606bac96687d",
 "notes": "not_reproduced (window not hit), explicitly NOT false_positive: the defect logic is proven from source and M_PREPENDs free-on-failure semantics are documented in-tree. Fix is trivial (free the remainder correctly once), recommended regardless.",
 "recommended_fix": "on M_PREPEND failure set error and free the remaining chain via m_freem(m0->m_nextpkt-traversing loop) exactly once, or pre-allocate headers before fragmenting",
 "fix_status": "not_testable",
 "fix_kernel_uname": "",
 "fix_baseline_reproduced": 0,
 "fix_patched_reproduced": 0,
 "fix_verdict": "No fix build: the defect could not be reproduced at will, so baseline/patched comparison is impossible on this guest.",
 "fix_evidence": "findings/poc/DF-3278/VERDICT.md"
}