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

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-0999 Β· 7 files
FileTypeDescriptionSize
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
README.md readme summary
↓ download 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).

VERDICT.md verdict full narrative including the BPARSE_BINTVAL_INVALID dead-flag finding
↓ download raw

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 = 0 once 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.ko is 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 β€” guard bintval == 0 in rum_set_sleep_time
  • module_build.log β€” proof the patched if_rum.c compiles
  • VERDICT.md, README.md, manifest.json

Fix verification

not_testable

compile 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.