RANN frame overwrites shared global ieee80211_hwmp_rannint without lock: remote timer DoS
Summary
hwmp_recv_rann(:1971) ieee80211_hwmp_rannint=rann->rann_interval from received frame, no lock (XXX: mtx lock? comment). Shared across all vaps, drives callout period(:841). Remote: RANN with rann_interval=0 -> callout tight loop CPU saturation. Data race vs sysctl handler.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-0352 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fix.diff | suggested-fix | atomic_swap_int + sanity clamp on rann_interval write | 956 B | view raw |
| VERDICT.md | verdict | source-trace confirmation, why not reachable on guest | 3.5 KB | β raw |
| env.txt | environment | guest has no WiFi HW / no wlan module loaded | 302 B | view raw |
| README.md | readme | human reproduce doc | 1.1 KB | β 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 |
DF-0352 PoC β RANN overwrites shared ieee80211_hwmp_rannint (no lock)
Status: LATENT β code-level bug confirmed, NOT reachable on audit guest. Severity: Medium (downgraded from "DoS" because guest lacks WiFi HW)
Bug
sys/netproto/802_11/wlan/ieee80211_hwmp.c:1971 writes the on-wire
rann->rann_interval directly into the file-scope global
ieee80211_hwmp_rannint (used by every vap's RANN callout) with no
lock (the comment even says XXX: mtx lock?). A remote on-link
attacker can forge a RANN with rann_interval=0 to pin the callout
at hard-clock frequency (CPU-saturation DoS), and the unlocked store
races sysctl reads of the same global.
Why not testable here
The audit guest has no WiFi hardware and no wlan/mesh module
loaded. hwmp_recv_rann is dead code at runtime on this guest; an
unprivileged user cannot create a vap, and kldload is root-only.
This is the "genuinely not reachable on this kernel" category with a
real latent bug β see VERDICT.md for the full source trace.
Files
fix.diffβ atomic write + sanity lower-boundVERDICT.mdβ full narrativeenv.txtβ guest environment
DF-0352 β RANN frame overwrites shared global ieee80211_hwmp_rannint (no lock)
Verdict
LATENT β code-level defect confirmed, NOT reachable on this guest.
The bug is real by source inspection. The audit guest has no WiFi
hardware and no wlan/mesh module loaded, so the receive path that
writes the shared global (hwmp_recv_rann) is dead code at runtime
here. An unprivileged local user cannot create a WiFi vap, inject a
frame, or load a WiFi driver module β all are root-only operations on
this guest. This is the "genuinely not reachable on this kernel"
category with a real latent bug.
Bug mechanism (source trace)
File: sys/netproto/802_11/wlan/ieee80211_hwmp.c.
- Line 183:
static int ieee80211_hwmp_rannint = -1;β file-scope global shared across all vaps in the system. - Lines 184β186: exposed as a writable sysctl
(
net.wlan_hwmp.rannint), with no internal locking. - Line 220: initialized to
msecs_to_ticks(1*1000)at module load. - Line 841:
callout_reset(&hs->hs_roottimer, ieee80211_hwmp_rannint, ...)β drives the periodic root-announcement callout period for every RANN-rooted vap, using the shared global. - Line 914: same global is read when sending a RANN
(
rann.rann_interval = ieee80211_hwmp_rannint). - Line 1971 (the bug): inside
hwmp_recv_rann, on receiving ANY RANN frame from the wire:c ieee80211_hwmp_rannint = rann->rann_interval; /* XXX: mtx lock? */The on-the-wirerann_intervalfield (attacker-controlled) is written directly into the shared global with no lock (theXXX: mtx lock?comment admits the omission).
Effects if reachable (realistic threat model)
On a host with a WiFi NIC in mesh mode + HWMP root mode:
- A remote on-link attacker sends a forged RANN with rann_interval=0
(or 1 tick). The victim's RANN callout is reset to that interval,
producing a tight-loop callout firing every tick β CPU saturation
on the callout's CPU.
- Concurrent sysctl reads / vap switches race the unlocked write β
torn reads, possibly bogus callout_reset args.
- The attacker controls rann_interval (16-bit), but the effect is
bounded to "drive callout at attacker-chosen rate"; no direct
memory corruption in this specific write.
So the realistic impact ceiling is remote DoS via CPU saturation + lockless-write race. No memory-corruption primitive.
Why not testable on this guest
$ ssh dfbsd-maxx 'ifconfig -l' vtnet0 lo0 $ ssh dfbsd 'kldstat | grep mesh' # (empty) $ ssh dfbsd 'pciconf -l | grep -i wireless' # (empty)
No WiFi hardware is presented to the guest. wlan.ko exists on disk
but is not loaded (and kldload is root-only, hence cannot be part
of an unprivileged chain). A vap cannot be created without a WiFi
driver instance, which itself requires real WiFi hardware or a
software-defined radio β neither available here.
The bug requires: WiFi NIC driver attached + vap in HWMP/RANN root mode + receiving a forged RANN. None of these can be set up by an unprivileged user, and none are present by default on the audit guest.
Recommended fix
Take hs->hs_lock (or the mesh state lock) around the write at
line 1971, AND validate rann->rann_interval against a sane
minimum (e.g. reject 0 / very-small values to prevent the
callout-tightening DoS). See fix.diff.
Files in this folder
fix.diffβ adds a lock around the write + a sanity lower-boundVERDICT.mdβ this filemanifest.jsonenv.txtβ guest environment confirming no WiFi HW
Fix verification
not_testablecompile validated
see evidence pack
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
Source-confirmed. RANN frame overwrites global ieee80211_hwmp_rannint unlocked. No WiFi HW.
No comments yet.