The debug message event handler removes the event prefix and accesses the message header without checking the skb length. It also subtracts the fixed header from the firmware-provided length without checking for an underflow and trusts the string length. A truncated event can therefore cause out-of-bounds reads while formatting firmware logs. Validate the event prefix, fixed fields, declared message extent and each format-specific payload before reading them. Fixes: c948b5da6bbe ("wifi: mt76: mt7925: add Mediatek Wi-Fi7 driver for mt7925 chips") Cc: stable@vger.kernel.org Signed-off-by: Jiale Yao --- .../net/wireless/mediatek/mt76/mt7925/mcu.c | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c index 26cdb3f0a98a..c612fda55eb7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c @@ -596,8 +596,14 @@ mt7925_mcu_uni_debug_msg_event(struct mt792x_dev *dev, struct sk_buff *skb) } __packed txt; }; } __packed * hdr; + u16 msg_len; + if (skb->len < sizeof(struct mt7925_mcu_rxd) + 4) + return; skb_pull(skb, sizeof(struct mt7925_mcu_rxd) + 4); + if (skb->len < offsetof(struct mt7925_uni_debug_msg, idx)) + return; + hdr = (struct mt7925_uni_debug_msg *)skb->data; if (hdr->id == 0x28) { @@ -608,19 +614,28 @@ mt7925_mcu_uni_debug_msg_event(struct mt792x_dev *dev, struct sk_buff *skb) return; } + msg_len = le16_to_cpu(hdr->len); + if (msg_len < offsetof(struct mt7925_uni_debug_msg, idx) || + msg_len > skb->len) + return; + if (hdr->type == 0) { /* idx log */ int i, ret, len = PAGE_SIZE - 1, nr_val; - struct page *page = dev_alloc_pages(get_order(len)); + struct page *page; __le32 *val; char *buf, *cur; + if (msg_len < sizeof(*hdr)) + return; + + page = dev_alloc_pages(get_order(len)); if (!page) return; buf = page_address(page); cur = buf; - nr_val = (le16_to_cpu(hdr->len) - sizeof(*hdr)) / 4; + nr_val = (msg_len - sizeof(*hdr)) / sizeof(*val); val = (__le32 *)hdr->idx.data; for (i = 0; i < nr_val && len > 0; i++) { ret = snprintf(cur, len, "0x%x,", le32_to_cpu(val[i])); @@ -635,6 +650,11 @@ mt7925_mcu_uni_debug_msg_event(struct mt792x_dev *dev, struct sk_buff *skb) le32_to_cpu(hdr->idx.idx), nr_val, buf); put_page(page); } else if (hdr->type == 2) { /* str log */ + if (msg_len < offsetof(struct mt7925_uni_debug_msg, txt.data) || + hdr->txt.len > msg_len - offsetof(struct mt7925_uni_debug_msg, + txt.data)) + return; + wiphy_info(mt76_hw(dev)->wiphy, "%.*s", hdr->txt.len, hdr->txt.data); } } -- 2.34.1