[PATCH AUTOSEL 6.0 02/44] wifi: cfg80211: Fix bitrates overflow issue

From: Sasha Levin
Date: Fri Nov 18 2022 - 21:11:41 EST


From: Paul Zhang <quic_paulz@xxxxxxxxxxx>

[ Upstream commit 18429c51c7ff6e6bfd627316c54670230967a7e5 ]

When invoking function cfg80211_calculate_bitrate_eht about
(320 MHz, EHT-MCS 13, EHT-NSS 2, EHT-GI 0), which means the
parameters as flags: 0x80, bw: 7, mcs: 13, eht_gi: 0, nss: 2,
this formula (result * rate->nss) will overflow and causes
the returned bitrate to be 3959 when it should be 57646.

Here is the explanation:
u64 tmp;
u32 result;

/* tmp = result = 4 * rates_996[0]
* = 4 * 480388888 = 0x72889c60
*/
tmp = result;

/* tmp = 0x72889c60 * 6144 = 0xabccea90000 */
tmp *= SCALE;

/* tmp = 0xabccea90000 / mcs_divisors[13]
* = 0xabccea90000 / 5120 = 0x8970bba6
*/
do_div(tmp, mcs_divisors[rate->mcs]);

/* result = 0x8970bba6 */
result = tmp;

/* normally (result * rate->nss) = 0x8970bba6 * 2 = 0x112e1774c,
* but since result is u32, (result * rate->nss) = 0x12e1774c,
* overflow happens and it loses the highest bit.
* Then result = 0x12e1774c / 8 = 39595753,
*/
result = (result * rate->nss) / 8;

Signed-off-by: Paul Zhang <quic_paulz@xxxxxxxxxxx>
Signed-off-by: Johannes Berg <johannes.berg@xxxxxxxxx>
Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>
---
net/wireless/util.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/net/wireless/util.c b/net/wireless/util.c
index 775836f6785a..450d609b512a 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1555,10 +1555,12 @@ static u32 cfg80211_calculate_bitrate_eht(struct rate_info *rate)
tmp = result;
tmp *= SCALE;
do_div(tmp, mcs_divisors[rate->mcs]);
- result = tmp;

/* and take NSS */
- result = (result * rate->nss) / 8;
+ tmp *= rate->nss;
+ do_div(tmp, 8);
+
+ result = tmp;

return result / 10000;
}
--
2.35.1