summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2026-07-24 12:47:47 +0000
committerFelix Fietkau <nbd@nbd.name>2026-07-31 12:25:40 +0000
commit6689b4a65e88d7b019e687fa9d6943ca070f3e43 (patch)
tree4112ee8755dacdb88a343f956d31bc6768a0b557
parent44af52467e72094351a362bf69effd52f1d9c186 (diff)
downloadlinux-next-6689b4a65e88d7b019e687fa9d6943ca070f3e43.tar.gz
linux-next-6689b4a65e88d7b019e687fa9d6943ca070f3e43.zip
wifi: mt76: fix out-of-bounds access in mmio copy helpers
mt76_mmio_write_copy() and mt76_mmio_read_copy() iterate up to ALIGN(len, 4), so a length that is not a multiple of four reads past the source buffer (write_copy) or writes past the destination (read_copy). Copy the aligned body in the loop and handle the remaining tail through a 4-byte bounce buffer, keeping the register access width unchanged. Fixes: 2df00805f7db ("wifi: mt76: mmio_*_copy fix byte order and alignment") Link: https://patch.msgid.link/20260724124813.3961474-3-nbd@nbd.name Signed-off-by: Felix Fietkau <nbd@nbd.name>
-rw-r--r--drivers/net/wireless/mediatek/mt76/mmio.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mmio.c b/drivers/net/wireless/mediatek/mt76/mmio.c
index 05d74cd7248e..73d47608bf42 100644
--- a/drivers/net/wireless/mediatek/mt76/mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mmio.c
@@ -35,9 +35,16 @@ static void mt76_mmio_write_copy(struct mt76_dev *dev, u32 offset,
{
int i;
- for (i = 0; i < ALIGN(len, 4); i += 4)
+ for (i = 0; i + 4 <= len; i += 4)
writel(get_unaligned_le32(data + i),
dev->mmio.regs + offset + i);
+
+ if (i < len) {
+ u8 tmp[4] = {};
+
+ memcpy(tmp, data + i, len - i);
+ writel(get_unaligned_le32(tmp), dev->mmio.regs + offset + i);
+ }
}
static void mt76_mmio_read_copy(struct mt76_dev *dev, u32 offset,
@@ -45,9 +52,16 @@ static void mt76_mmio_read_copy(struct mt76_dev *dev, u32 offset,
{
int i;
- for (i = 0; i < ALIGN(len, 4); i += 4)
+ for (i = 0; i + 4 <= len; i += 4)
put_unaligned_le32(readl(dev->mmio.regs + offset + i),
data + i);
+
+ if (i < len) {
+ u8 tmp[4];
+
+ put_unaligned_le32(readl(dev->mmio.regs + offset + i), tmp);
+ memcpy(data + i, tmp, len - i);
+ }
}
static int mt76_mmio_wr_rp(struct mt76_dev *dev, u32 base,