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

wlan_xauth: nrefs is never incremented (NULL ia_attach) so kldunload succeeds while VAPs hold raw iv_auth pointers β€” use-after-free of module text/data on later auth dispatch

Summary

The module unload guard for 802.11 policy modules keys solely on the static nrefs counter (EBUSY when nrefs != 0). Sibling policy modules bump nrefs in their attach callbacks; wlan_xauth declares nrefs but its ia_attach/ia_detach are NULL, so nrefs stays 0 forever and kldunload wlan_xauth is always permitted. Meanwhile VAPs using 802.1x/WPA-external auth hold a raw, uncounted pointer into the module's static const struct (vap->iv_auth). After unload, any subsequent auth dispatch dereferences freed module memory: node join/leave (reachable from over-the-air association events), mode change/teardown. The NULL-guards themselves become UAF reads on freed pages, and if the guard reads stale non-NULL garbage the subsequent indirect call jumps into freed module memory. Arming requires root twice (kldunload while a root-configured 802.1x VAP is up), but once armed the dangling dereference is triggerable by an unauthenticated remote peer via association/disassociation frames on any 802.11 hardware. Realistic ceiling kernel panic (UAF read / call into freed module pages). Not reachable on the audit guest (no radio); not runtime-verified. Fix: real attach/detach callbacks maintaining nrefs (net80211 only invokes ia_attach when non-NULL so nothing increments it today). [VERIFIED pass2: hardware-gated no radio; guard-inertness demonstrated nrefs never incremented; UAF arming code-certain on HW]

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3473 Β· 7 files
FileTypeDescriptionSize
README.md β€” 461 B ↓ raw
VERDICT.md β€” 1.6 KB ↓ raw
env.txt β€” 309 B view raw
fix.diff β€” 498 B view raw
manifest.json β€” 709 B view raw
run.log β€” 224 B view raw
verdict.json β€” 1.7 KB view raw

DF-3473 - wlan_xauth nrefs never incremented

kldload wlan_xauth; kldunload wlan_xauth -> succeeds immediately with zero VAPs (guard inert; nrefs can never be incremented because ia_attach is NULL). Full UAF arming requires 802.11 hardware (802.1x VAP holding iv_auth) - not present on this guest -> inconclusive / hardware-gated.

Kernel: DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64

VERDICT.md
↓ download raw

DF-3473 - VERDICT

status: inconclusive | reproduced: 0 | impact: none | confidence: certain

Not testable to full effect on this guest (no 802.11 radio, so no 802.1x VAP can exist to hold iv_auth), but the guard-inertness half IS demonstrated: wlan_xauth.ko loads on the stock guest and kldunload wlan_xauth succeeds immediately and unconditionally - nrefs is provably never incremented because ieee80211_xauth.c:66-71 declares ia_attach/ia_detach NULL (net80211 only bumps nrefs inside ia_attach). Therefore any kldunload is permitted regardless of how many VAPs hold raw pointers into the module text (vap->iv_auth) - the unload-while-armed UAF is code-certain on hardware but cannot be armed on this rig. Arming needs root twice (802.1x VAP up + kldunload); the dangling dereference is then triggerable by an unauthenticated peer via association events. Ceiling: kernel panic (UAF read / call into freed module pages).

Kernel references

Evidence

run.log (kldload/kldunload transcript), source excerpt ieee80211_xauth.c:62-78

implement ia_attach/ia_detach that maintain nrefs (and refuse unload while referenced).

Fix status (batch validation)

Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

Fix verification

not_testable
↓ fix.diffper-fix-DF-3473

Confirmed kernel references

Detail

Evidence (decisive lines)

run.log (kldload/kldunload transcript), source excerpt ieee80211_xauth.c:62-78

PoC changes

none (unload-guard demo only)

Verified recommended fix

implement ia_attach/ia_detach that maintain nrefs (and refuse unload while referenced).

Verdict

Not testable to full effect on this guest (no 802.11 radio, so no 802.1x VAP can exist to hold iv_auth), but the guard-inertness half IS demonstrated: wlan_xauth.ko loads on the stock guest and kldunload wlan_xauth succeeds immediately and unconditionally - nrefs is provably never incremented because ieee80211_xauth.c:66-71 declares ia_attach/ia_detach NULL (net80211 only bumps nrefs inside ia_attach). Therefore any kldunload is permitted regardless of how many VAPs hold raw pointers into the module text (vap->iv_auth) - the unload-while-armed UAF is code-certain on hardware but cannot be armed on this rig. Arming needs root twice (802.1x VAP up + kldunload); the dangling dereference is then triggerable by an unauthenticated peer via association events. Ceiling: kernel panic (UAF read / call into freed module pages).