From: Eric Dumazet Date: Sat, 28 Feb 2015 02:35:35 +0000 (-0800) Subject: macvtap: make sure neighbour code can push ethernet header X-Git-Tag: v3.12.39~90 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2b6de7d31c8dab3c4e2b0c0883fb19d27ce73ebb;p=people%2Fms%2Flinux.git macvtap: make sure neighbour code can push ethernet header [ Upstream commit 2f1d8b9e8afa5a833d96afcd23abcb8cdf8d83ab ] Brian reported crashes using IPv6 traffic with macvtap/veth combo. I tracked the crashes in neigh_hh_output() -> memcpy(skb->data - HH_DATA_MOD, hh->hh_data, HH_DATA_MOD); Neighbour code assumes headroom to push Ethernet header is at least 16 bytes. It appears macvtap has only 14 bytes available on arches where NET_IP_ALIGN is 0 (like x86) Effect is a corruption of 2 bytes right before skb->head, and possible crashes if accessing non existing memory. This fix should also increase IPv4 performance, as paranoid code in ip_finish_output2() wont have to call skb_realloc_headroom() Reported-by: Brian Rak Tested-by: Brian Rak Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Jiri Slaby --- diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 89d21fc47a16..393873fb792e 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -635,12 +635,15 @@ static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb, return 0; } +/* Neighbour code has some assumptions on HH_DATA_MOD alignment */ +#define MACVTAP_RESERVE HH_DATA_OFF(ETH_HLEN) + /* Get packet from user space buffer */ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, const struct iovec *iv, unsigned long total_len, size_t count, int noblock) { - int good_linear = SKB_MAX_HEAD(NET_IP_ALIGN); + int good_linear = SKB_MAX_HEAD(MACVTAP_RESERVE); struct sk_buff *skb; struct macvlan_dev *vlan; unsigned long len = total_len; @@ -699,7 +702,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, linear = vnet_hdr.hdr_len; } - skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, copylen, + skb = macvtap_alloc_skb(&q->sk, MACVTAP_RESERVE, copylen, linear, noblock, &err); if (!skb) goto err;