summaryrefslogtreecommitdiff
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorPengpeng Hou <pengpeng@iscas.ac.cn>2026-08-30 21:10:49 +0800
committerFelix Fietkau <nbd@nbd.name>2026-10-07 12:50:42 +0200
commit356735fc612ea54062eb741ea15fa4ff7df4fc36 (patch)
tree0e3ed03671125daf28a6ef029b84ffaec1c99faa /drivers/net/wireless
parent8d604c899f7bd1a76a2eb21c0b706c02878abd36 (diff)
wifi: mt76: mt7615: validate MCU response lengths
mt7615_mcu_parse_response() reads the common response header before checking its size and then consumes command-specific fields after unchecked skb_pull() calls. A short firmware response can therefore be read beyond its current extent. Validate the common header and each command-specific payload before reading it. Fixes: 0e6a29e477f3 ("mt76: mt7615: add support to read temperature from mcu") Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn> Link: https://patch.msgid.link/20260830131049.2097-1-pengpeng@iscas.ac.cn Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/mcu.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
index 1ce0192c2c91..aab4303fef65 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
@@ -145,6 +145,9 @@ int mt7615_mcu_parse_response(struct mt76_dev *mdev, int cmd,
}
rxd = (struct mt7615_mcu_rxd *)skb->data;
+ if (skb->len < sizeof(*rxd))
+ return -EMSGSIZE;
+
if (seq != rxd->seq)
return -EAGAIN;
@@ -152,11 +155,15 @@ int mt7615_mcu_parse_response(struct mt76_dev *mdev, int cmd,
skb_pull(skb, sizeof(*rxd) - 4);
ret = *skb->data;
} else if (cmd == MCU_EXT_CMD(THERMAL_CTRL)) {
+ if (skb->len < sizeof(*rxd) + (is_mt7663(mdev) ? 8 : 4))
+ return -EMSGSIZE;
skb_pull(skb, sizeof(*rxd));
if (is_mt7663(mdev))
skb_pull(skb, 4);
ret = le32_to_cpu(*(__le32 *)skb->data);
} else if (cmd == MCU_EXT_QUERY(RF_REG_ACCESS)) {
+ if (skb->len < sizeof(*rxd) + 8 + sizeof(__le32))
+ return -EMSGSIZE;
skb_pull(skb, sizeof(*rxd));
ret = le32_to_cpu(*(__le32 *)&skb->data[8]);
} else if (cmd == MCU_UNI_CMD(DEV_INFO_UPDATE) ||
@@ -167,12 +174,16 @@ int mt7615_mcu_parse_response(struct mt76_dev *mdev, int cmd,
cmd == MCU_UNI_CMD(SUSPEND)) {
struct mt76_connac_mcu_uni_event *event;
+ if (skb->len < sizeof(*rxd) + sizeof(*event))
+ return -EMSGSIZE;
skb_pull(skb, sizeof(*rxd));
event = (struct mt76_connac_mcu_uni_event *)skb->data;
ret = le32_to_cpu(event->status);
} else if (cmd == MCU_CE_QUERY(REG_READ)) {
struct mt76_connac_mcu_reg_event *event;
+ if (skb->len < sizeof(*rxd) + sizeof(*event))
+ return -EMSGSIZE;
skb_pull(skb, sizeof(*rxd));
event = (struct mt76_connac_mcu_reg_event *)skb->data;
ret = (int)le32_to_cpu(event->val);