mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 13:14:02 +02:00
wifi: mac80211: don't allow injecting frames wider than the chanctx
Frames injected on a monitor interface can carry a radiotap
field requesting a bandwidth, which mac80211 passes down to
the driver regardless of the the actual operational bandwidth.
If the bandwidth requested is too wide, that triggers a warning
in hwsim:
WARN_ON(hwsim_get_chanwidth(bw) > hwsim_get_chanwidth(confbw))
Drop such frames entirely instead since they cannot be sent.
Assisted-by: LLM
Fixes: 646e76bb5d ("mac80211: parse VHT info in injected frames")
Reported-by: syzbot+435fdb053cf98bfa5778@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=435fdb053cf98bfa5778
Link: https://patch.msgid.link/20260908122838.201719-13-johannes@sipsolutions.net
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
c1ba7f7f18
commit
e14bf37bb2
|
|
@ -7638,11 +7638,14 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
|
|||
*
|
||||
* @skb: packet injected by userspace
|
||||
* @dev: the &struct device of this 802.11 device
|
||||
* @chandef: the channel definition the frame will be transmitted on, or
|
||||
* %NULL to skip the bandwidth checks
|
||||
*
|
||||
* Return: %true if the radiotap header was parsed, %false otherwise
|
||||
*/
|
||||
bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
|
||||
struct net_device *dev);
|
||||
struct net_device *dev,
|
||||
const struct cfg80211_chan_def *chandef);
|
||||
|
||||
/**
|
||||
* struct ieee80211_noa_data - holds temporary data for tracking P2P NoA state
|
||||
|
|
|
|||
|
|
@ -991,7 +991,7 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev,
|
|||
/* reset flags and info before parsing radiotap header */
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
if (!ieee80211_parse_tx_radiotap(skb, dev))
|
||||
if (!ieee80211_parse_tx_radiotap(skb, dev, NULL))
|
||||
return 0; /* doesn't matter, frame will be dropped */
|
||||
|
||||
len_rthdr = ieee80211_get_radiotap_len(skb->data);
|
||||
|
|
|
|||
|
|
@ -2105,8 +2105,29 @@ static bool ieee80211_validate_radiotap_len(struct sk_buff *skb)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool ieee80211_rate_bw_usable(u16 rate_flags,
|
||||
const struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
int width;
|
||||
|
||||
if (!chandef)
|
||||
return true;
|
||||
|
||||
if (rate_flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
|
||||
width = 160;
|
||||
else if (rate_flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
|
||||
width = 80;
|
||||
else if (rate_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
|
||||
width = 40;
|
||||
else
|
||||
return true;
|
||||
|
||||
return width <= cfg80211_chandef_get_width(chandef);
|
||||
}
|
||||
|
||||
bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
struct net_device *dev,
|
||||
const struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
struct ieee80211_radiotap_iterator iterator;
|
||||
|
|
@ -2280,6 +2301,9 @@ bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
|
|||
struct ieee80211_supported_band *sband =
|
||||
local->hw.wiphy->bands[info->band];
|
||||
|
||||
if (!ieee80211_rate_bw_usable(rate_flags, chandef))
|
||||
return false;
|
||||
|
||||
info->control.flags |= IEEE80211_TX_CTRL_RATE_INJECT;
|
||||
|
||||
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
|
||||
|
|
@ -2479,7 +2503,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
|
|||
* selected chandef above to accurately set injection rates and
|
||||
* retransmissions.
|
||||
*/
|
||||
if (!ieee80211_parse_tx_radiotap(skb, dev))
|
||||
if (!ieee80211_parse_tx_radiotap(skb, dev, chandef))
|
||||
goto fail_rcu;
|
||||
|
||||
/* remove the injection radiotap header */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user