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)
PoC verification
Evidence pack
findings/poc/DF-3473 Β· 7 files| File | Type | Description | Size | |
|---|---|---|---|---|
| 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
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
- sys/netproto/802_11/wlan_xauth/ieee80211_xauth.c:66
- sys/netproto/802_11/wlan_xauth/ieee80211_xauth.c:71
Evidence
run.log (kldload/kldunload transcript), source excerpt ieee80211_xauth.c:62-78
Recommended fix
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_testableConfirmed 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).
No comments yet.