]>
Commit | Line | Data |
---|---|---|
373f9370 GKH |
1 | From foo@baz Wed Mar 11 11:44:33 CET 2015 |
2 | From: Eric Dumazet <edumazet@google.com> | |
3 | Date: Fri, 27 Feb 2015 18:35:35 -0800 | |
4 | Subject: macvtap: make sure neighbour code can push ethernet header | |
5 | ||
6 | From: Eric Dumazet <edumazet@google.com> | |
7 | ||
8 | [ Upstream commit 2f1d8b9e8afa5a833d96afcd23abcb8cdf8d83ab ] | |
9 | ||
10 | Brian reported crashes using IPv6 traffic with macvtap/veth combo. | |
11 | ||
12 | I tracked the crashes in neigh_hh_output() | |
13 | ||
14 | -> memcpy(skb->data - HH_DATA_MOD, hh->hh_data, HH_DATA_MOD); | |
15 | ||
16 | Neighbour code assumes headroom to push Ethernet header is | |
17 | at least 16 bytes. | |
18 | ||
19 | It appears macvtap has only 14 bytes available on arches | |
20 | where NET_IP_ALIGN is 0 (like x86) | |
21 | ||
22 | Effect is a corruption of 2 bytes right before skb->head, | |
23 | and possible crashes if accessing non existing memory. | |
24 | ||
25 | This fix should also increase IPv4 performance, as paranoid code | |
26 | in ip_finish_output2() wont have to call skb_realloc_headroom() | |
27 | ||
28 | Reported-by: Brian Rak <brak@vultr.com> | |
29 | Tested-by: Brian Rak <brak@vultr.com> | |
30 | Signed-off-by: Eric Dumazet <edumazet@google.com> | |
31 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
32 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
33 | --- | |
34 | drivers/net/macvtap.c | 7 +++++-- | |
35 | 1 file changed, 5 insertions(+), 2 deletions(-) | |
36 | ||
37 | --- a/drivers/net/macvtap.c | |
38 | +++ b/drivers/net/macvtap.c | |
39 | @@ -654,11 +654,14 @@ static void macvtap_skb_to_vnet_hdr(stru | |
40 | } /* else everything is zero */ | |
41 | } | |
42 | ||
43 | +/* Neighbour code has some assumptions on HH_DATA_MOD alignment */ | |
44 | +#define MACVTAP_RESERVE HH_DATA_OFF(ETH_HLEN) | |
45 | + | |
46 | /* Get packet from user space buffer */ | |
47 | static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, | |
48 | struct iov_iter *from, int noblock) | |
49 | { | |
50 | - int good_linear = SKB_MAX_HEAD(NET_IP_ALIGN); | |
51 | + int good_linear = SKB_MAX_HEAD(MACVTAP_RESERVE); | |
52 | struct sk_buff *skb; | |
53 | struct macvlan_dev *vlan; | |
54 | unsigned long total_len = iov_iter_count(from); | |
55 | @@ -722,7 +725,7 @@ static ssize_t macvtap_get_user(struct m | |
56 | linear = macvtap16_to_cpu(q, vnet_hdr.hdr_len); | |
57 | } | |
58 | ||
59 | - skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, copylen, | |
60 | + skb = macvtap_alloc_skb(&q->sk, MACVTAP_RESERVE, copylen, | |
61 | linear, noblock, &err); | |
62 | if (!skb) | |
63 | goto err; |