[PATCH] wifi: p54: validate USB receive prefixes

Pengpeng Hou posted 1 patch 3 weeks, 6 days ago
drivers/net/wireless/intersil/p54/p54usb.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
[PATCH] wifi: p54: validate USB receive prefixes
Posted by Pengpeng Hou 3 weeks, 6 days ago
p54u_rx_cb() strips transport-specific prefixes from a successful USB
receive without checking urb->actual_length. A short transfer can leave
skb_pull() ineffective and pass an unstripped buffer to p54_rx().

Compute the required prefix length and recycle a short receive buffer
before parsing it.

Fixes: eff1a59c48e3 ("[P54]: add mac80211-based driver for prism54 softmac hardware")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
 drivers/net/wireless/intersil/p54/p54usb.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/intersil/p54/p54usb.c b/drivers/net/wireless/intersil/p54/p54usb.c
index b88a3dadddc09..c689b98418ddd 100644
--- a/drivers/net/wireless/intersil/p54/p54usb.c
+++ b/drivers/net/wireless/intersil/p54/p54usb.c
@@ -143,6 +143,7 @@ static void p54u_rx_cb(struct urb *urb)
 	struct p54u_rx_info *info = (struct p54u_rx_info *)skb->cb;
 	struct ieee80211_hw *dev = info->dev;
 	struct p54u_priv *priv = dev->priv;
+	unsigned int prefix_len = 0;
 
 	skb_unlink(skb, &priv->rx_queue);
 
@@ -151,8 +152,18 @@ static void p54u_rx_cb(struct urb *urb)
 		return;
 	}
 
-	skb_put(skb, urb->actual_length);
+	if (priv->hw_type == P54U_NET2280)
+		prefix_len += priv->common.tx_hdr_len;
+	if (priv->common.fw_interface == FW_LM87)
+		prefix_len += 4;
+	if (urb->actual_length < prefix_len) {
+		skb_reset_tail_pointer(skb);
+		skb_trim(skb, 0);
+		urb->transfer_buffer = skb_tail_pointer(skb);
+		goto resubmit;
+	}
 
+	skb_put(skb, urb->actual_length);
 	if (priv->hw_type == P54U_NET2280)
 		skb_pull(skb, priv->common.tx_hdr_len);
 	if (priv->common.fw_interface == FW_LM87) {
@@ -183,6 +194,7 @@ static void p54u_rx_cb(struct urb *urb)
 		skb_trim(skb, 0);
 		urb->transfer_buffer = skb_tail_pointer(skb);
 	}
+resubmit:
 	skb_queue_tail(&priv->rx_queue, skb);
 	usb_anchor_urb(urb, &priv->submitted);
 	if (usb_submit_urb(urb, GFP_ATOMIC)) {

base-commit: 08dbfad3f5040f5bdb6c529da20d6d4e81fefd72
-- 
2.50.1