Divide-by-zero in rum_set_sleep_time when associated AP advertises zero beacon interval
Summary
rum_set_sleep_time at if_rum.c:2671 exp=ic->ic_lintval/bintval; :2672 delay=ic->ic_lintval%bintval. bintval from vap->iv_bss->ni_intval which net80211 copies verbatim from beacon interval IE (ieee80211_input.c:545 le16toh) with NO non-zero validation. Malicious AP beacon_int=0 -> victim STA associates -> RUN state -> rum_enable_tsf_sync :2220 -> rum_set_sleep_time(0) -> #DE -> kernel panic. ic_lintval default 100 !=0 so division fires. Remote DoS within radio range. Fix: if(bintval==0) return EINVAL.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-0999 Β· 7 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fix.diff | suggested-fix | guard bintval==0 in rum_set_sleep_time (treat as 1) | 610 B | view raw |
| module_build.log | build-log | if_rum.ko compiles cleanly with the fix applied | 1.3 KB | view raw |
| VERDICT.md | verdict | full narrative including the BPARSE_BINTVAL_INVALID dead-flag finding | 3.5 KB | β raw |
| README.md | readme | summary | 802 B | β raw |
| manifest.json | manifest | this catalog | 2.5 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 |
DF-0999 β rum_set_sleep_time divide-by-zero
Summary
rum_set_sleep_time() at sys/bus/u4b/wlan/if_rum.c:2671 divides
ic->ic_lintval / bintval where bintval ultimately comes from the
beacon IE. net80211 does flag bintval=0 as IEEE80211_BPARSE_BINTVAL_INVALID
but never enforces the flag, so the zero reaches the divide β #DE β
kernel panic.
Trigger: malicious AP within radio range broadcasting beacon_int=0; victim
STA associates β RUN state β rum_enable_tsf_sync β rum_set_sleep_time(0).
Why not tested on default guest
No RT2573 USB WiFi adapter and no malicious AP in the QEMU guest.
Fix
fix.diff guards bintval == 0 (treat as 1) at the top of
rum_set_sleep_time().
Compilation check
Compiles cleanly into if_rum.ko (see module_build.log).
DF-0999 β rum_set_sleep_time divide-by-zero (zero beacon interval)
Verdict
NOT TESTABLE on default guest (requires Ralink RT2573 USB WiFi adapter
associating with a malicious AP, neither present). Bug is real and
confirmed by source review; net80211 does flag bintval=0 as
invalid but the flag is never enforced, so the bad value reaches the
divide. The fix.diff compiles cleanly as a KLD module (see
module_build.log).
Mechanism (cited)
rum_set_sleep_time() at sys/bus/u4b/wlan/if_rum.c:2662-2691:
2671: exp = ic->ic_lintval / bintval; /* <-- #DE if bintval == 0 */
2672: delay = ic->ic_lintval % bintval;
bintval is passed in from rum_enable_tsf_sync() at
sys/bus/u4b/wlan/if_rum.c:2184:
2184: bintval = vap->iv_bss->ni_intval;
...
2220: return (rum_set_sleep_time(sc, bintval));
ni_intval is copied verbatim from the beacon IE at
sys/netproto/802_11/wlan/ieee80211_input.c:545:
scan->bintval = le16toh(*(uint16_t *)frm); and reaches
ni->ni_intval = sp->bintval; at
sys/netproto/802_11/wlan/ieee80211_node.c:1525 without modification.
Important refinement of the original claim
The finding summary states net80211 "copies verbatim ... with NO non-zero
validation." That is inaccurate but inconsequential: net80211 does
check at sys/netproto/802_11/wlan/ieee80211_input.c:700-708:
700: if (!(IEEE80211_BINTVAL_MIN <= scan->bintval &&
701: scan->bintval <= IEEE80211_BINTVAL_MAX)) {
702: IEEE80211_DISCARD(vap, ...);
706: vap->iv_stats.is_rx_badbintval++;
707: scan->status |= IEEE80211_BPARSE_BINTVAL_INVALID;
708: }
(IEEE80211_BINTVAL_MIN=25, MAX=1000 per sys/netproto/802_11/ieee80211.h:1337-1338).
But IEEE80211_BPARSE_BINTVAL_INVALID (0x40, defined at
sys/netproto/802_11/ieee80211_scan.h:212) is never checked anywhere.
The only BPARSE_ flag the scan path consumes is OFFCHAN
(sys/netproto/802_11/wlan/ieee80211_scan_sta.c:296,319 and
sys/netproto/802_11/wlan/ieee80211_hostap.c:1707,1768). So the bad
bintval flows through ise->se_intval = sp->bintval;
(ieee80211_scan_sta.c:308) β ni->ni_intval = sp->bintval;
(ieee80211_node.c:1525) β rum_set_sleep_time(0) β #DE / kernel panic*.
ic->ic_lintval defaults to 100 (non-zero), so the divide fires on a zero
bintval argument regardless of ic_lintval.
Impact
- Kernel panic / DoS (#DE on divide-by-zero).
- Triggerable remotely within radio range by a malicious AP broadcasting
beacon_int = 0once the victim STA attempts to associate. CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H(Medium as filed).
Why not tested on the guest
- No Ralink RT2573 USB WiFi adapter is attached to the QEMU guest.
if_rum.kois not loaded.- Reproduction requires a USB WiFi adapter in STA mode within range of a malicious AP β outside the audit guest's capabilities.
Fix
fix.diff β at the top of rum_set_sleep_time(), treat bintval == 0
as 1 to avoid the trap. This is the most localized defense; a more
thorough fix would be to enforce IEEE80211_BPARSE_BINTVAL_INVALID in
net80211 (drop the beacon / refuse association when the flag is set), but
that is a larger change in another subsystem.
Compilation check
Fix (applied with DF-0997 and DF-0998) compiles cleanly into if_rum.ko.
See module_build.log.
Files
fix.diffβ guardbintval == 0inrum_set_sleep_timemodule_build.logβ proof the patchedif_rum.ccompilesVERDICT.md,README.md,manifest.json
Fix verification
not_testablecompile validated
see evidence pack
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
Source-confirmed. rum_set_sleep_time bintval=0 -> div-by-zero. BPARSE_BINTVAL_INVALID dead flag. No if_rum HW. Fix compiles.
No comments yet.