DORMANTno replies

[PATCH wireless-next v2] wifi: nxpwifi: validate variable IE lengths in beacon parser

From: Aamir Ahmed <hidden>
Date: 2026-09-12 16:20:36
Also in: lkml
Subsystem: networking drivers (wireless), nxp nxpwifi wireless driver, the rest · Maintainers: Johannes Berg, Jeff Chen, Linus Torvalds

nxpwifi_update_bss_desc_with_ie() stores pointers to the HT, VHT and HE
capability and operation elements, to the operating mode notification
and to the 20/40 BSS coexistence element, taken from a beacon or probe
response, without checking that each element is long enough for the
structure the driver later dereferences it as.

bss_desc->beacon_buf is a tight kmemdup() of the on-air elements, so a
truncated element leaves the stored pointer short of the structure and
the consumers read past the end of that allocation at association time.
Some of those bytes are copied into the association request, so a rogue
access point in range can both trigger the read and receive the result.

Reject the frame with -EINVAL when any of these elements is shorter than
the structure read from it, as the FH, DS and CF parameter set cases in
the same parser already do.

The extended capabilities element has no structure size to check
against, so nxpwifi_is_ap_11ax_twt_supported()'s read of
bcn_ext_cap->data[9] is bounded at that consumer instead.

Fixes: 73b01e57ed3e ("wifi: nxp: add nxpwifi driver for IW61x")
Assisted-by: LLM
Signed-off-by: Aamir Ahmed <redacted>
---
v2:
  - drop Cc: stable; nxpwifi is not in a released kernel yet (Jeff)
  - cut the commit message down (Jeff)
  - Assisted-by: LLM, without the tool name
  - name the target tree in the subject
v1: https://lore.kernel.org/linux-wireless/AS8P251MB00017FB955BDEFEEA1EA579BC8B32@AS8P251MB0001.EURP251.PROD.OUTLOOK.COM/ (local)

Tested on a KASAN kernel with a harness that feeds a short element
stream ending in a zero-length HT capability element to the parser and
then copies from bcn_ht_cap as the association path does: unpatched that
copy trips a slab-out-of-bounds read, patched the parser returns -EINVAL
and KASAN is silent. I have no IW61x hardware, so the over-the-air path
was not exercised.

 drivers/net/wireless/nxp/nxpwifi/11ax.c |  2 ++
 drivers/net/wireless/nxp/nxpwifi/scan.c | 18 ++++++++++++++++++
 2 files changed, 20 insertions(+)
