Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH 00/10] wifi: nl80211/mac80211: Sashiko fixes
@ 2026-10-05 20:47 Johannes Berg
  2026-10-05 20:47 ` [PATCH 01/10] wifi: mac80211: clear fragment cache entry 'is_protected' Johannes Berg
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: Johannes Berg @ 2026-10-05 20:47 UTC (permalink / raw)
  To: linux-wireless

So Sashiko started reporting bugs (in private) now, I took
a look and knocked down the obvious ones...

johannes


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 01/10] wifi: mac80211: clear fragment cache entry 'is_protected'
  2026-10-05 20:47 [PATCH 00/10] wifi: nl80211/mac80211: Sashiko fixes Johannes Berg
@ 2026-10-05 20:47 ` Johannes Berg
  2026-10-05 20:47 ` [PATCH 02/10] wifi: mac80211: mesh: use hlist_add_head_rcu() Johannes Berg
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Johannes Berg @ 2026-10-05 20:47 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

In practice, we probably shouldn't end up with a fragmented
frame that's protected, filled into the cache, finished or
dropped and then the next frame is unprotected, since only
unicast data frames can be fragmented.

However, tools complain and it's more correct to be able to
do this (e.g. an unencrypted fragmented EAPOL _could_, at
least in theory, happen), so clear the flag when the entry
is reused.

Assisted-by: LLM
Fixes: 7e44a0b597f0 ("mac80211: prevent attacks on TKIP/WEP as well")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/rx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 1121e650b0dd..bd8ae24ed1be 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2284,6 +2284,7 @@ ieee80211_reassemble_add(struct ieee80211_fragment_cache *cache,
 	entry->rx_queue = rx_queue;
 	entry->last_frag = frag;
 	entry->check_sequential_pn = false;
+	entry->is_protected = false;
 	entry->extra_len = 0;
 
 	return entry;
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 02/10] wifi: mac80211: mesh: use hlist_add_head_rcu()
  2026-10-05 20:47 [PATCH 00/10] wifi: nl80211/mac80211: Sashiko fixes Johannes Berg
  2026-10-05 20:47 ` [PATCH 01/10] wifi: mac80211: clear fragment cache entry 'is_protected' Johannes Berg
@ 2026-10-05 20:47 ` Johannes Berg
  2026-10-05 20:47 ` [PATCH 03/10] wifi: mac80211: kill wake_txqs_tasklet on unregistration Johannes Berg
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Johannes Berg @ 2026-10-05 20:47 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

The mesh paths walk list used under RCU, so we must use
hlist_add_head_rcu() to publish an entry. Fix one place
that didn't do that.

Assisted-by: LLM
Fixes: b4c3fbe63601 ("mac80211: Use linked list instead of rhashtable walk for mesh tables")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/mesh_pathtbl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 7b2f71186dfb..0485a979b3c2 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -712,7 +712,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
 						  &new_mpath->rhash,
 						  mesh_rht_params);
 	if (!mpath)
-		hlist_add_head(&new_mpath->walk_list, &tbl->walk_head);
+		hlist_add_head_rcu(&new_mpath->walk_list, &tbl->walk_head);
 	spin_unlock_bh(&tbl->walk_lock);
 
 	if (mpath) {
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 03/10] wifi: mac80211: kill wake_txqs_tasklet on unregistration
  2026-10-05 20:47 [PATCH 00/10] wifi: nl80211/mac80211: Sashiko fixes Johannes Berg
  2026-10-05 20:47 ` [PATCH 01/10] wifi: mac80211: clear fragment cache entry 'is_protected' Johannes Berg
  2026-10-05 20:47 ` [PATCH 02/10] wifi: mac80211: mesh: use hlist_add_head_rcu() Johannes Berg
@ 2026-10-05 20:47 ` Johannes Berg
  2026-10-05 20:47 ` [PATCH 04/10] wifi: nl80211: reject zero RNR/MBSSID elements Johannes Berg
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Johannes Berg @ 2026-10-05 20:47 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

We never kill the wake_txqs_tasklet so it could be running
while the hardware is being freed. Kill it, late enough to
never be able to restart afterwards.

