diff options
| author | Pengpeng Hou <pengpeng@iscas.ac.cn> | 2026-08-30 21:10:49 +0800 |
|---|---|---|
| committer | Felix Fietkau <nbd@nbd.name> | 2026-10-07 12:50:42 +0200 |
| commit | 356735fc612ea54062eb741ea15fa4ff7df4fc36 (patch) | |
| tree | 0e3ed03671125daf28a6ef029b84ffaec1c99faa /drivers/net/wireless | |
| parent | 8d604c899f7bd1a76a2eb21c0b706c02878abd36 (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.c | 11 |
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); |
