ar9287FillCapabilityInfo never enforces 2GHz-only Kiwi-2 silicon: GMODE divergence re-adds 11A/11NA wireless modes the EEPROM layer explicitly denies, and 5GHz channel edges are inherited β 5GHz channels admitted on 2GHz-only silicon (enabler of the DF-4793 NULL-pier panic)
Summary
The 9287 EEPROM layer refuses AMODE ('no 5GHz for Kiwi') but the inherited ar5416 GMODE block re-ORs 11A/11NA on every stock 11g card, edges are unconditional 4915-6100, and the ~20-field override never clamps - halWirelessModes is the sole HW gate in getchannels, so a 5GHz-permissive EEPROM regdomain admits 5GHz channels on 2GHz-only silicon: selecting one triggers the DF-4793 NULL-pier panic or off-calibration transmission. Exact DF-4799 (ar9285) twin; nf_5g IS populated here so the delta is caps/edges only. Clamp-the-A-family-modes fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4872 Β· 4 files| File | Type | Description | Size | |
|---|---|---|---|---|
| VERDICT.md | file | 5.1 KB | β raw | |
| env.txt | file | 272 B | view raw | |
| fix.diff | file | 1.0 KB | view raw | |
| verdict.json | file | 4.2 KB | view raw |
DF-4872 β ar9287Attach: 2GHz-only Kiwi-2 caps never enforced β GMODE divergence re-adds 11A/11NA modes and 5GHz edges survive; enables 5GHz channel selection on 2GHz-only silicon (upstream enabler of the DF-4793 NULL-pier panic)
What was verified (static, line-by-line; no AR9287 silicon on the audit guest)
The full chain from EEPROM opflag to 5GHz channel admission, every hop cited:
-
The AR9287 EEPROM layer explicitly denies A-mode.
sys/dev/netif/ath/ath_hal/ah_eeprom_9287.c:73-74c case AR_EEP_AMODE: return HAL_EIO; /* no 5GHz for Kiwi */The AR9287 EEPROM image itself carries only 2GHz calibration data:ah_eeprom_9287.h:135-153βcalFreqPier2G[AR9287_NUM_2G_CAL_PIERS],calPierData2G[AR9287_MAX_CHAINS][AR9287_NUM_2G_CAL_PIERS], and a singlemodalHeader("only 2.4ghz here; so only one modal header entry", ah_eeprom_9287.c:187). There is no 5GHz pier/target data anywhere. -
The generic caps builder re-adds 11A anyway via the GMODE divergence.
ar9287Attachβar9287FillCapabilityInfo(sys/dev/netif/ath/ath_hal/ar9002/ar9287_attach.c:321-324, 428-469) callsar5416FillCapabilityInfo(ah)at line 433 and inherits: -ar5416_attach.c:904-915: whenAR_EEP_GMODEis set (every functional 11g card:v9287EepromGetreturns OK whenopCapFlags & AR5416_OPFLAGS_11G,ah_eeprom_9287.c:75-79; identical polarity inah_eeprom_v14.c:110-115andah_eeprom_v4k.c:83-90), lines 910-914 unconditionally ORHAL_MODE_11A | HAL_MODE_11NA_HT20 | HAL_MODE_11NA_HT40PLUS | HAL_MODE_11NA_HT40MINUSintohalWirelessModesβ even though the AMODE branch was denied. -ar5416_attach.c:920-921:halLow5GhzChan = 4915; halHigh5GhzChan = 6100;set unconditionally. -
ar9287FillCapabilityInfo never clamps. Its override block (
ar9287_attach.c:435-466) sets ~20 fields (GPIO count, WoW, RIFS, STBC, SGI20, ...) but never toucheshalWirelessModes,halLow5GhzChan, orhalHigh5GhzChan. Unlike the ar9285 twin (DF-4799), nf_5g is populated here (ar9287_attach.c:353-355), so the residual defect for the AR9287 is exactly the caps/edges divergence. -
halWirelessModes is the channel-admission gate.
if_ath.c:6073-6084ath_getradiocaps()βath_hal_getchannels(..., HAL_MODE_ALL, ...). Ingetchannels()(sys/dev/netif/ath/ath_hal/ah_regdomain.c:398-416):c modesAvail = ath_hal_getWirelessModes(ah); /* == halWirelessModes */ ... if ((cm->mode & modeSelect) == 0) continue; /* HAL_MODE_ALL passes */ if ((cm->mode & modesAvail) == 0) continue; /* <-- the only HW gate */With the divergent 11A/11NA bits set, every 5GHzcmodepasses; the 5GHz channel bitmap then comes from the EEPROM regdomain (ah_currentRD = regDmn[0],ar9287_attach.c:334-335, unvalidated u16).ar5212GetChannelEdges(ar5212_attach.c:646-655) hardcodes 4915/6100 for any 5GHZ-flagged mode, so 5GHz bands are admitted. -
Downstream consequence (already filed at the crash site as DF-4793). Selecting one of those 5GHz channels reaches
ar9287SetPowerCalTable(ar9002/ar9287_reset.c): the 9287 EEPROM accessors return a NULL pier list for non-2GHz channels, and the unguarded per-chain walk NULL-derefspList[0]inath_ee_getLowerUpperIndexβ kernel panic. Even without the panic, the radio is programmed from 2GHz-only calibration data (regulatory misoperation), mirroring DF-4799's impact analysis for the AR9285.
Why no runtime PoC (untested, per family precedent DF-4793/DF-4799/DF-4548)
The trigger requires an AR9287 ("Kite-2") PCIe NIC whose EEPROM carries an 11G opflag (normal) plus a regdomain with 5GHz entries. The single-tenant QEMU/KVM audit guest has no Atheros NIC (no PCIe device assignment), so neither the panic nor the mis-tune can be exercised there. Verification is the static chain above; every hop was opened and read, no hop is assumed.
Threat model
Untrusted-EEPROM (same model as DF-4548/DF-4793/DF-4799): a card with a
reprogrammed/corrupt EEPROM (physical access, resold hardware, or a
malicious "compat" card). No EEPROM validation happens between the raw
image and regDmn[0]/opCapFlags beyond the checksum, which the attacker
recomputes. Note the GMODE hop needs nothing unusual at all β every stock
11g AR9287 satisfies it; only the regdomain content decides whether 5GHz
channels appear.
Fix
Mask the A-family modes and invalidate the 5GHz edges in
ar9287FillCapabilityInfo right after the inherit (see fix.diff). The
cleaner companion fix is in ar5416_attach.c:904-915 β the GMODE block
should not OR 11A/11NA bits; every 5416-family chip that supports 11A
already gets those bits from the AMODE branch β but the per-chip clamp is
the minimal, targeted change (matches the fix proposed for DF-4799).
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 from line-accurate root cause and verified git-apply-able; runtime fix validation impossible on the guest for the same reason the PoC is untested (no AR9287 hardware)
findings/poc/DF-4872/fix.diff
Confirmed kernel references
- sys/dev/netif/ath/ath_hal/ar9002/ar9287_attach.c:433
- sys/dev/netif/ath/ath_hal/ar9002/ar9287_attach.c:429-469
- sys/dev/netif/ath/ath_hal/ar5416/ar5416_attach.c:904-915
- sys/dev/netif/ath/ath_hal/ar5416/ar5416_attach.c:920-921
- sys/dev/netif/ath/ath_hal/ah_eeprom_9287.c:73-79
- sys/dev/netif/ath/ath_hal/ah_eeprom_9287.h:135-153
- sys/dev/netif/ath/ath_hal/ah_regdomain.c:398-416
- sys/dev/netif/ath/ath/if_ath.c:6073-6084
- sys/dev/netif/ath/ath_hal/ar9002/ar9287_reset.c
Detail
Exploit chain
stock 11g opflag (or attacker-reprogrammed EEPROM, checksum recomputed) -> GMODE divergence adds 11A/11NA to halWirelessModes despite AMODE denial -> ar9287FillCapabilityInfo never clamps; 5GHz edges inherited -> ath_getradiocaps HAL_MODE_ALL (if_ath.c:6082) -> getchannels modesAvail gate passes 11A/11NA + EEPROM regdomain rd5GHz bitmaps -> 5GHz channels in ic_channels on 2GHz-only silicon -> channel switch -> DF-4793 NULL pier-list panic in ar9287SetPowerCalTable (or uncalibrated out-of-band radio programming)
Evidence (decisive lines)
findings/poc/DF-4872/VERDICT.md (full static chain with path:line at every hop); findings/poc/DF-4872/fix.diff (git apply --check clean)
PoC changes
No runtime PoC possible: trigger hardware (AR9287 Kite-2 PCIe NIC + its EEPROM) absent from the QEMU guest; verification is the static line-by-line chain in VERDICT.md
Verified recommended fix
In ar9287FillCapabilityInfo, immediately after ar5416FillCapabilityInfo succeeds, mask HAL_MODE_11A|TURBO|108A|11A_HALF|11A_QUARTER|11NA_HT20|11NA_HT40PLUS|11NA_HT40MINUS out of halWirelessModes and zero halLow5GhzChan/halHigh5GhzChan (see fix.diff)
Verdict
Hardware-bound caps/regulatory defect, no memory corruption in this file: ar9287FillCapabilityInfo (ar9287_attach.c:433) inherits ar5416FillCapabilityInfo, whose GMODE block (ar5416_attach.c:904-915) unconditionally ORs HAL_MODE_11A|11NA_HT20|11NA_HT40+|11NA_HT40- into halWirelessModes whenever the EEPROM 11G opflag is set (true on every functional 11g card, polarity verified uniform in v14/v4k/9287 eeprom layers) even though the 9287 EEPROM layer explicitly denies AR_EEP_AMODE ('no 5GHz for Kiwi', ah_eeprom_9287.c:73-74); 5GHz edges 4915/6100 are set unconditionally (ar5416_attach.c:920-921). The override block (ar9287_attach.c:435-466) sets ~20 caps fields but never clamps halWirelessModes or the 5GHz edges. halWirelessModes is the sole hardware gate admitting 11A/11NA cmodes in getchannels (ah_regdomain.c:398-416 'cm->mode & modesAvail'), so an EEPROM regDmn[0] (taken unvalidated at ar9287_attach.c:334-335) with 5GHz entries yields 5GHz channels on 2GHz-only silicon; selecting one hits the already-filed DF-4793 NULL-pier panic in ar9287SetPowerCalTable or programs the RF from 2GHz-only cal data (ar9287 EEPROM image has no 5GHz structures, ah_eeprom_9287.h:135-153). Exact DF-4799 (ar9285) twin shape; unlike ar9287, nf_5g IS populated here (ar9287_attach.c:353-355). Static chain verified hop-by-hop; no AR9287 NIC on the QEMU guest, so untested at runtime per family precedent (DF-4793/DF-4799/DF-4548).
No comments yet.