Commit 2af6d21f authored by Jakub Kicinski's avatar Jakub Kicinski Committed by Kalle Valo

mt7601u: watch out for invalid-length frames

Users of older Ralink devices report that received frames
sometimes have zero length.  Watch out for that.
Signed-off-by: default avatarJakub Kicinski <kubakici@wp.pl>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 69647fab
...@@ -37,16 +37,20 @@ mt7601u_rx_skb_from_seg(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi, ...@@ -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) void *data, u32 seg_len, u32 truesize, struct page *p)
{ {
struct sk_buff *skb; struct sk_buff *skb;
u32 true_len; u32 true_len, hdr_len = 0, copy, frag;
int hdr_len, copy, frag;
skb = alloc_skb(p ? 128 : seg_len, GFP_ATOMIC); skb = alloc_skb(p ? 128 : seg_len, GFP_ATOMIC);
if (!skb) if (!skb)
return NULL; return NULL;
true_len = mt76_mac_process_rx(dev, skb, data, rxwi); 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); 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)) { if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) {
memcpy(skb_put(skb, hdr_len), data, hdr_len); 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, ...@@ -69,6 +73,12 @@ mt7601u_rx_skb_from_seg(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi,
} }
return skb; 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, static void mt7601u_rx_process_seg(struct mt7601u_dev *dev, u8 *data,
......
...@@ -450,10 +450,14 @@ u32 mt76_mac_process_rx(struct mt7601u_dev *dev, struct sk_buff *skb, ...@@ -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 ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct mt7601u_rxwi *rxwi = rxi; 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); u16 rate = le16_to_cpu(rxwi->rate);
int rssi; 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)) { if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_DECRYPT)) {
status->flag |= RX_FLAG_DECRYPTED; status->flag |= RX_FLAG_DECRYPTED;
status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; 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, ...@@ -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); dev->avg_rssi = (dev->avg_rssi * 15) / 16 + (rssi << 8);
spin_unlock_bh(&dev->con_mon_lock); spin_unlock_bh(&dev->con_mon_lock);
return MT76_GET(MT_RXWI_CTL_MPDU_LEN, ctl); return len;
} }
static enum mt76_cipher_type static enum mt76_cipher_type
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment