[PATCH wireless 1/1] wifi: wcn36xx: validate scan bands against radio capabilities
Alexander Vernel
alex at alexvernel.com
Tue Oct 13 02:18:02 PDT 2026
WCN3620 only registers a 2.4 GHz band, but its firmware can report scan
results with rf_band values that select the 5 GHz channel mapping.
The resulting receive status references an unsupported band. On a
WCN3620 tablet, this caused a NULL dereference in the survey update
called by wcn36xx_rx_skb(), with a reported frequency of 5280 MHz.
Only use the 5 GHz mapping when that band is registered. Otherwise
interpret the descriptor's channel as a 2.4 GHz channel. Reject scan
frequencies absent from the registered channel tables before updating
survey data or delivering the frame to mac80211. Ordinary receive and
valid dual-band scan mappings are unchanged.
This follows Stephan Gerhold's WCN3620 workaround in the msm8916
integration tree, using registered band support instead of a radio-ID
check.
AI tools assisted with crash analysis, adaptation of the workaround,
testing and preparation and review of this submission.
Link: https://github.com/msm8916-mainline/linux/commit/0be2d63a476e83c757d9caafc22eae00bcfd1df8
Fixes: 8a27ca394782 ("wcn36xx: Correct band/freq reporting on RX")
Assisted-by: LLM
Signed-off-by: Alexander Vernel <alex at alexvernel.com>
---
The original crash was on 7.3.0-rc6-tb-x103f-mdp3-r28, based on
6c377d19d4a51 with board/display bring-up patches. The affected txrx.c
matches that mainline base. Firmware reported API 1.5.1.2 and CRM 67946-1.
Selected UART lines (other lines omitted):
PC is at wcn36xx_rx_skb+0x160/0x74c [wcn36xx]
LR is at wcn36xx_rx_skb+0x378/0x74c [wcn36xx]
r3 : 00000000 r2 : c1cec260 r1 : 000014a0 r0 : ffffffc4
wcn36xx_rx_skb [wcn36xx] from wcn36xx_rx_handle_packets+0x140/0x218 [wcn36xx]
wcn36xx_rx_handle_packets [wcn36xx] from wcn36xx_dxe_rx_frame+0x70/0xd0 [wcn36xx]
Kernel panic - not syncing: Fatal exception in interrupt
Decoding the exact module locates the fault in wcn36xx_update_survey(),
inlined into wcn36xx_rx_skb(). The frequency is 0x14a0 = 5280 MHz and
the supported-band pointer is NULL. The raw descriptor was not captured;
neither its exact rf_band value nor the actual receive channel is known.
The fallback follows the earlier workaround. Channel-table membership
checks that the decoded frequency is supported, not that it is the
frequency on which this particular frame was received.
Tested on a Lenovo TB-X103F with WCN3620 using a mainline-based board
bring-up kernel, 7.3.0-rc6-tb-x103f-mdp3-r29.
The 20-minute UART capture showed no kernel alerts. Twelve normal scan
requests were accepted; 4 MiB was uploaded and 48 MiB downloaded with
SHA256 verification. This does not establish that the malformed descriptor
occurred again. No dual-band hardware testing was performed.
An extracted-function host harness passes 261 RX cases covering band and
channel decoding, missing channels, ordinary RX and queue purge. The
original code traps at the unsupported-band survey access. With only the
band guard removed, the synthetic WCN3620 channel-6 case is dropped
instead of delivered as 2437 MHz. With only the channel guard removed,
invalid-frequency cases are not dropped. These are separate expectations;
the mutation tests do not show that both guards are individually needed
to prevent the reported panic.
These tests use shims and do not simulate firmware, concurrency or full
A-MSDU handling. An ARMv7 W=1 kernel/modules/DTB build completed without
warnings.
drivers/net/wireless/ath/wcn36xx/txrx.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c
index 882699879..c12d4a503 100644
--- a/drivers/net/wireless/ath/wcn36xx/txrx.c
+++ b/drivers/net/wireless/ath/wcn36xx/txrx.c
@@ -367,7 +367,9 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
*/
u8 hwch = (bd->reserved0 << 4) + bd->rx_ch;
- if (bd->rf_band != 1 && hwch <= sizeof(ab_rx_ch_map) && hwch >= 1) {
+ /* WCN3620 can report a 5 GHz band for 2.4 GHz scan results. */
+ if (wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] &&
+ bd->rf_band != 1 && hwch <= sizeof(ab_rx_ch_map) && hwch >= 1) {
status.band = NL80211_BAND_5GHZ;
status.freq = ieee80211_channel_to_frequency(ab_rx_ch_map[hwch - 1],
status.band);
@@ -375,6 +377,9 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
status.band = NL80211_BAND_2GHZ;
status.freq = ieee80211_channel_to_frequency(hwch, status.band);
}
+
+ if (!ieee80211_get_channel(wcn->hw->wiphy, status.freq))
+ goto drop;
} else {
status.band = WCN36XX_BAND(wcn);
status.freq = WCN36XX_CENTER_FREQ(wcn);
More information about the wcn36xx
mailing list