Linux-mediatek Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH wireless] wifi: mt76: mt792x: validate ACPI SAR table length before parsing
@ 2026-08-11 23:28 Devin Wittmayer
  2026-09-04  3:18 ` Devin Wittmayer
  0 siblings, 1 reply; 2+ messages in thread
From: Devin Wittmayer @ 2026-08-11 23:28 UTC (permalink / raw)
  To: Felix Fietkau, Lorenzo Bianconi
  Cc: linux-wireless, linux-mediatek, Ryder Lee, Shayne Chen, Sean Wang,
	Deren Wu, Sagun Kayastha

Both SAR readers derive the entry count from the ACPI buffer length.
Nothing checks that the length is at least the header size, that it
divides evenly into whole entries, or that the count the table declares
in nr_tbl matches.  A malformed table whose length happens to land the
count inside the accepted range is parsed with the wrong layout and its
limits are applied to the radio.

mt792x_acpi_read() allocates exactly package.count bytes and only rejects
counts below 4, so a four byte table is possible.  The MTDS path already
reads ->enable at offset 4 before any length check, past the end of such
a buffer.

Take the length checks first, then read the header fields, then compare
the derived count against nr_tbl.

Seen on an ASUS ROG Zephyrus G15 GA503RM whose MTGS and MTDS are both
malformed.  The parser accepted them and applied a limit that clamped
every txpower_sku entry to tmac 4, about 2 dBm.  With them rejected,
txpower goes from 3.00 dBm to 23.00 dBm and txpower_sku spreads back
across OFDM/HT20/HT40/VHT80/VHT160.

Fixes: f965333e491e ("mt76: mt7921: introduce ACPI SAR support")
Link: https://github.com/morrownr/mt76/issues/62
Reported-by: Sagun Kayastha <sgn.kayastha@gmail.com>
Tested-by: Sagun Kayastha <sgn.kayastha@gmail.com>
Signed-off-by: Devin Wittmayer <lucid_duck@justthetip.ca>
---
 .../wireless/mediatek/mt76/mt792x_acpi_sar.c  | 28 ++++++++++++++++---
 1 file changed, 24 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c b/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c
index 946dd79..7e72c38 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c
+++ b/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c
@@ -114,6 +114,7 @@ mt792x_asar_acpi_read_mtds(struct mt792x_dev *dev, u8 **table, u8 version)
 {
 	int len, ret, sarlen, prelen, tblcnt;
 	bool enable;
+	u8 nr_tbl;
 
 	ret = mt792x_acpi_read(dev, MT792x_ACPI_MTDS, table, &len);
 	if (ret)
@@ -122,12 +123,10 @@ mt792x_asar_acpi_read_mtds(struct mt792x_dev *dev, u8 **table, u8 version)
 	/* Table content validation */
 	switch (version) {
 	case 1:
-		enable = ((struct mt792x_asar_dyn *)*table)->enable;
 		sarlen = sizeof(struct mt792x_asar_dyn_limit);
 		prelen = sizeof(struct mt792x_asar_dyn);
 		break;
 	case 2:
-		enable = ((struct mt792x_asar_dyn_v2 *)*table)->enable;
 		sarlen = sizeof(struct mt792x_asar_dyn_limit_v2);
 		prelen = sizeof(struct mt792x_asar_dyn_v2);
 		break;
@@ -135,8 +134,19 @@ mt792x_asar_acpi_read_mtds(struct mt792x_dev *dev, u8 **table, u8 version)
 		return -EINVAL;
 	}
 
+	if (len < prelen || (len - prelen) % sarlen)
+		return -EINVAL;
+
+	if (version == 1) {
+		enable = ((struct mt792x_asar_dyn *)*table)->enable;
+		nr_tbl = ((struct mt792x_asar_dyn *)*table)->nr_tbl;
+	} else {
+		enable = ((struct mt792x_asar_dyn_v2 *)*table)->enable;
+		nr_tbl = ((struct mt792x_asar_dyn_v2 *)*table)->nr_tbl;
+	}
+
 	tblcnt = (len - prelen) / sarlen;
-	if (!enable ||
+	if (!enable || tblcnt != nr_tbl ||
 	    tblcnt > MT792x_ASAR_MAX_DYN || tblcnt < MT792x_ASAR_MIN_DYN)
 		return -EINVAL;
 
@@ -148,6 +158,7 @@ static int
 mt792x_asar_acpi_read_mtgs(struct mt792x_dev *dev, u8 **table, u8 version)
 {
 	int len, ret, sarlen, prelen, tblcnt;
+	u8 nr_tbl;
 
 	ret = mt792x_acpi_read(dev, MT792x_ACPI_MTGS, table, &len);
 	if (ret)
@@ -167,8 +178,17 @@ mt792x_asar_acpi_read_mtgs(struct mt792x_dev *dev, u8 **table, u8 version)
 		return -EINVAL;
 	}
 
+	if (len < prelen || (len - prelen) % sarlen)
+		return -EINVAL;
+
+	if (version == 1)
+		nr_tbl = ((struct mt792x_asar_geo *)*table)->nr_tbl;
+	else
+		nr_tbl = ((struct mt792x_asar_geo_v2 *)*table)->nr_tbl;
+
 	tblcnt = (len - prelen) / sarlen;
-	if (tblcnt > MT792x_ASAR_MAX_GEO || tblcnt < MT792x_ASAR_MIN_GEO)
+	if (tblcnt != nr_tbl ||
+	    tblcnt > MT792x_ASAR_MAX_GEO || tblcnt < MT792x_ASAR_MIN_GEO)
 		return -EINVAL;
 
 	return 0;
-- 
2.55.0



^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH wireless] wifi: mt76: mt792x: validate ACPI SAR table length before parsing
  2026-08-11 23:28 [PATCH wireless] wifi: mt76: mt792x: validate ACPI SAR table length before parsing Devin Wittmayer
@ 2026-09-04  3:18 ` Devin Wittmayer
  0 siblings, 0 replies; 2+ messages in thread