Assisted-by: LLM
Fixes: 21a5d4c3a45c ("mac80211: add stop/start logic for software TXQs")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/main.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index b889d2a7ef75..ad7dfc07ee63 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1738,6 +1738,8 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
 
 	cancel_work_sync(&local->restart_work);
 
+	tasklet_kill(&local->wake_txqs_tasklet);
+
 	ieee80211_clear_tx_pending(local);
 	rate_control_deinitialize(local);
 
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 04/10] wifi: nl80211: reject zero RNR/MBSSID elements
  2026-10-05 20:47 [PATCH 00/10] wifi: nl80211/mac80211: Sashiko fixes Johannes Berg
                   ` (2 preceding siblings ...)
  2026-10-05 20:47 ` [PATCH 03/10] wifi: mac80211: kill wake_txqs_tasklet on unregistration Johannes Berg
@ 2026-10-05 20:47 ` Johannes Berg
  2026-10-05 20:47 ` [PATCH 05/10] wifi: mac80211: init radiotap iter after length checks Johannes Berg
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Johannes Berg @ 2026-10-05 20:47 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

That's a nonsensical configuration, and we get errors
reported further down in mac80211 for it; hostapd has
code that only adds the nested element if it'll not be
an empty list.

Remove an unnecessary NULL check while at it.

Fixes: dbbb27e183b1 ("cfg80211: support RNR for EMA AP")
Assisted-by: LLM
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/wireless/nl80211.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 7ee69ec10b0f..9c2d5c89598b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6582,6 +6582,9 @@ nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs,
 		num_elems++;
 	}
 
+	if (!num_elems)
+		return ERR_PTR(-EINVAL);
+
 	elems = kzalloc_flex(*elems, elem, num_elems);
 	if (!elems)
 		return ERR_PTR(-ENOMEM);
@@ -6617,6 +6620,9 @@ nl80211_parse_rnr_elems(struct wiphy *wiphy, struct nlattr *attrs,
 		num_elems++;
 	}
 
+	if (!num_elems)
+		return ERR_PTR(-EINVAL);
+
 	elems = kzalloc_flex(*elems, elem, num_elems);
 	if (!elems)
 		return ERR_PTR(-ENOMEM);
@@ -6860,7 +6866,8 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
 			if (IS_ERR(rnr))
 				return PTR_ERR(rnr);
 
-			if (rnr && rnr->cnt < bcn->mbssid_ies->cnt) {
+			/* RNR elements are only used with MBSSID elements */
+			if (rnr->cnt < bcn->mbssid_ies->cnt) {
 				kfree(rnr);
 				return -EINVAL;
 			}
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 05/10] wifi: mac80211: init radiotap iter after length checks
  2026-10-05 20:47 [PATCH 00/10] wifi: nl80211/mac80211: Sashiko fixes Johannes Berg
                   ` (3 preceding siblings ...)
  2026-10-05 20:47 ` [PATCH 04/10] wifi: nl80211: reject zero RNR/MBSSID elements Johannes Berg
@ 2026-10-05 20:47 ` Johannes Berg
  2026-10-05 20:47 ` [PATCH 06/10] wifi: mac80211: limit injected HT/VHT MCSes Johannes Berg
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Johannes Berg @ 2026-10-05 20:47 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

The radiotap iterator initialization will already parse
the presence bitmaps, so it accesses a good part of the
header. This might not be present in the linear part of
the SKB, we haven't checked it at this point. Check the
lengths first.

Assisted-by: LLM
Fixes: cb17ed29a7a5 ("mac80211: parse radiotap header when selecting Tx queue")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/tx.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 1953ec35c783..ff493e9203e3 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2182,8 +2182,6 @@ bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
 	struct ieee80211_radiotap_header *rthdr =
 		(struct ieee80211_radiotap_header *) skb->data;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
-						   NULL);
 	u16 txflags;
 	u16 rate = 0;
 	bool rate_found = false;
@@ -2192,11 +2190,14 @@ bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
 	u8 mcs_known, mcs_flags, mcs_bw;
 	u16 vht_known;
 	u8 vht_mcs = 0, vht_nss = 0;
-	int i;
+	int ret, i;
 
 	if (!ieee80211_validate_radiotap_len(skb))
 		return false;
 
