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

Commit 52a9692a authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'vlan-fix'

Toshiaki Makita says:

====================
Fix vlan tag handling for vlan packets without ethernet headers

Eric Dumazet reported syzbot found a new bug which leads to underflow of
size argument of memmove(), causing crash[1]. This can be triggered by tun
devices.

The underflow happened because skb_vlan_untag() did not expect vlan packets
without ethernet headers, and tun can produce such packets.
I also checked vlan_insert_inner_tag() and found a similar bug.

This series fixes these problems.

[1] https://marc.info/?l=linux-netdev&m=152221753920510&w=2


====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a9645b27 c769accd
Loading
Loading
Loading
Loading
+13 −2
Original line number Diff line number Diff line
@@ -323,13 +323,24 @@ static inline int __vlan_insert_inner_tag(struct sk_buff *skb,
	skb_push(skb, VLAN_HLEN);

	/* Move the mac header sans proto to the beginning of the new header. */
	if (likely(mac_len > ETH_TLEN))
		memmove(skb->data, skb->data + VLAN_HLEN, mac_len - ETH_TLEN);
	skb->mac_header -= VLAN_HLEN;

	veth = (struct vlan_ethhdr *)(skb->data + mac_len - ETH_HLEN);

	/* first, the ethernet type */
	if (likely(mac_len >= ETH_TLEN)) {
		/* h_vlan_encapsulated_proto should already be populated, and
		 * skb->data has space for h_vlan_proto
		 */
		veth->h_vlan_proto = vlan_proto;
	} else {
		/* h_vlan_encapsulated_proto should not be populated, and
		 * skb->data has no space for h_vlan_proto
		 */
		veth->h_vlan_encapsulated_proto = skb->protocol;
	}

	/* now, the TCI */
	veth->h_vlan_TCI = htons(vlan_tci);
+4 −2
Original line number Diff line number Diff line
@@ -5028,8 +5028,10 @@ static struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb)
	}

	mac_len = skb->data - skb_mac_header(skb);
	if (likely(mac_len > VLAN_HLEN + ETH_TLEN)) {
		memmove(skb_mac_header(skb) + VLAN_HLEN, skb_mac_header(skb),
			mac_len - VLAN_HLEN - ETH_TLEN);
	}
	skb->mac_header += VLAN_HLEN;
	return skb;
}