mt7601u: watch out for invalid-length frames
authorJakub Kicinski <kubakici@wp.pl>
Tue, 2 Jun 2015 19:11:26 +0000 (21:11 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Mon, 8 Jun 2015 11:28:07 +0000 (14:28 +0300)
Users of older Ralink devices report that received frames
sometimes have zero length.  Watch out for that.

Signed-off-by: Jakub Kicinski <kubakici@wp.pl>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/mediatek/mt7601u/dma.c
drivers/net/wireless/mediatek/mt7601u/mac.c

index 16df67b..7217da4 100644 (file)
@@ -37,16 +37,20 @@ mt7601u_rx_skb_from_seg(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi,
                        void *data, u32 seg_len, u32 truesize, struct page *p)
 {
        struct sk_buff *skb;
-       u32 true_len;
-       int hdr_len, copy, frag;
+       u32 true_len, hdr_len = 0, copy, frag;
 
        skb = alloc_skb(p ? 128 : seg_len, GFP_ATOMIC);
        if (!skb)
                return NULL;
 
        true_len = mt76_mac_process_rx(dev, skb, data, rxwi);
+       if (!true_len || true_len > seg_len)
+               goto bad_frame;
 
        hdr_len = ieee80211_get_hdrlen_from_buf(data, true_len);
+       if (!hdr_len)
+               goto bad_frame;
+
        if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) {
                memcpy(skb_put(skb, hdr_len), data, hdr_len);
 
@@ -69,6 +73,12 @@ mt7601u_rx_skb_from_seg(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi,
        }
 
        return skb;
+
+bad_frame:
+       dev_err_ratelimited(dev->dev, "Error: incorrect frame len:%u hdr:%u\n",
+                           true_len, hdr_len);
+       dev_kfree_skb(skb);
+       return NULL;
 }
 
 static void mt7601u_rx_process_seg(struct mt7601u_dev *dev, u8 *data,
index c161bcc..7514bce 100644 (file)
@@ -450,10 +450,14 @@ u32 mt76_mac_process_rx(struct mt7601u_dev *dev, struct sk_buff *skb,
 {
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
        struct mt7601u_rxwi *rxwi = rxi;
-       u32 ctl = le32_to_cpu(rxwi->ctl);
+       u32 len, ctl = le32_to_cpu(rxwi->ctl);
        u16 rate = le16_to_cpu(rxwi->rate);
        int rssi;
 
+       len = MT76_GET(MT_RXWI_CTL_MPDU_LEN, ctl);
+       if (len < 10)
+               return 0;
+
        if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_DECRYPT)) {
                status->flag |= RX_FLAG_DECRYPTED;
                status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
@@ -474,7 +478,7 @@ u32 mt76_mac_process_rx(struct mt7601u_dev *dev, struct sk_buff *skb,
                dev->avg_rssi = (dev->avg_rssi * 15) / 16 + (rssi << 8);
        spin_unlock_bh(&dev->con_mon_lock);
 
-       return MT76_GET(MT_RXWI_CTL_MPDU_LEN, ctl);
+       return len;
 }
 
 static enum mt76_cipher_type