+	ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
+					       NULL);
+
 	info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
 		       IEEE80211_TX_CTL_DONTFRAG;
 
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 06/10] wifi: mac80211: limit injected HT/VHT MCSes
  2026-10-05 20:47 [PATCH 00/10] wifi: nl80211/mac80211: Sashiko fixes Johannes Berg
                   ` (4 preceding siblings ...)
  2026-10-05 20:47 ` [PATCH 05/10] wifi: mac80211: init radiotap iter after length checks Johannes Berg
@ 2026-10-05 20:47 ` Johannes Berg
  2026-10-05 20:47 ` [PATCH 07/10] wifi: mac80211: mesh: fix path table generation counters Johannes Berg
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Johannes Berg @ 2026-10-05 20:47 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

With radiotap injection the HT/VHT MCSes can be just
about anything, but that can later get problematic.

Limit them to the rates the device reports, which is
presumably going to be a subset of what mac80211 can
do, except for HT MCS 32 which some devices report as
supported, but then TX status can't deal with it.

If it's not supported just ignore the config.

Assisted-by: LLM
Fixes: dfdfc2beb0dd ("mac80211: Parse legacy and HT rate in injected frames")
Fixes: 646e76bb5daf ("mac80211: parse VHT info in injected frames")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/tx.c | 33 ++++++++++++++++++++++++++++++---
 1 file changed, 30 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index ff493e9203e3..34f3a4ac7278 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2172,6 +2172,27 @@ static bool ieee80211_rate_bw_usable(u16 rate_flags,
 	return width <= cfg80211_chandef_get_width(chandef);
 }
 
+static bool
+ieee80211_vht_tx_rate_supported(const struct ieee80211_sta_vht_cap *vht_cap,
+				u8 mcs, u8 nss)
+{
+	u16 map = le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map);
+
+	if (!vht_cap->vht_supported)
+		return false;
+
+	switch ((map >> (2 * (nss - 1))) & 3) {
+	case IEEE80211_VHT_MCS_SUPPORT_0_7:
+		return mcs <= 7;
+	case IEEE80211_VHT_MCS_SUPPORT_0_8:
+		return mcs <= 8;
+	case IEEE80211_VHT_MCS_SUPPORT_0_9:
+		return mcs <= 9;
+	default:
+		return false;
+	}
+}
+
 bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
 				 struct net_device *dev,
 				 const struct cfg80211_chan_def *chandef,
@@ -2368,14 +2389,20 @@ bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
 					hweight8(info->control.antennas))
 				info->control.antennas = 0;
 
-			info->control.rates[0].idx = rate;
+			/* MCS 32 and up aren't handled, e.g. by TX status */
+			if (sband && sband->ht_cap.ht_supported && rate < 32 &&
+			    sband->ht_cap.mcs.rx_mask[rate / 8] & BIT(rate % 8))
+				info->control.rates[0].idx = rate;
 		} else if (rate_flags & IEEE80211_TX_RC_VHT_MCS) {
 			/* reset antennas if not enough */
 			if (vht_nss > hweight8(info->control.antennas))
 				info->control.antennas = 0;
 
-			ieee80211_rate_set_vht(info->control.rates, vht_mcs,
-					       vht_nss);
+			if (sband &&
+			    ieee80211_vht_tx_rate_supported(&sband->vht_cap,
+							    vht_mcs, vht_nss))
+				ieee80211_rate_set_vht(info->control.rates,
+						       vht_mcs, vht_nss);
 		} else if (sband) {
 			for (i = 0; i < sband->n_bitrates; i++) {
 				if (rate * 5 != sband->bitrates[i].bitrate)
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 07/10] wifi: mac80211: mesh: fix path table generation counters
  2026-10-05 20:47 [PATCH 00/10] wifi: nl80211/mac80211: Sashiko fixes Johannes Berg
                   ` (5 preceding siblings ...)
  2026-10-05 20:47 ` [PATCH 06/10] wifi: mac80211: limit injected HT/VHT MCSes Johannes Berg
@ 2026-10-05 20:47 ` Johannes Berg
  2026-10-05 20:47 ` [PATCH 08/10] wifi: mac80211: fix mbssid/rnr allocation in beacon data Johannes Berg
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Johannes Berg @ 2026-10-05 20:47 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

The mesh and MPP path generation counters (for netlink)
are updated wrongly and sometimes unlocked. Fix those
issues.

Assisted-by: LLM
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/mesh_pathtbl.c | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 0485a979b3c2..dcb0a58e0fa9 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -711,8 +711,10 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
 	mpath = rhashtable_lookup_get_insert_fast(&tbl->rhead,
 						  &new_mpath->rhash,
 						  mesh_rht_params);
-	if (!mpath)
+	if (!mpath) {
 		hlist_add_head_rcu(&new_mpath->walk_list, &tbl->walk_head);
+		sdata->u.mesh.mesh_paths_generation++;
+	}
 	spin_unlock_bh(&tbl->walk_lock);
 
 	if (mpath) {
@@ -725,7 +727,6 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
 		new_mpath = mpath;
 	}
 
-	sdata->u.mesh.mesh_paths_generation++;
 	return new_mpath;
 }
 
