brcmfmac: cleanup netdev transmit callback
authorArend van Spriel <arend@broadcom.com>
Wed, 2 Jan 2013 14:22:46 +0000 (15:22 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 7 Jan 2013 20:16:57 +0000 (15:16 -0500)
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>
drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c

index a1ca691..9ca7411 100644 (file)
@@ -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);