From 91b193d546683558a8799ffb2e2f935d3800633e Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Sun, 2 Jun 2024 10:22:00 +0300 Subject: [PATCH] wifi: cfg80211: reject non-conformant 6 GHz center frequencies On 6 GHz (and also 5 GHz to some degree), only a specific set of center frequencies should be used depending on the channel bandwidth. Verify this is the case on 6 GHz. For 5 GHz, we are more accepting as there are APs that got it wrong historically. Signed-off-by: Benjamin Berg Signed-off-by: Miri Korenblit Link: https://msgid.link/20240602102200.876b10a2beda.I0d3d0daea4014e99654437ff6691378dbe452652@changeid Signed-off-by: Johannes Berg --- net/wireless/chan.c | 38 ++++++++++++++++++++++++++++++++++++++ net/wireless/tests/chan.c | 22 +++++++++++----------- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/net/wireless/chan.c b/net/wireless/chan.c index bf2fdcd42019..e579d7e1425f 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -263,6 +263,37 @@ static int cfg80211_chandef_get_width(const struct cfg80211_chan_def *c) return nl80211_chan_width_to_mhz(c->width); } +static bool cfg80211_valid_center_freq(u32 center, + enum nl80211_chan_width width) +{ + int bw; + int step; + + /* We only do strict verification on 6 GHz */ + if (center < 5955 || center > 7115) + return true; + + bw = nl80211_chan_width_to_mhz(width); + if (bw < 0) + return false; + + /* Validate that the channels bw is entirely within the 6 GHz band */ + if (center - bw / 2 < 5945 || center + bw / 2 > 7125) + return false; + + /* With 320 MHz the permitted channels overlap */ + if (bw == 320) + step = 160; + else + step = bw; + + /* + * Valid channels are packed from lowest frequency towards higher ones. + * So test that the lower frequency alignes with one of these steps. + */ + return (center - bw / 2 - 5945) % step == 0; +} + bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) { u32 control_freq, oper_freq; @@ -374,6 +405,13 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) return false; } + if (!cfg80211_valid_center_freq(chandef->center_freq1, chandef->width)) + return false; + + if (chandef->width == NL80211_CHAN_WIDTH_80P80 && + !cfg80211_valid_center_freq(chandef->center_freq2, chandef->width)) + return false; + /* channel 14 is only for IEEE 802.11b */ if (chandef->center_freq1 == 2484 && chandef->width != NL80211_CHAN_WIDTH_20_NOHT) diff --git a/net/wireless/tests/chan.c b/net/wireless/tests/chan.c index d02258ac2dab..74bbee25085f 100644 --- a/net/wireless/tests/chan.c +++ b/net/wireless/tests/chan.c @@ -113,16 +113,16 @@ static const struct chandef_compat_case { }, }, { - .desc = "different primary 160 MHz", + .desc = "different primary 320 MHz", .c1 = { .width = NL80211_CHAN_WIDTH_320, .chan = &chan_6ghz_105, - .center_freq1 = 6475 + 150, + .center_freq1 = 6475 + 110, }, .c2 = { .width = NL80211_CHAN_WIDTH_320, .chan = &chan_6ghz_105, - .center_freq1 = 6475 - 10, + .center_freq1 = 6475 - 50, }, }, { @@ -131,12 +131,12 @@ static const struct chandef_compat_case { .c1 = { .width = NL80211_CHAN_WIDTH_160, .chan = &chan_6ghz_105, - .center_freq1 = 6475 + 70, + .center_freq1 = 6475 + 30, }, .c2 = { .width = NL80211_CHAN_WIDTH_320, .chan = &chan_6ghz_105, - .center_freq1 = 6475 - 10, + .center_freq1 = 6475 - 50, }, .compat = true, }, @@ -145,12 +145,12 @@ static const struct chandef_compat_case { .c1 = { .width = NL80211_CHAN_WIDTH_160, .chan = &chan_6ghz_105, - .center_freq1 = 6475 + 70, + .center_freq1 = 6475 + 30, }, .c2 = { .width = NL80211_CHAN_WIDTH_320, .chan = &chan_6ghz_105, - .center_freq1 = 6475 - 10, + .center_freq1 = 6475 - 50, .punctured = 0xf, }, .compat = true, @@ -160,13 +160,13 @@ static const struct chandef_compat_case { .c1 = { .width = NL80211_CHAN_WIDTH_160, .chan = &chan_6ghz_105, - .center_freq1 = 6475 + 70, + .center_freq1 = 6475 + 30, .punctured = 0xc0, }, .c2 = { .width = NL80211_CHAN_WIDTH_320, .chan = &chan_6ghz_105, - .center_freq1 = 6475 - 10, + .center_freq1 = 6475 - 50, .punctured = 0xc000, }, .compat = true, @@ -176,13 +176,13 @@ static const struct chandef_compat_case { .c1 = { .width = NL80211_CHAN_WIDTH_160, .chan = &chan_6ghz_105, - .center_freq1 = 6475 + 70, + .center_freq1 = 6475 + 30, .punctured = 0x80, }, .c2 = { .width = NL80211_CHAN_WIDTH_320, .chan = &chan_6ghz_105, - .center_freq1 = 6475 - 10, + .center_freq1 = 6475 - 50, .punctured = 0xc000, }, },