Commit 044453b3 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

arp: fix possible crash in arp_rcv()

We should call skb_share_check() before pskb_may_pull(), or we
can crash in pskb_expand_head()
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 839c8cc3
...@@ -928,24 +928,25 @@ static void parp_redo(struct sk_buff *skb) ...@@ -928,24 +928,25 @@ static void parp_redo(struct sk_buff *skb)
static int arp_rcv(struct sk_buff *skb, struct net_device *dev, static int arp_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev) struct packet_type *pt, struct net_device *orig_dev)
{ {
struct arphdr *arp; const struct arphdr *arp;
if (dev->flags & IFF_NOARP ||
skb->pkt_type == PACKET_OTHERHOST ||
skb->pkt_type == PACKET_LOOPBACK)
goto freeskb;
skb = skb_share_check(skb, GFP_ATOMIC);
if (!skb)
goto out_of_mem;
/* ARP header, plus 2 device addresses, plus 2 IP addresses. */ /* ARP header, plus 2 device addresses, plus 2 IP addresses. */
if (!pskb_may_pull(skb, arp_hdr_len(dev))) if (!pskb_may_pull(skb, arp_hdr_len(dev)))
goto freeskb; goto freeskb;
arp = arp_hdr(skb); arp = arp_hdr(skb);
if (arp->ar_hln != dev->addr_len || if (arp->ar_hln != dev->addr_len || arp->ar_pln != 4)
dev->flags & IFF_NOARP ||
skb->pkt_type == PACKET_OTHERHOST ||
skb->pkt_type == PACKET_LOOPBACK ||
arp->ar_pln != 4)
goto freeskb; goto freeskb;
skb = skb_share_check(skb, GFP_ATOMIC);
if (skb == NULL)
goto out_of_mem;
memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb)); memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));
return NF_HOOK(NFPROTO_ARP, NF_ARP_IN, skb, dev, NULL, arp_process); return NF_HOOK(NFPROTO_ARP, NF_ARP_IN, skb, dev, NULL, arp_process);
......
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