Browse Source

brcmfmac: cleanup netdev transmit callback

The header of the ethernet packet is processed conditionally, but
the check is wrong as it checks skb length is at least ETH_ALEN. It
should check it is at least sizeof struct ethhdr instead.

Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Arend van Spriel 12 years ago
parent
commit
12b33dacb4
1 changed files with 13 additions and 9 deletions
  1. 13 9
      drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c

+ 13 - 9
drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c

@@ -165,6 +165,7 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 	int ret;
 	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct brcmf_pub *drvr = ifp->drvr;
+	struct ethhdr *eh;
 
 	brcmf_dbg(TRACE, "Enter\n");
 
@@ -202,17 +203,20 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 		}
 	}
 
-	/* Update multicast statistic */
-	if (skb->len >= ETH_ALEN) {
-		u8 *pktdata = (u8 *)(skb->data);
-		struct ethhdr *eh = (struct ethhdr *)pktdata;
-
-		if (is_multicast_ether_addr(eh->h_dest))
-			drvr->tx_multicast++;
-		if (ntohs(eh->h_proto) == ETH_P_PAE)
-			atomic_inc(&drvr->pend_8021x_cnt);
+	/* validate length for ether packet */
+	if (skb->len < sizeof(*eh)) {
+		ret = -EINVAL;
+		dev_kfree_skb(skb);
+		goto done;
 	}
 
+	/* handle ethernet header */
+	eh = (struct ethhdr *)(skb->data);
+	if (is_multicast_ether_addr(eh->h_dest))
+		drvr->tx_multicast++;
+	if (ntohs(eh->h_proto) == ETH_P_PAE)
+		atomic_inc(&drvr->pend_8021x_cnt);
+
 	/* If the protocol uses a data header, apply it */
 	brcmf_proto_hdrpush(drvr, ifp->idx, skb);