Commit 91b193d5 authored by Benjamin Berg's avatar Benjamin Berg Committed by Johannes Berg

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: default avatarBenjamin Berg <benjamin.berg@intel.com>
Signed-off-by: default avatarMiri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20240602102200.876b10a2beda.I0d3d0daea4014e99654437ff6691378dbe452652@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent c1d8bd8d
...@@ -263,6 +263,37 @@ static int cfg80211_chandef_get_width(const struct cfg80211_chan_def *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); 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) bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
{ {
u32 control_freq, oper_freq; u32 control_freq, oper_freq;
...@@ -374,6 +405,13 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) ...@@ -374,6 +405,13 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
return false; 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 */ /* channel 14 is only for IEEE 802.11b */
if (chandef->center_freq1 == 2484 && if (chandef->center_freq1 == 2484 &&
chandef->width != NL80211_CHAN_WIDTH_20_NOHT) chandef->width != NL80211_CHAN_WIDTH_20_NOHT)
......
...@@ -113,16 +113,16 @@ static const struct chandef_compat_case { ...@@ -113,16 +113,16 @@ static const struct chandef_compat_case {
}, },
}, },
{ {
.desc = "different primary 160 MHz", .desc = "different primary 320 MHz",
.c1 = { .c1 = {
.width = NL80211_CHAN_WIDTH_320, .width = NL80211_CHAN_WIDTH_320,
.chan = &chan_6ghz_105, .chan = &chan_6ghz_105,
.center_freq1 = 6475 + 150, .center_freq1 = 6475 + 110,
}, },
.c2 = { .c2 = {
.width = NL80211_CHAN_WIDTH_320, .width = NL80211_CHAN_WIDTH_320,
.chan = &chan_6ghz_105, .chan = &chan_6ghz_105,
.center_freq1 = 6475 - 10, .center_freq1 = 6475 - 50,
}, },
}, },
{ {
...@@ -131,12 +131,12 @@ static const struct chandef_compat_case { ...@@ -131,12 +131,12 @@ static const struct chandef_compat_case {
.c1 = { .c1 = {
.width = NL80211_CHAN_WIDTH_160, .width = NL80211_CHAN_WIDTH_160,
.chan = &chan_6ghz_105, .chan = &chan_6ghz_105,
.center_freq1 = 6475 + 70, .center_freq1 = 6475 + 30,
}, },
.c2 = { .c2 = {
.width = NL80211_CHAN_WIDTH_320, .width = NL80211_CHAN_WIDTH_320,
.chan = &chan_6ghz_105, .chan = &chan_6ghz_105,
.center_freq1 = 6475 - 10, .center_freq1 = 6475 - 50,
}, },
.compat = true, .compat = true,
}, },
...@@ -145,12 +145,12 @@ static const struct chandef_compat_case { ...@@ -145,12 +145,12 @@ static const struct chandef_compat_case {
.c1 = { .c1 = {
.width = NL80211_CHAN_WIDTH_160, .width = NL80211_CHAN_WIDTH_160,
.chan = &chan_6ghz_105, .chan = &chan_6ghz_105,
.center_freq1 = 6475 + 70, .center_freq1 = 6475 + 30,
}, },
.c2 = { .c2 = {
.width = NL80211_CHAN_WIDTH_320, .width = NL80211_CHAN_WIDTH_320,
.chan = &chan_6ghz_105, .chan = &chan_6ghz_105,
.center_freq1 = 6475 - 10, .center_freq1 = 6475 - 50,
.punctured = 0xf, .punctured = 0xf,
}, },
.compat = true, .compat = true,
...@@ -160,13 +160,13 @@ static const struct chandef_compat_case { ...@@ -160,13 +160,13 @@ static const struct chandef_compat_case {
.c1 = { .c1 = {
.width = NL80211_CHAN_WIDTH_160, .width = NL80211_CHAN_WIDTH_160,
.chan = &chan_6ghz_105, .chan = &chan_6ghz_105,
.center_freq1 = 6475 + 70, .center_freq1 = 6475 + 30,
.punctured = 0xc0, .punctured = 0xc0,
}, },
.c2 = { .c2 = {
.width = NL80211_CHAN_WIDTH_320, .width = NL80211_CHAN_WIDTH_320,
.chan = &chan_6ghz_105, .chan = &chan_6ghz_105,
.center_freq1 = 6475 - 10, .center_freq1 = 6475 - 50,
.punctured = 0xc000, .punctured = 0xc000,
}, },
.compat = true, .compat = true,
...@@ -176,13 +176,13 @@ static const struct chandef_compat_case { ...@@ -176,13 +176,13 @@ static const struct chandef_compat_case {
.c1 = { .c1 = {
.width = NL80211_CHAN_WIDTH_160, .width = NL80211_CHAN_WIDTH_160,
.chan = &chan_6ghz_105, .chan = &chan_6ghz_105,
.center_freq1 = 6475 + 70, .center_freq1 = 6475 + 30,
.punctured = 0x80, .punctured = 0x80,
}, },
.c2 = { .c2 = {
.width = NL80211_CHAN_WIDTH_320, .width = NL80211_CHAN_WIDTH_320,
.chan = &chan_6ghz_105, .chan = &chan_6ghz_105,
.center_freq1 = 6475 - 10, .center_freq1 = 6475 - 50,
.punctured = 0xc000, .punctured = 0xc000,
}, },
}, },
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment