wifi: mt76: mt7996: bound EEPROM access event before copying

mt7996_mcu_get_eeprom() copied the event->eeprom payload out of the
firmware response skb without checking that the response actually held
the bytes being read. A short or malformed response could read past the
end of the skb. Reject a response shorter than the event header and bound
each copy to the payload present in the skb.

Fixes: 0da2e410705e ("wifi: mt76: mt7996: extend flexibility of mt7996_mcu_get_eeprom()")
Signed-off-by: Felix Fietkau <[email protected]>
This commit is contained in:
Felix Fietkau
2026-08-01 17:46:20 +02:00
parent d170cb14b9
commit 591568f4e6
+16 -2
View File
@@ -4596,6 +4596,11 @@ int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_l
return ret;
event = (struct mt7996_mcu_eeprom_access_event *)skb->data;
if (skb->len < sizeof(*event)) {
dev_kfree_skb(skb);
return -EINVAL;
}
if (event->valid) {
u32 ret_len = le32_to_cpu(event->eeprom.ext_eeprom.data_len);
u32 block = mode == EEPROM_MODE_EXT ? MT7996_EXT_EEPROM_BLOCK_SIZE :
@@ -4616,14 +4621,23 @@ int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_l
if (!buf_len || buf_len > MT7996_EEPROM_BLOCK_SIZE)
buf_len = MT7996_EEPROM_BLOCK_SIZE;
if (event->eeprom.efuse + buf_len > skb->data + skb->len) {
ret = -EINVAL;
break;
}
memcpy(buf, event->eeprom.efuse, buf_len);
break;
case EEPROM_MODE_EXT:
if (!buf_len || buf_len > MT7996_EXT_EEPROM_BLOCK_SIZE)
buf_len = MT7996_EXT_EEPROM_BLOCK_SIZE;
if (ret_len < buf_len)
buf_len = ret_len;
memcpy(buf, event->eeprom.ext_eeprom.data,
ret_len < buf_len ? ret_len : buf_len);
if (event->eeprom.ext_eeprom.data + buf_len > skb->data + skb->len) {
ret = -EINVAL;
break;
}
memcpy(buf, event->eeprom.ext_eeprom.data, buf_len);
break;
default:
ret = -EINVAL;