@@ -760,8 +761,10 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata,
 	ret = rhashtable_lookup_insert_fast(&tbl->rhead,
 					    &new_mpath->rhash,
 					    mesh_rht_params);
-	if (!ret)
+	if (!ret) {
 		hlist_add_head_rcu(&new_mpath->walk_list, &tbl->walk_head);
+		sdata->u.mesh.mpp_paths_generation++;
+	}
 	spin_unlock_bh(&tbl->walk_lock);
 
 	if (ret) {
@@ -771,7 +774,6 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata,
 		mesh_fast_tx_flush_addr(sdata, dst);
 	}
 
-	sdata->u.mesh.mpp_paths_generation++;
 	return ret;
 }
 
@@ -833,10 +835,13 @@ static void __mesh_path_del(struct mesh_table *tbl, struct mesh_path *mpath)
 	spin_lock_bh(&mpath->state_lock);
 	WRITE_ONCE(mpath->flags, mpath->flags | MESH_PATH_DELETED);
 	spin_unlock_bh(&mpath->state_lock);
-	if (tbl == &mpath->sdata->u.mesh.mpp_paths)
+	if (tbl == &mpath->sdata->u.mesh.mpp_paths) {
+		mpath->sdata->u.mesh.mpp_paths_generation++;
 		mesh_fast_tx_flush_addr(mpath->sdata, mpath->dst);
-	else
+	} else {
+		mpath->sdata->u.mesh.mesh_paths_generation++;
 		mesh_fast_tx_flush_mpath(mpath);
+	}
 	mesh_path_free_rcu(tbl, mpath);
 }
 