diff --git a/drivers/net/wireless/nxp/nxpwifi/11ax.c b/drivers/net/wireless/nxp/nxpwifi/11ax.c
index 96540914f3cf..dc1e747383ec 100644
--- a/drivers/net/wireless/nxp/nxpwifi/11ax.c
+++ b/drivers/net/wireless/nxp/nxpwifi/11ax.c
@@ -402,6 +402,8 @@ static u8 nxpwifi_is_ap_11ax_twt_supported(struct nxpwifi_bssdescriptor *bss_des
 		return false;
 	ext_cap = (struct element *)bss_desc->bcn_ext_cap;
 
+	if (ext_cap->datalen < 10)
+		return false;
 	if (!(ext_cap->data[9] & WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT))
 		return false;
 	return true;
diff --git a/drivers/net/wireless/nxp/nxpwifi/scan.c b/drivers/net/wireless/nxp/nxpwifi/scan.c
index b77056983e83..d82ee8e502f6 100644
--- a/drivers/net/wireless/nxp/nxpwifi/scan.c
+++ b/drivers/net/wireless/nxp/nxpwifi/scan.c
@@ -1209,6 +1209,8 @@ int nxpwifi_update_bss_desc_with_ie(struct nxpwifi_adapter *adapter,
 				(u16)(current_ptr - bss_entry->beacon_buf);
 			break;
 		case WLAN_EID_HT_CAPABILITY:
+			if (element_len < sizeof(*bss_entry->bcn_ht_cap))
+				return -EINVAL;
 			bss_entry->bcn_ht_cap =
 				(struct ieee80211_ht_cap *)(current_ptr +
 							    elem_size);
@@ -1217,6 +1219,8 @@ int nxpwifi_update_bss_desc_with_ie(struct nxpwifi_adapter *adapter,
 				      bss_entry->beacon_buf);
 			break;
 		case WLAN_EID_HT_OPERATION:
+			if (element_len < sizeof(*bss_entry->bcn_ht_oper))
+				return -EINVAL;
 			bss_entry->bcn_ht_oper =
 				(struct ieee80211_ht_operation *)(current_ptr +
 								  elem_size);
@@ -1225,6 +1229,8 @@ int nxpwifi_update_bss_desc_with_ie(struct nxpwifi_adapter *adapter,
 				      bss_entry->beacon_buf);
 			break;
 		case WLAN_EID_VHT_CAPABILITY:
+			if (element_len < sizeof(*bss_entry->bcn_vht_cap))
+				return -EINVAL;
 			bss_entry->disable_11ac = false;
 			bss_entry->bcn_vht_cap = (void *)(current_ptr +
 							  elem_size);
@@ -1233,6 +1239,8 @@ int nxpwifi_update_bss_desc_with_ie(struct nxpwifi_adapter *adapter,
 				      bss_entry->beacon_buf);
 			break;
 		case WLAN_EID_VHT_OPERATION:
+			if (element_len < sizeof(*bss_entry->bcn_vht_oper))
+				return -EINVAL;
 			bss_entry->bcn_vht_oper =
 				(void *)(current_ptr + elem_size);
 			bss_entry->vht_info_offset =
@@ -1240,6 +1248,8 @@ int nxpwifi_update_bss_desc_with_ie(struct nxpwifi_adapter *adapter,
 				      bss_entry->beacon_buf);
 			break;
 		case WLAN_EID_BSS_COEX_2040:
+			if (!element_len)
+				return -EINVAL;
 			bss_entry->bcn_bss_co_2040 = current_ptr;
 			bss_entry->bss_co_2040_offset =
 				(u16)(current_ptr - bss_entry->beacon_buf);
@@ -1250,6 +1260,8 @@ int nxpwifi_update_bss_desc_with_ie(struct nxpwifi_adapter *adapter,
 				(u16)(current_ptr - bss_entry->beacon_buf);
 			break;
 		case WLAN_EID_OPMODE_NOTIF:
+			if (total_ie_len < sizeof(*bss_entry->oper_mode))
+				return -EINVAL;
 			bss_entry->oper_mode = (void *)current_ptr;
 			bss_entry->oper_mode_offset =
 				(u16)(current_ptr - bss_entry->beacon_buf);
@@ -1262,6 +1274,9 @@ int nxpwifi_update_bss_desc_with_ie(struct nxpwifi_adapter *adapter,
 
 			switch (elem->data[0]) {
 			case WLAN_EID_EXT_HE_CAPABILITY:
+				if (element_len <
+				    1 + sizeof(*bss_entry->bcn_he_cap))
+					return -EINVAL;
 				bss_entry->disable_11ax = false;
 				bss_entry->bcn_he_cap =
 					(void *)(current_ptr + elem_size + 1);
@@ -1270,6 +1285,9 @@ int nxpwifi_update_bss_desc_with_ie(struct nxpwifi_adapter *adapter,
 					      bss_entry->beacon_buf);
 				break;
 			case WLAN_EID_EXT_HE_OPERATION:
+				if (element_len <
+				    1 + sizeof(*bss_entry->bcn_he_oper))
+					return -EINVAL;
 				bss_entry->bcn_he_oper =
 					(void *)(current_ptr + elem_size + 1);
 				bss_entry->he_info_offset =
base-commit: df2908090cda368b01ff43709f51890076c56157
-- 
2.55.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help