diff mbox series

[1/1] wifi: mac80211: ignore the bitrate mask when scanning

Message ID 20240125090737.49673-2-dmantipov@yandex.ru
State New
Headers show
Series Re: wifi: mac80211: don't ask rate control with zero rate mask if scanning | expand

Commit Message

Dmitry Antipov Jan. 25, 2024, 9:07 a.m. UTC
When the frame is transmitted due to scanning rather than
regular operation on the interface, ignore the bitrate mask.

Reported-by: syzbot+fdc5123366fb9c3fdc6d@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=fdc5123366fb9c3fdc6d
Suggested-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
---
 include/net/mac80211.h | 3 +++
 net/mac80211/rate.c    | 4 +++-
 net/mac80211/scan.c    | 2 ++
 3 files changed, 8 insertions(+), 1 deletion(-)

Comments

Johannes Berg Jan. 26, 2024, 10:06 a.m. UTC | #1
On Thu, 2024-01-25 at 12:07 +0300, Dmitry Antipov wrote:
> 
> +++ b/net/mac80211/rate.c
> @@ -351,6 +351,7 @@ static void __rate_control_send_low(struct ieee80211_hw *hw,
>  	int i;
>  	u32 rate_flags =
>  		ieee80211_chandef_rate_flags(&hw->conf.chandef);
> +	bool scanning = !!(info->control.flags & IEEE80211_TX_CTRL_SCAN_TX);
>  
>  	if (sband->band == NL80211_BAND_S1GHZ) {
>  		info->control.rates[0].flags |= IEEE80211_TX_RC_S1G_MCS;
> @@ -364,7 +365,8 @@ static void __rate_control_send_low(struct ieee80211_hw *hw,
>  
>  	info->control.rates[0].idx = 0;
>  	for (i = 0; i < sband->n_bitrates; i++) {
> -		if (!(rate_mask & BIT(i)))
> +		/* Do not use the bitrate mask when scanning. */
> +		if (!scanning && !(rate_mask & BIT(i)))
>  			continue;
> 

I know my patch didn't work, but I think I'd still prefer if we didn't
pass a 0 rate mask around to ignore it - maybe we can just make it ~0 in
the outer place that looks at the sdata mask(s)?

I'm not sure why we fill "BIT(sband->n_bitrates) - 1" rather than ~0 in
the first place, we always (have to) check anyway, so wouldn't really
care about having more bits set than rates exist ...

johannes
diff mbox series

Patch

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index d400fe2e8668..df9b578e58bb 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -932,6 +932,8 @@  enum mac80211_tx_info_flags {
  *	of their QoS TID or other priority field values.
  * @IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX: first MLO TX, used mostly internally
  *	for sequence number assignment
+ * @IEEE80211_TX_CTRL_SCAN_TX: Indicates that this frame is transmitted
+ *	due to scanning, not in normal operation on the interface.
  * @IEEE80211_TX_CTRL_MLO_LINK: If not @IEEE80211_LINK_UNSPECIFIED, this
  *	frame should be transmitted on the specific link. This really is
  *	only relevant for frames that do not have data present, and is
@@ -952,6 +954,7 @@  enum mac80211_tx_control_flags {
 	IEEE80211_TX_CTRL_NO_SEQNO		= BIT(7),
 	IEEE80211_TX_CTRL_DONT_REORDER		= BIT(8),
 	IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX	= BIT(9),
+	IEEE80211_TX_CTRL_SCAN_TX		= BIT(10),
 	IEEE80211_TX_CTRL_MLO_LINK		= 0xf0000000,
 };
 
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index d5ea5f5bcf3a..6878fe454c36 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -351,6 +351,7 @@  static void __rate_control_send_low(struct ieee80211_hw *hw,
 	int i;
 	u32 rate_flags =
 		ieee80211_chandef_rate_flags(&hw->conf.chandef);
+	bool scanning = !!(info->control.flags & IEEE80211_TX_CTRL_SCAN_TX);
 
 	if (sband->band == NL80211_BAND_S1GHZ) {
 		info->control.rates[0].flags |= IEEE80211_TX_RC_S1G_MCS;
@@ -364,7 +365,8 @@  static void __rate_control_send_low(struct ieee80211_hw *hw,
 
 	info->control.rates[0].idx = 0;
 	for (i = 0; i < sband->n_bitrates; i++) {
-		if (!(rate_mask & BIT(i)))
+		/* Do not use the bitrate mask when scanning. */
+		if (!scanning && !(rate_mask & BIT(i)))
 			continue;
 
 		if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 645355e5f1bc..dd68dfe46e0e 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -632,6 +632,8 @@  static void ieee80211_send_scan_probe_req(struct ieee80211_sub_if_data *sdata,
 				cpu_to_le16(IEEE80211_SN_TO_SEQ(sn));
 		}
 		IEEE80211_SKB_CB(skb)->flags |= tx_flags;
+		IEEE80211_SKB_CB(skb)->control.flags |=
+			IEEE80211_TX_CTRL_SCAN_TX;
 		ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band);
 	}
 }