⬢ DragonFlyBSD Kernel Audit
DF-3365 / run.log
← back to finding ↓ download raw
DF-3365 race attempt -- instrumented kernel #1 (stock logic), INVARIANTS on,
debug.use_weird_array=1 (kfree overwrites freed chunks with 0xdeadc0de).

Thread 1 (wlan serializer held -- the exact locking discipline of the
driver rx path): injects beacons for MAC 02:44:44:44:44:44 with rssi=1
(match_bss always fails MATCH_RSSI, GOTPICK never sets) while
ss_flags |= IEEE80211_SCAN_PICK1ST, so EVERY sta_add() executes the
match_bss() tail at ieee80211_scan_sta.c:403 AFTER TABLE_UNLOCK at :397.

Thread 2 (NO wlan serializer -- the exact locking discipline of the
node-timeout callout that drives ieee80211_scan_timeout -> scan_age ->
adhoc_age entry frees; sta_flush uses the same table-lock-only
discipline): loops ss_ops->scan_flush() freeing the entry thread 1 may
be match_bss()ing.

Run 1 (60s): fwscan: race finished: 150000 injections survived
             (no panic => window not hit or hit silently)
Run 2 (120s, use_weird_array=1): fwscan: race finished: 21800
             injections survived; guest up, load averages normal.

VERDICT: not reproduced at runtime. The window is real (code-trace +
lock analysis: rx path holds only wlan_global_serializer, the free
paths run from the taskqueue/callout contexts under ic_comlock/table
lock, so nothing serializes the two), but it is a few hundred
nanoseconds wide inside a multi-microsecond path, and even on a hit
the reads land in mapped, stale-or-junked slab memory: no fault, no
observable corruption. Impact ceiling: silent use of stale entry data
(phantom AP selection / copying a freed IE blob into a node), or a
crash if a freed-and-reallocated entry yields an invalid se_chan
pointer. Recorded as a genuine but non-demonstrated UAF-read race.