@@ -944,14 +949,10 @@ static int table_path_del(struct mesh_table *tbl,
  */
 int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
 {
-	int err;
-
 	/* flush relevant mpp entries first */
 	mpp_flush_by_proxy(sdata, addr);
 
-	err = table_path_del(&sdata->u.mesh.mesh_paths, sdata, addr);
-	sdata->u.mesh.mesh_paths_generation++;
-	return err;
+	return table_path_del(&sdata->u.mesh.mesh_paths, sdata, addr);
 }
 
 /**
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 08/10] wifi: mac80211: fix mbssid/rnr allocation in beacon data
  2026-10-05 20:47 [PATCH 00/10] wifi: nl80211/mac80211: Sashiko fixes Johannes Berg
                   ` (6 preceding siblings ...)
  2026-10-05 20:47 ` [PATCH 07/10] wifi: mac80211: mesh: fix path table generation counters Johannes Berg
@ 2026-10-05 20:47 ` Johannes Berg
  2026-10-05 20:48 ` [PATCH 09/10] wifi: mac80211: don't read runt headers in injection Johannes Berg
  2026-10-05 20:48 ` [PATCH 10/10] wifi: mac80211: fix TDLS setup frame length check Johannes Berg
  9 siblings, 0 replies; 11+ messages in thread
From: Johannes Berg @ 2026-10-05 20:47 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

These structs are placed after the tail, but that can make
them unaligned. Change the order so the structs are after
one another, and then followed by the head/tail/elements.

Assisted-by: LLM
Fixes: 2b3171c6fe0a ("mac80211: MBSSID beacon handling in AP mode")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c | 53 +++++++++++++++++++++++++++-------------------
 1 file changed, 31 insertions(+), 22 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 69002d740a58..d0d14f621588 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1511,6 +1511,7 @@ ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
 	struct beacon_data *new, *old;
 	int new_head_len, new_tail_len;
 	int size, err;
+	u8 *pos;
 	u64 _changed = BSS_CHANGED_BEACON;
 	struct ieee80211_bss_conf *link_conf = link->conf;
 
@@ -1538,20 +1539,16 @@ ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
 	/* new or old multiple BSSID elements? */
 	if (params->mbssid_ies) {
 		mbssid = params->mbssid_ies;
-		size += struct_size(new->mbssid_ies, elem, mbssid->cnt);
-		if (params->rnr_ies) {
-			rnr = params->rnr_ies;
-			size += struct_size(new->rnr_ies, elem, rnr->cnt);
-		}
-		size += ieee80211_get_mbssid_beacon_len(mbssid, rnr,
-							mbssid->cnt);
+		rnr = params->rnr_ies;
 	} else if (old && old->mbssid_ies) {
 		mbssid = old->mbssid_ies;
+		rnr = old->rnr_ies;
+	}
+
+	if (mbssid) {
 		size += struct_size(new->mbssid_ies, elem, mbssid->cnt);
-		if (old->rnr_ies) {
-			rnr = old->rnr_ies;
+		if (rnr)
 			size += struct_size(new->rnr_ies, elem, rnr->cnt);
-		}
 		size += ieee80211_get_mbssid_beacon_len(mbssid, rnr,
 							mbssid->cnt);
 	}
@@ -1563,26 +1560,38 @@ ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
 	/* start filling the new info now */
 
 	/*
-	 * pointers go into the block we allocated,
-	 * memory is | beacon_data | head | tail | mbssid_ies | rnr_ies
+	 * pointers go into the block we allocated, the order in memory is
+	 *  - struct beacon_data
+	 *  - struct mbssid_ies (including variable array)
+	 *  - struct rnr_ies (including variable array)
+	 *  - beacon head
+	 *  - beacon tail
+	 *  - mbssid/rnr elements
+	 * so that the structs (which contain pointers) are all aligned
 	 */
-	new->head = ((u8 *) new) + sizeof(*new);
-	new->tail = new->head + new_head_len;
-	new->head_len = new_head_len;
-	new->tail_len = new_tail_len;
-	/* copy in optional mbssid_ies */
+	pos = (u8 *)(new + 1);
 	if (mbssid) {
-		u8 *pos = new->tail + new->tail_len;
-
 		new->mbssid_ies = (void *)pos;
 		pos += struct_size(new->mbssid_ies, elem, mbssid->cnt);
-		pos += ieee80211_copy_mbssid_beacon(pos, new->mbssid_ies,
-						    mbssid);
 		if (rnr) {
 			new->rnr_ies = (void *)pos;
 			pos += struct_size(new->rnr_ies, elem, rnr->cnt);
-			ieee80211_copy_rnr_beacon(pos, new->rnr_ies, rnr);
 		}
+	}
+
+	new->head = pos;
+	new->head_len = new_head_len;
+	pos += new_head_len;
+	new->tail = pos;
+	new->tail_len = new_tail_len;
+	pos += new_tail_len;
+
+	/* copy in optional mbssid_ies */
+	if (mbssid) {
+		pos += ieee80211_copy_mbssid_beacon(pos, new->mbssid_ies,
+						    mbssid);
+		if (rnr)
+			ieee80211_copy_rnr_beacon(pos, new->rnr_ies, rnr);
 		/* update bssid_indicator */
 		if (new->mbssid_ies->cnt && new->mbssid_ies->elem[0].len > 2)
 			link_conf->bssid_indicator =
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 09/10] wifi: mac80211: don't read runt headers in injection
  2026-10-05 20:47 [PATCH 00/10] wifi: nl80211/mac80211: Sashiko fixes Johannes Berg
                   ` (7 preceding siblings ...)
  2026-10-05 20:47 ` [PATCH 08/10] wifi: mac80211: fix mbssid/rnr allocation in beacon data Johannes Berg
@ 2026-10-05 20:48 ` Johannes Berg
  2026-10-05 20:48 ` [PATCH 10/10] wifi: mac80211: fix TDLS setup frame length check Johannes Berg
  9 siblings, 0 replies; 11+ messages in thread
From: Johannes Berg @ 2026-10-05 20:48 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

For injection we only check the header is in the skb
head, but e.g. ACK/CTS are really short, and we then
try to use A2 anyway. Require A1 (no S1G extension
frames) and use A2 only when present.

Assisted-by: LLM
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/tx.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 34f3a4ac7278..27294466958d 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2471,7 +2471,9 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
 	hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
 
-	if (skb_headlen(skb) < len_rthdr + hdrlen)
+	if (skb_headlen(skb) < len_rthdr +
+			       max_t(int, hdrlen,
+				     offsetofend(struct ieee80211_hdr, addr1)))
 		goto fail;
 
 	/*
@@ -2505,7 +2507,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
 		if (tmp_sdata->vif.type == NL80211_IFTYPE_MONITOR ||
 		    tmp_sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
 			continue;
-		if (ether_addr_equal(tmp_sdata->vif.addr, hdr->addr2)) {
+		if (hdrlen >= offsetofend(struct ieee80211_hdr, addr2) &&
+		    ether_addr_equal(tmp_sdata->vif.addr, hdr->addr2)) {
 			sdata = tmp_sdata;
 			break;
 		}
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 10/10] wifi: mac80211: fix TDLS setup frame length check
  2026-10-05 20:47 [PATCH 00/10] wifi: nl80211/mac80211: Sashiko fixes Johannes Berg
                   ` (8 preceding siblings ...)
  2026-10-05 20:48 ` [PATCH 09/10] wifi: mac80211: don't read runt headers in injection Johannes Berg
@ 2026-10-05 20:48 ` Johannes Berg
  9 siblings, 0 replies; 11+ messages in thread
From: Johannes Berg @ 2026-10-05 20:48 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

If TDLS setup packets are created by AF_PACKET or so, then
the payload may not be present. Since we only care about
those mac80211 generated (which are linear), just replace
the skb->len check with a skb_headlen() check to avoid any
out-of-bounds accesses.

Assisted-by: LLM
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/tx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 27294466958d..8a9466ad9fe3 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2606,7 +2606,7 @@ static inline bool ieee80211_is_tdls_setup(struct sk_buff *skb)
 	u16 ethertype = (skb->data[12] << 8) | skb->data[13];
 
 	return ethertype == ETH_P_TDLS &&
-	       skb->len > 14 &&
+	       skb_headlen(skb) > 14 &&
 	       skb->data[14] == WLAN_TDLS_SNAP_RFTYPE;
 }
 
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2026-10-05 20:50 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-05 20:47 [PATCH 00/10] wifi: nl80211/mac80211: Sashiko fixes Johannes Berg
2026-10-05 20:47 ` [PATCH 01/10] wifi: mac80211: clear fragment cache entry 'is_protected' Johannes Berg
2026-10-05 20:47 ` [PATCH 02/10] wifi: mac80211: mesh: use hlist_add_head_rcu() Johannes Berg
2026-10-05 20:47 ` [PATCH 03/10] wifi: mac80211: kill wake_txqs_tasklet on unregistration Johannes Berg
2026-10-05 20:47 ` [PATCH 04/10] wifi: nl80211: reject zero RNR/MBSSID elements Johannes Berg
2026-10-05 20:47 ` [PATCH 05/10] wifi: mac80211: init radiotap iter after length checks Johannes Berg
2026-10-05 20:47 ` [PATCH 06/10] wifi: mac80211: limit injected HT/VHT MCSes Johannes Berg
2026-10-05 20:47 ` [PATCH 07/10] wifi: mac80211: mesh: fix path table generation counters Johannes Berg
2026-10-05 20:47 ` [PATCH 08/10] wifi: mac80211: fix mbssid/rnr allocation in beacon data Johannes Berg
2026-10-05 20:48 ` [PATCH 09/10] wifi: mac80211: don't read runt headers in injection Johannes Berg
2026-10-05 20:48 ` [PATCH 10/10] wifi: mac80211: fix TDLS setup frame length check Johannes Berg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox