mirror of
https://github.com/outbackdingo/mt76.git
synced 2026-10-24 13:26:48 +00:00
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:
+5
-5
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user