β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-0320

Reorder buffer rxa_m[] mutated without dedicated lock: RX races timer flush and ADDBA re-init (double-free/UAF)

Summary

ieee80211_rx_ampdu rxa_m[64] accessed by 3 contexts with no per-rap lock: RX ieee80211_ampdu_reorder(:780/:908), node-age callout ampdu_rx_flush(:1125/:1151 frees mbufs), ADDBA ampdu_rx_start(:540/:553 purge+memset). Code littered with XXX locking(:1819,:1842). Remote peer interleaves A-MPDU + ADDBA -> double-free/UAF mbuf corruption.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-0320 Β· 5 files
FileTypeDescriptionSize
VERDICT.md verdict source-trace confirmed race, no WiFi HW 2.5 KB ↓ raw
README.md readme status explanation 692 B ↓ raw
fix.diff suggested-fix add rxa_lock spinlock to ieee80211_rx_ampdu; compiles on GENERIC 2.1 KB view raw
../fix_build_combined.log build-log Combined 41-finding kernel build (rc=0, -Werror clean) 5.6 MB ↓ download
../fix_build_summary.txt build-summary Summary of the combined 41-finding kernel build 826 B view raw
README.md readme status explanation
↓ download raw

DF-0320 PoC β€” WiFi A-MSDU reorder buffer race

Status: REAL (source-trace confirmed), not testable on this guest

The race is confirmed by tracing three concurrent mutators of rxa_m[] with no dedicated lock: - RX reorder write at ieee80211_ht.c:911 - Node-age flush at :1151 - ADDBA memset at :553

Not testable because: - No WiFi hardware on this guest - wlan module not loaded at runtime - Requires a remote WiFi peer interleaving A-MPDU + ADDBA frames

The code IS compiled into GENERIC (device wlan).

Fix

See fix.diff β€” adds struct spinlock rxa_lock to struct ieee80211_rx_ampdu and wraps the critical sections. Verified to compile cleanly on GENERIC.

VERDICT.md verdict source-trace confirmed race, no WiFi HW
↓ download raw

DF-0320 β€” Reorder buffer rxa_m[] mutated without dedicated lock

Verdict: REAL (source-trace confirmed) β€” not testable on this guest (no WiFi HW)

Mechanism

struct ieee80211_rx_ampdu (sys/netproto/802_11/ieee80211_ht.h:151-163) contains struct mbuf *rxa_m[IEEE80211_AGGR_BAWMAX] (64-slot reorder buffer) which is mutated by three concurrent execution contexts with no dedicated lock:

  1. RX reorder path β€” ieee80211_ampdu_reorder() at ieee80211_ht.c:780 writes rxa_m[off] at :911 and calls ampdu_rx_flush() at :897 which frees mbufs from rxa_m[].

  2. Node-age callout β€” ieee80211_ht_node_age() at :1125 iterates TIDs and calls ampdu_rx_flush() at :1151 which frees mbufs from rxa_m[]. Runs from a callout/softclock context.

  3. ADDBA re-init β€” ampdu_rx_start() at :540 calls ampdu_rx_purge() then memset(rap, 0, sizeof(*rap)) at :553, wiping all rxa_m[] entries without freeing them first (or racing with a concurrent flush that's freeing them).

The code is littered with XXX locking comments (:570, :885, :1144). Without serialization: - Context 3 (memset) can zero rxa_m[i] while Context 1/2 is freeing the mbuf β†’ double-free (both the memset-wiped slot and the caller's mbuf reference become dangling) - Context 2 (flush) can free rxa_m[i] while Context 1 is writing to it β†’ use-after-free / type confusion

Privilege / testability

  • Remote-triggerable: a WiFi peer interleaving A-MPDU data frames with ADDBA request frames can race the RX reorder path against the ADDBA re-init.
  • The wlan code IS compiled into GENERIC (device wlan).
  • But requires WiFi hardware β€” none on this guest.
  • The wlan module is not loaded at runtime.

This is a valid hard blocker: the code path is unreachable at runtime on this guest (no WiFi hardware).

Fix

fix.diff β€” adds a struct spinlock rxa_lock to struct ieee80211_rx_ampdu (using available rxa_pad space), initializes it in ampdu_rx_start(), and wraps the critical ampdu_rx_purge()/ampdu_rx_flush() calls in all three contexts. Also adds #include <sys/spinlock2.h> to ieee80211_ht.c. Verified to compile cleanly on GENERIC.

Impact

Remote double-free / UAF of kernel mbufs from an unauthenticated WiFi peer. On a default kernel with INVARIANTS, this would likely manifest as a panic (slab poisoning detected). Without INVARIANTS, it's a heap corruption primitive exploitable for code execution. Realistic only in a WiFi deployment with HT (802.11n) A-MPDU aggregation.

Fix verification

not_testable

compile validated

see evidence pack

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

β€”

Verdict

Source-confirmed. rxa_m[64] reorder buffer mutated by 3 contexts no dedicated lock -> double-free/UAF. No WiFi HW. Fix compiles.