From: Devin Wittmayer @ 2026-09-04  3:18 UTC (permalink / raw)
  To: Felix Fietkau, Lorenzo Bianconi
  Cc: linux-wireless, linux-mediatek, Ryder Lee, Shayne Chen, Sean Wang,
	Deren Wu, Sagun Kayastha

I've been back through the GA503RM's bytes since sending this, and
calling those tables malformed isn't right. Both are version 2, and MTCL
is what declares version 1 for all three, so they get read as v1 and
every field shifts a byte:

  MTGS  28 bytes   as v1: (28-6) % 5 = 2, nr_tbl 0, count 4
                   as v2: (28-7) % 7 = 0, nr_tbl 3, count 3
  MTDS  19 bytes   as v1: (19-6) % 6 = 1, nr_tbl 0, count 2
                   as v2: (19-7) % 12 = 0, nr_tbl 1, count 1

Read as version 2 they're an ordinary SAR table:

  MTGS, FCC   2.4 GHz 14 dBm    5 GHz 14.5 dBm    6 GHz 8.5 dBm
  MTDS        8 to 14.5 dBm across the range

So this patch rejects two good tables and leaves the machine with no SAR
limit at all. The reporter measured 23 dBm afterwards, on a laptop whose
own tables ask for 14.5.

The layouts are 6 + 5n and 7 + 7n bytes with the count declared inside,
so they never collide at any accepted size and the right one falls out
of the shape. I have that written: it applies 14.5 dBm where this patch
applies nothing.

I think parsing them is the better answer, since it gives the machine
what it asks for. Rejecting is safer if you'd sooner not have the driver
guess at a layout.

Devin


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-09-04  3:18 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-11 23:28 [PATCH wireless] wifi: mt76: mt792x: validate ACPI SAR table length before parsing Devin Wittmayer
2026-09-04  3:18 ` Devin Wittmayer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox