aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2015-02-27 18:35:35 -0800
committerBen Hutchings <ben@decadent.org.uk>2015-05-09 23:16:38 +0100
commit83d51909f235d8a94e9f1491482d334fb82897a3 (patch)
tree79108f3504883a13303c0c270fb7fb20b16194bd /drivers/net
parent75f9b4534aa31e33e96ae36dd96a62907470da91 (diff)
downloadkernel_samsung_smdk4412-83d51909f235d8a94e9f1491482d334fb82897a3.zip
kernel_samsung_smdk4412-83d51909f235d8a94e9f1491482d334fb82897a3.tar.gz
kernel_samsung_smdk4412-83d51909f235d8a94e9f1491482d334fb82897a3.tar.bz2
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 <brak@vultr.com> Tested-by: Brian Rak <brak@vultr.com> Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/macvtap.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 07ca8d3..7300447 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -667,12 +667,15 @@ static unsigned long iov_pages(const struct iovec *iv, int offset,
return pages;
}
+/* 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;
@@ -731,7 +734,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;