Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e2aaa2c0 authored by Eric Dumazet's avatar Eric Dumazet Committed by Sasha Levin
Browse files

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: default avatarBrian Rak <brak@vultr.com>
Tested-by: default avatarBrian Rak <brak@vultr.com>
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSasha Levin <sasha.levin@oracle.com>
parent 7c03ec3e
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -637,12 +637,15 @@ static void macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
	} /* else everything is zero */
}

/* 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;
@@ -701,7 +704,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;