summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyder Lee <ryder.lee@mediatek.com>2025-09-23 17:23:22 +0000
committerJohannes Berg <johannes.berg@intel.com>2025-10-27 09:16:23 +0100
commita392cde88d19af917740d27e13115447d3b21a06 (patch)
treeabb59ce2c1e5cff529ea11db5451e3da37fc6ac4
parent428ea708b714ba09c96da5722fb1c8b86af509d1 (diff)
wifi: cfg80211/mac80211: validate radio frequency range for monitor mode
In multi-radio devices, it is possible to have an MLD AP and a monitor interface active at the same time. In such cases, monitor mode may not be able to specify a fixed channel and could end up capturing frames from all radios, including those outside the intended frequency bands. This patch adds frequency validation for monitor mode. Received frames are now only processed if their frequency fall within the allowed ranges of the radios specified by the interface's radio_mask. This prevents monitor mode from capturing frames outside the supported radio. Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> Link: https://patch.msgid.link/700b8284e845d96654eb98431f8eeb5a81503862.1758647858.git.ryder.lee@mediatek.com Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/net/cfg80211.h14
-rw-r--r--net/mac80211/rx.c49
-rw-r--r--net/wireless/util.c6
3 files changed, 66 insertions, 3 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 781624f5913a..3b6f48a783bb 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1015,6 +1015,7 @@ const struct cfg80211_chan_def *
cfg80211_chandef_compatible(const struct cfg80211_chan_def *chandef1,
const struct cfg80211_chan_def *chandef2);
+
/**
* nl80211_chan_width_to_mhz - get the channel width in MHz
* @chan_width: the channel width from &enum nl80211_chan_width
@@ -6883,6 +6884,19 @@ static inline bool cfg80211_channel_is_psc(struct ieee80211_channel *chan)
}
/**
+ * ieee80211_radio_freq_range_valid - Check if the radio supports the
+ * specified frequency range
+ *
+ * @radio: wiphy radio
+ * @freq: the frequency (in KHz) to be queried
+ * @width: the bandwidth (in KHz) to be queried
+ *
+ * Return: whether or not the given frequency range is valid for the given radio
+ */
+bool ieee80211_radio_freq_range_valid(const struct wiphy_radio *radio,
+ u32 freq, u32 width);
+
+/**
* cfg80211_radio_chandef_valid - Check if the radio supports the chandef
*
* @radio: wiphy radio
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 6af43dfefdd6..29175a0c9f68 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -763,6 +763,51 @@ ieee80211_make_monitor_skb(struct ieee80211_local *local,
return skb;
}
+static bool
+ieee80211_validate_monitor_radio(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_local *local,
+ struct ieee80211_rx_status *status)
+{
+ struct wiphy *wiphy = local->hw.wiphy;
+ int i, freq, bw;
+
+ if (!wiphy->n_radio)
+ return true;
+
+ switch (status->bw) {
+ case RATE_INFO_BW_20:
+ bw = 20000;
+ break;
+ case RATE_INFO_BW_40:
+ bw = 40000;
+ break;
+ case RATE_INFO_BW_80:
+ bw = 80000;
+ break;
+ case RATE_INFO_BW_160:
+ bw = 160000;
+ break;
+ case RATE_INFO_BW_320:
+ bw = 320000;
+ break;
+ default:
+ return false;
+ }
+
+ freq = MHZ_TO_KHZ(status->freq);
+
+ for (i = 0; i < wiphy->n_radio; i++) {
+ if (!(sdata->wdev.radio_mask & BIT(i)))
+ continue;
+
+ if (!ieee80211_radio_freq_range_valid(&wiphy->radio[i], freq, bw))
+ continue;
+
+ return true;
+ }
+ return false;
+}
+
/*
* This function copies a received frame to all monitor interfaces and
* returns a cleaned-up SKB that no longer includes the FCS nor the
@@ -855,6 +900,10 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
chandef->chan->center_freq != status->freq)
continue;
+ if (ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR) &&
+ !ieee80211_validate_monitor_radio(sdata, local, status))
+ continue;
+
if (!prev_sdata) {
prev_sdata = sdata;
continue;
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 56724b33af04..97f40c6d1e9d 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -2942,9 +2942,8 @@ cfg80211_get_iftype_ext_capa(struct wiphy *wiphy, enum nl80211_iftype type)
}
EXPORT_SYMBOL(cfg80211_get_iftype_ext_capa);
-static bool
-ieee80211_radio_freq_range_valid(const struct wiphy_radio *radio,
- u32 freq, u32 width)
+bool ieee80211_radio_freq_range_valid(const struct wiphy_radio *radio,
+ u32 freq, u32 width)
{
const struct wiphy_radio_freq_range *r;
int i;
@@ -2958,6 +2957,7 @@ ieee80211_radio_freq_range_valid(const struct wiphy_radio *radio,
return false;
}
+EXPORT_SYMBOL(ieee80211_radio_freq_range_valid);
bool cfg80211_radio_chandef_valid(const struct wiphy_radio *radio,
const struct cfg80211_chan_def *chandef)