Skip to contentSkip to conversation

Patch "packet: only allow extra vlan len on ethernet devices" has been added to the 4.2-stable tree

PATCH [email protected] 1 participant 1 message Dec 11, 2015

Subsystems (3)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

packet: only allow extra vlan len on ethernet devices

to the 4.2-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
packet-only-allow-extra-vlan-len-on-ethernet-devices.patch
and it can be found in the queue-4.2 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From foo@baz Fri Dec 11 11:38:35 EST 2015

From: Daniel Borkmann <[email protected]>
Date: Wed, 11 Nov 2015 23:25:42 +0100
Subject: packet: only allow extra vlan len on ethernet devices

From: Daniel Borkmann <[email protected]>

[ Upstream commit 3c70c132488794e2489ab045559b0ce0afcf17de ]

Packet sockets can be used by various net devices and are not really restricted to ARPHRD_ETHER device types. However, when currently checking for the extra 4 bytes that can be transmitted in VLAN case, our assumption is that we generally probe on ARPHRD_ETHER devices. Therefore, before looking into Ethernet header, check the device type first.

This also fixes the issue where non-ARPHRD_ETHER devices could have no dev->hard_header_len in TX_RING SOCK_RAW case, and thus the check would test unfilled linear part of the skb (instead of non-linear).

Fixes 57f89bfa2140 ("network: Allow af_packet to transmit +4 bytes for VLAN packets.")
Fixes 52f1454f629f ("packet: allow to transmit +4 byte in TX_RING slot for VLAN case")
---
 net/packet/af_packet.c |   60 ++++++++++++++++++++-----------------------------
 1 file changed, 25 insertions(+), 35 deletions(-)
net/packet/af_packet.c +25 -35
@@ -1622,6 +1622,20 @@ static void fanout_release(struct sock *
 		kfree_rcu(po->rollover, rcu);
 }
 
+static bool packet_extra_vlan_len_allowed(const struct net_device *dev,
+					  struct sk_buff *skb)
+{
+	/* Earlier code assumed this would be a VLAN pkt, double-check
+	 * this now that we have the actual packet in hand. We can only
+	 * do this check on Ethernet devices.
+	 */
+	if (unlikely(dev->type != ARPHRD_ETHER))
+		return false;
+
+	skb_reset_mac_header(skb);
+	return likely(eth_hdr(skb)->h_proto == htons(ETH_P_8021Q));
+}
+
 static const struct proto_ops packet_ops;
 
 static const struct proto_ops packet_ops_spkt;
@@ -1783,18 +1797,10 @@ retry:
 		goto retry;
 	}
 
-	if (len > (dev->mtu + dev->hard_header_len + extra_len)) {
-		/* Earlier code assumed this would be a VLAN pkt,
-		 * double-check this now that we have the actual
-		 * packet in hand.
-		 */
-		struct ethhdr *ehdr;
-		skb_reset_mac_header(skb);
-		ehdr = eth_hdr(skb);
-		if (ehdr->h_proto != htons(ETH_P_8021Q)) {
-			err = -EMSGSIZE;
-			goto out_unlock;
-		}
+	if (len > (dev->mtu + dev->hard_header_len + extra_len) &&
+	    !packet_extra_vlan_len_allowed(dev, skb)) {
+		err = -EMSGSIZE;
+		goto out_unlock;
 	}
 
 	skb->protocol = proto;
@@ -2406,18 +2412,10 @@ static int tpacket_snd(struct packet_soc
 		tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto,
 					  addr, hlen);
 		if (likely(tp_len >= 0) &&
-		    tp_len > dev->mtu + dev->hard_header_len) {
-			struct ethhdr *ehdr;
-			/* Earlier code assumed this would be a VLAN pkt,
-			 * double-check this now that we have the actual
-			 * packet in hand.
-			 */
+		    tp_len > dev->mtu + dev->hard_header_len &&
+		    !packet_extra_vlan_len_allowed(dev, skb))
+			tp_len = -EMSGSIZE;
 
-			skb_reset_mac_header(skb);
-			ehdr = eth_hdr(skb);
-			if (ehdr->h_proto != htons(ETH_P_8021Q))
-				tp_len = -EMSGSIZE;
-		}
 		if (unlikely(tp_len < 0)) {
 			if (po->tp_loss) {
 				__packet_set_status(po, ph,
@@ -2638,18 +2636,10 @@ static int packet_snd(struct socket *soc
 
 	sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags);
 
-	if (!gso_type && (len > dev->mtu + reserve + extra_len)) {
-		/* Earlier code assumed this would be a VLAN pkt,
-		 * double-check this now that we have the actual
-		 * packet in hand.
-		 */
-		struct ethhdr *ehdr;
-		skb_reset_mac_header(skb);
-		ehdr = eth_hdr(skb);
-		if (ehdr->h_proto != htons(ETH_P_8021Q)) {
-			err = -EMSGSIZE;
-			goto out_free;
-		}
+	if (!gso_type && (len > dev->mtu + reserve + extra_len) &&
+	    !packet_extra_vlan_len_allowed(dev, skb)) {
+		err = -EMSGSIZE;
+		goto out_free;
 	}
 
 	skb->protocol = proto;

Patches currently in stable-queue which might be from [email protected] are

queue-4.2/packet-infer-protocol-from-ethernet-header-if-unset.patch queue-4.2/bpf-array-fix-heap-out-of-bounds-access-when-updating-elements.patch queue-4.2/ipv6-sctp-implement-sctp_v6_destroy_sock.patch queue-4.2/packet-only-allow-extra-vlan-len-on-ethernet-devices.patch queue-4.2/net-scm-fix-pax-detected-msg_controllen-overflow-in-scm_detach_fds.patch queue-4.2/packet-fix-tpacket_snd-max-frame-len.patch queue-4.2/packet-always-probe-for-transport-header.patch queue-4.2/packet-do-skb_probe_transport_header-when-we-actually-have-data.patch queue-4.2/tools-net-use-include-uapi-with-__exported_headers__.patch