DF-3470 / analysis.txt
# DF-3470 — code-level evidence (guest + tree)
## Guard exists but is never armed: `nrefs` occurrence counts
$ grep -rn "nrefs" sys/netproto/802_11/ | grep -v "^Binary"
sys/netproto/802_11/wlan_wep/ieee80211_crypto_wep.c:86:static int nrefs = 0;
sys/netproto/802_11/wlan_wep/ieee80211_crypto_wep.c:108: nrefs++; /* NB: we assume caller locking */
sys/netproto/802_11/wlan_wep/ieee80211_crypto_wep.c:118: KASSERT(nrefs > 0, ("imbalanced attach/detach"));
sys/netproto/802_11/wlan_wep/ieee80211_crypto_wep.c:119: nrefs--; /* NB: we assume caller locking */
sys/netproto/802_11/wlan/ieee80211_ratectl_none.c:96:static int nrefs = 0; <-- never used again
sys/netproto/802_11/wlan/ieee80211_rssadapt.c:97:static int nrefs = 0; <-- never used again
sys/netproto/802_11/wlan/ieee80211_scan_sta.c:150:static int nrefs = 0;
sys/netproto/802_11/wlan/ieee80211_scan_sta.c:178: nrefs++; /* NB: we assume caller locking */
sys/netproto/802_11/wlan/ieee80211_scan_sta.c:195: KASSERT(nrefs > 0, ("imbalanced attach/detach"));
sys/netproto/802_11/wlan/ieee80211_scan_sta.c:196: nrefs--; /* NB: we assume caller locking */
sys/netproto/802_11/wlan_tkip/ieee80211_crypto_tkip.c:107:static int nrefs = 0; (+108/137/138 ++/--)
sys/netproto/802_11/wlan/ieee80211_amrr.c:77:static int nrefs = 0; <-- never used again (default algorithm!)
## The unload guard that is bypassed (sys/netproto/802_11/ieee80211_dragonfly.h)
#define _IEEE80211_POLICY_MODULE(policy, name, version) \
...
case MOD_UNLOAD: \
error = 0; \
if (nrefs) { \
kprintf("wlan_" #name ": still in use (%u " \
"dynamic refs)\n", \
nrefs); \
error = EBUSY; \
} else if (type == MOD_UNLOAD) { \
SET_FOREACH(iter, policy##_set) { \
f = (void*) *iter; \
f(type); \
} \
} \
...
IEE80211_RATECTL_ALG(name, alg, v) -> MOD_UNLOAD -> ieee80211_ratectl_unregister(alg)
(ratectl.c:66-71: ratectls[type] = NULL, no user check)
## The dangling consumer chain
ratectl.c:152 vap->iv_rate = ratectls[type]; /* pointer INTO the module */
ratectl.c:123 vap->iv_rate->ir_init(vap);
ratectl.h:88 vap->iv_rate->ir_rate(ni, arg, iarg); /* every TX */
ratectl.c:83 ieee80211_ratectl_node_stats(ni, sb) ->
ratectl.h:121 vap->iv_rate->ir_node_stats(ni, s) /* world-readable rate_stats sysctl
(ratectl.c:127-129, CTLFLAG_RD) */
ratectl.h:70 vap->iv_rate->ir_deinit(vap); /* vap teardown */
## Guest facts (stock INVARIANTS kernel #0)
$ kldstat -v | grep -wE "wlan_amrr|wlan_rssadapt"
180 wlan_amrr <- compiled INTO the kernel image
$ kldunload wlan_amrr
kldunload: can't find file wlan_amrr: No such file or directory
$ grep -c nrefs /usr/src/sys/netproto/802_11/wlan/ieee80211_amrr.c
1
=> On this guest the unload cannot be attempted at all (algorithm built-in),
and no 802.11 hardware exists to attach a vap. Runtime reproduction of the
dangling iv_rate call is therefore impossible here; the defect is proven
from source (missing nrefs increment in amrr/rssadapt/none + no registry
backstop).