⬢ DragonFlyBSD Kernel Audit
DF-5254 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5254",
  "status": "inconclusive",
  "reproduced": false,
  "impact": "none",
  "confidence": "likely",
  "verdict": "Use-after-free WRITE on struct urtwn_vap.bcn_mbuf: urtwn_update_beacon() releases sc_mtx around ieee80211_beacon_update() (if_urtwn.c:2206-2212, writer holds only the net80211 com lock via iv_update_beacon callers such as ieee80211_set_tim) while urtwn_setup_beacon() frees-and-swaps the same mbuf under sc_mtx with the com lock dropped (urtwn_newstate if_urtwn.c:2551-2552, setup at 2168-2171; IBSS S_RUN re-entry is remotely triggerable via ieee80211_ibss_merge->ieee80211_sta_join1), and urtwn_vap_delete() frees it with no lock at all (840-841). No lock orders writer against freer. On-guest kernel PoC is hardware-gated (no RTL8188 USB NIC on the QEMU guest; if_urtwn.ko present but unloadable without a device), so kernel-level reproduction is honestly recorded as inconclusive; a faithful three-thread two-lock-domain simulation of the exact interleaving reproduced the write-after-free in 6/6 runs on the guest as an unprivileged user, including the vap_delete variant (run.2.log). Severity High (memcorrupt), twin of the if_run.c pass-2 beacon-lifecycle family.",
  "exploit_chain": "unauthenticated remote peer (IBSS) or local admin-triggered state churn -> (1) attacker sends crafted beacons with larger TSF to force ieee80211_ibss_merge -> newstate(S_RUN) re-entry -> urtwn_setup_beacon m_freem(bcn_mbuf) under sc_mtx; concurrently (2) station power-save traffic drives ieee80211_set_tim -> urtwn_update_beacon -> ieee80211_beacon_update writes TIM/CSA bytes into the freed 2KB mbuf cluster -> cross-object heap corruption (cluster pool recycles immediately) -> crash today, controlled-content write into recycled kernel object with pool grooming. Simulated chain proven at interleaving level (exit=3, 6/6); hardware chain not exercised.",
  "evidence": "race_sim.c + run.log (5/5 runs exit=3 UAF write detected, gens 220/184/186/404/403), run.2.log (vap_delete variant, C frees=1), VERDICT.md source trace with path:line for all three racing paths, fix.diff (git apply --check clean)",
  "kernel_refs": [
    "sys/bus/u4b/wlan/if_urtwn.c:2206",
    "sys/bus/u4b/wlan/if_urtwn.c:2212",
    "sys/bus/u4b/wlan/if_urtwn.c:2168",
    "sys/bus/u4b/wlan/if_urtwn.c:2171",
    "sys/bus/u4b/wlan/if_urtwn.c:2551",
    "sys/bus/u4b/wlan/if_urtwn.c:840",
    "sys/netproto/802_11/wlan/ieee80211_power.c:316",
    "sys/netproto/802_11/wlan/ieee80211_node.c:630"
  ],
  "poc_changes": "No kernel PoC possible (hardware-gated); built race_sim.c from scratch: pthread model of the exact lock choreography (com held across update path, sc dropped at 2206, com dropped at 2551, no-lock vap_delete), zone-allocator emulation with generation counters so a stale-generation write is a true write-after-free. Iterations: fixed aligned_alloc size-misuse crash, made vap_delete thread leave the field dangling (as the kernel does) instead of NULLing it.",
  "attempts": 4,
  "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": 95,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -pthread -Wall -o race_sim race_sim.c",
  "run_cmd": "./race_sim 5   (x5 runs, exit code 3 == UAF write detected)",
  "code_hash": "37a2eb97099454f50001c3b36f6cb3611f259b8021e76d627552980257d8f5a3",
  "notes": "Hardware-gated: guest has if_urtwn.ko in /boot/kernel but no RTL8188/8192 USB device (kldstat empty for urtwn, usbdevs empty). Requires a urtwn-supported NIC in hostap or ibss mode on real hardware to fire in-kernel; in IBSS the racing S_RUN re-entry is drivable by an unauthenticated peer. Simulated evidence per protocol for hardware-gated findings.",
  "recommended_fix": "Hold URTWN_LOCK(sc) across ieee80211_beacon_update() in urtwn_update_beacon() and take URTWN_LOCK(sc) around m_freem(uvp->bcn_mbuf) in urtwn_vap_delete() (see fix.diff)",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff is git-apply-able against sys/ and removes the unlocked window by construction (B/C serialize on sc_mtx with the writer); kernel build+device test not possible on this guest (no USB WLAN hardware) so not_testable",
  "fix_evidence": "findings/poc/DF-5254/fix.diff (git apply --check PASSED); locking argument in VERDICT.md"
}