Reachable KASSERT panic in ath_rate_ctl_start() from a zero-length Supported Rates IE beacon β remote DoS on default (INVARIANTS) DragonFly kernels with ath+onoe+IBSS
Summary
DFly's DEFAULT kernel ships INVARIANTS (verified in the running guest) making this KASSERT a production panic: a beacon with IBSS capinfo and a zero-length RATES IE passes element verification (checks maxlen only), the rate-setup error is discarded, and ic_newassoc reaches the assert - the code's own comment documents rate-less adhoc nodes as 'not fatal'. One crafted beacon = kernel panic from radio range. amrr.c:312 carries the identical assert (twin flagged). Graceful-return fix (+ mirror). [PASS-2 NOTE: amrr.c:312 carries the identical reachable KASSERT - apply the same graceful-return fix there (see findings/poc/DF-4882/fix.diff)]
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4882 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.9 KB | β raw | |
| VERDICT.md | β | 2.4 KB | β raw | |
| env.txt | β | 1.1 KB | view raw | |
| fix.diff | β | 836 B | view raw | |
| verdict.json | β | 3.4 KB | view raw |
DF-4882 β onoe ath_rate_ctl_start() reachable KASSERT panic via rate-less IBSS beacon
What
sys/dev/netif/ath/ath_rate/onoe/onoe.c:285:
KASSERT(ni->ni_rates.rs_nrates > 0, ("no rates"));
DragonFly's default kernel config ships options INVARIANTS
(sys/config/X86_64_GENERIC:56, verified in the running guest), so KASSERT
is an active panic in production. A single unauthenticated 802.11
beacon/probe-response with a zero-length Supported Rates IE (and IBSS
capability bit), received by an ath(4) interface running in adhoc (IBSS)
mode with the onoe ratectl module attached, reaches this KASSERT and panics
the kernel.
Full static chain (every hop verified in-tree)
adhoc_recv_mgmtprocesses BEACON/PROBE_RESP frames β unauthenticated (sys/netproto/802_11/wlan/ieee80211_adhoc.c:678-699).ieee80211_parse_beacononly flags a missing RATES element (IEEE80211_BPARSE_RATES_INVALID, ieee80211_input.c:667-668) β a zero-length RATES IE passesIEEE80211_VERIFY_ELEMENT(checksie[1] > maxlenonly β ieee80211_input.h:31-41; 0 <= 15) with clean status.- IBSS capinfo + unknown addr2 β
ieee80211_add_neighbor(ieee80211_adhoc.c:727-735). ieee80211_init_neighborβieee80211_setup_rates(ni, sp->rates, ...)withrates[1] == 0βrs_nrates = 0βieee80211_fix_rateloop body never executes βokrate == 0β returns error (sys/netproto/802_11/wlan/ieee80211_proto.c:682,746-748) β and the return value is ignored (ieee80211_node.c:1559-1561).ieee80211_add_neighborproceeds unconditionally toic->ic_newassoc(ni, 1)(ieee80211_node.c:1607-1608).ath_newassocβath_rate_newassoc(sc, an, isnew)(sys/dev/netif/ath/ath/if_ath.c:1271, ~ath_newassoc body).- onoe.c:189-190
isnewβath_rate_ctl_startβ KASSERT panic (onoe.c:285). The very next lines (onoe.c:316-321) explicitly document that nodes without a rate set are expected here ("orphaned nodes created in adhoc mode may not have any rate set ... This is not fatal") β but on INVARIANTS kernels the KASSERT fires first and it is fatal.
The amrr sibling has the identical KASSERT (amrr.c:312, filed separately
as context only; this pack covers onoe).
Threat model
Unauthenticated radio-range peer (IBSS participant or spoofer of the cell's BSSID) β kernel panic = remote DoS. Preconditions: Atheros NIC + onoe ratectl module attached (sample is the shipped default, X86_64_GENERIC:266) + IBSS/adhoc vap + INVARIANTS kernel (the default).
Why not reproduced on the QEMU guest
The guest has no Atheros NIC (pciconf shows only a virtio vgapci) and no onoe.ko module (env.txt). The chain is proven statically end-to-end above.
Fix
Replace the KASSERT with the graceful fallback the surrounding code already implements (drop the rate-ctl start for empty rate sets), matching the code's own comment that this case "is not fatal". See fix.diff.
DF-4882 VERDICT
Status: inconclusive (guest lacks the required hardware; static chain proven end-to-end; no kernel manifestation possible on this guest).
What was verified
- Guest kernel:
DragonFly dfbsd 6.5-DEVELOPMENT #0 .../sys/X86_64_GENERICβ the shipped default config includesoptions INVARIANTS(verified at/usr/src/sys/config/X86_64_GENERIC:56in the guest), so KASSERT is an active panic, not a debug nicety. This is the decisive environmental fact for severity: the assertion is production-reachable. - Guest hardware:
pciconf -lshows onlyvgapci0@pci0:0:2:0 chip=0x11111234(virtio-gpu). No Atheros (168c:) device, no radio. - Guest modules:
/boot/kernelcontainsif_ath.ko,ath_hal.ko,ath_rate.ko(strings identify it as sample, the default), andwlan_amrr.ko. No onoe module is shipped. - Source audit chain (README.md) β every hop cited path:line; nothing
relies on speculation. The empty-rate-set scenario is acknowledged by
the code itself (onoe.c:316-320 "orphaned nodes created in adhoc mode
may not have any rate set ... This is not fatal"), and
ieee80211_setup_rates's error return for zero rates (ieee80211_proto.c:746-748) is demonstrably ignored at ieee80211_node.c:1559-1561.
Why it cannot be exercised here
Triggering requires an ath(4) interface in IBSS mode with onoe attached and
an injected 802.11 beacon β none of which QEMU/virtio can provide (no NIC,
no 802.11 stack attachment, module absent). Building onoe.ko in the guest
would not help: ic_newassoc is only wired to onoe code when an ath device
attaches through it.
Impact ceiling
Remote kernel panic (DoS) of the default INVARIANTS kernel, from one crafted frame, for ath+onoe+IBSS configurations. amrr.c:312 has the same bug (out of this file's scope).
Fix validation
Not possible on this guest (no ath hardware). fix.diff authored against the read-only tree: converts the KASSERT into the graceful path the surrounding code already implements. fix_status: not_applicable.
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_testablefix.diff authored (KASSERT -> graceful return for rs_nrates==0, matching the code's own 'not fatal' comment) but not kernel-buildable-testable here: the panic path needs an ath NIC in IBSS mode with onoe attached, which the guest cannot provide.
findings/poc/DF-4882/fix.diff
Confirmed kernel references
- sys/dev/netif/ath/ath_rate/onoe/onoe.c:285
- sys/netproto/802_11/wlan/ieee80211_adhoc.c:735
- sys/netproto/802_11/wlan/ieee80211_node.c:1559
- sys/netproto/802_11/wlan/ieee80211_node.c:1607
- sys/netproto/802_11/wlan/ieee80211_proto.c:746
- sys/netproto/802_11/ieee80211_input.h:31
- sys/dev/netif/ath/ath/if_ath.c:1271
- sys/config/X86_64_GENERIC:56
Detail
Exploit chain
unauthenticated radio peer -> beacon/probe-resp with IBSS capinfo + zero-length RATES IE -> adhoc_recv_mgmt (ieee80211_adhoc.c:735) -> ieee80211_add_neighbor -> ic_newassoc(ni,1) (ieee80211_node.c:1607) -> ath_rate_newassoc isnew (onoe.c:187-190) -> ath_rate_ctl_start -> KASSERT panic (onoe.c:285). Cannot be chained further: it is a clean panic.
Evidence (decisive lines)
README.md (full hop-by-hop chain with path:line), VERDICT.md (environment facts), env.txt (guest: INVARIANTS at X86_64_GENERIC:56, pciconf shows no 168c device, /boot/kernel has no onoe module). Decisive lines: onoe.c:285 KASSERT; ieee80211_node.c:1607-1608 unconditional ic_newassoc; ieee80211_proto.c:746-748 okrate==0 error path ignored.
PoC changes
n/a - no runnable PoC possible without ath hardware; evidence pack documents the static chain and guest environment instead
Verified recommended fix
Replace onoe.c:285 KASSERT with an early return when rs_nrates==0 (the path ath_rate_update already handles gracefully), and mirror in amrr.c:312
Verdict
Reachable-assertion panic, proven statically end-to-end but not exercisable on this guest (no Atheros NIC, no onoe module). DragonFly's default kernel config ships INVARIANTS (verified at /usr/src/sys/config/X86_64_GENERIC:56 in the running guest), so onoe.c:285 KASSERT is an active panic: an unauthenticated IBSS beacon with a zero-length Supported Rates IE reaches ic_newassoc(ni,1) with rs_nrates==0 because ieee80211_parse_beacon accepts zero-length RATES elements (ieee80211_input.h:31-41 checks ie[1] > maxlen only) and ieee80211_init_neighbor ignores the ieee80211_setup_rates error return (ieee80211_node.c:1559-1561, ieee80211_proto.c:746-748). The code's own comment (onoe.c:316-320) documents that rate-less adhoc nodes reach this path and claims it is 'not fatal' - on INVARIANTS kernels it is. Remote DoS for ath+onoe+IBSS configurations.
No comments yet.