wifi: mt76: mt7925: fix infinite loop in UNI event TLV parsing

The event TLV loops accept a zero-length TLV, which advances neither the
cursor nor the remaining length, so a malformed event hangs the caller.
mt7925_mcu_uni_roc_event() additionally walked past the end of the skb,
since it never checked the declared length against the remainder.

Replace the five open-coded loops with a shared iterator that rejects
lengths below the TLV header and beyond the remaining buffer, and check
the per-tag payload sizes before dereferencing them.

While here, make the RSSI monitor event read from the current TLV rather
than from the start of the list.

Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
This commit is contained in:
Felix Fietkau
2026-08-25 11:42:57 +02:00
parent 435eb72693
commit f701fad5c0
3 changed files with 46 additions and 21 deletions
+5 -5
View File
@@ -1579,7 +1579,7 @@ void mt7925_scan_work(struct work_struct *work)
while (true) {
struct sk_buff *skb;
struct tlv *tlv;
int tlv_len;
u32 tlv_len;
spin_lock_bh(&phy->dev->mt76.lock);
skb = __skb_dequeue(&phy->scan_event_list);
@@ -1592,7 +1592,7 @@ void mt7925_scan_work(struct work_struct *work)
tlv = (struct tlv *)skb->data;
tlv_len = skb->len;
while (tlv_len > 0 && le16_to_cpu(tlv->len) <= tlv_len) {
mt7925_for_each_tlv(tlv, tlv_len) {
struct mt7925_mcu_scan_chinfo_event *evt;
switch (le16_to_cpu(tlv->tag)) {
@@ -1605,6 +1605,9 @@ void mt7925_scan_work(struct work_struct *work)
}
break;
case UNI_EVENT_SCAN_DONE_CHNLINFO:
if (le16_to_cpu(tlv->len) < sizeof(*tlv) + sizeof(*evt))
break;
evt = (struct mt7925_mcu_scan_chinfo_event *)tlv->data;
mt7925_regd_change(phy, evt->alpha2);
@@ -1616,9 +1619,6 @@ void mt7925_scan_work(struct work_struct *work)
default:
break;
}
tlv_len -= le16_to_cpu(tlv->len);
tlv = (struct tlv *)((char *)(tlv) + le16_to_cpu(tlv->len));
}
dev_kfree_skb(skb);