lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220418044339.127545-3-liuhangbin@gmail.com>
Date:   Mon, 18 Apr 2022 12:43:39 +0800
From:   Hangbin Liu <liuhangbin@...il.com>
To:     netdev@...r.kernel.org
Cc:     "Michael S . Tsirkin" <mst@...hat.com>,
        Jason Wang <jasowang@...hat.com>,
        "David S . Miller" <davem@...emloft.net>,
        Jakub Kicinski <kuba@...nel.org>,
        Paolo Abeni <pabeni@...hat.com>,
        Maxim Mikityanskiy <maximmi@...lanox.com>,
        Willem de Bruijn <willemb@...gle.com>,
        virtualization@...ts.linux-foundation.org,
        Balazs Nemeth <bnemeth@...hat.com>,
        Mike Pattrick <mailmpattric@...hat.com>,
        Eric Dumazet <edumazet@...gle.com>,
        Hangbin Liu <liuhangbin@...il.com>
Subject: [PATCH net 2/2] virtio_net: check L3 protocol for VLAN packets

For gso packets, virtio_net_hdr_to_skb() will check the protocol via
virtio_net_hdr_match_proto(). But a packet may come from a raw socket
with a VLAN tag. Checking the VLAN protocol for virtio net_hdr makes no
sense. Let's check the L3 protocol if it's a VLAN packet.

Make the virtio_net_hdr_match_proto() checking for all skbs instead of
only skb without protocol setting.

Also update the data, protocol parameter for
skb_flow_dissect_flow_keys_basic() as the skb->protocol may not IP or IPv6.

Fixes: 7e5cced9ca84 ("net: accept UFOv6 packages in virtio_net_hdr_to_skb")
Signed-off-by: Hangbin Liu <liuhangbin@...il.com>
---
 include/linux/virtio_net.h | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
index a960de68ac69..97b4f9680786 100644
--- a/include/linux/virtio_net.h
+++ b/include/linux/virtio_net.h
@@ -3,6 +3,7 @@
 #define _LINUX_VIRTIO_NET_H
 
 #include <linux/if_vlan.h>
+#include <uapi/linux/if_arp.h>
 #include <uapi/linux/tcp.h>
 #include <uapi/linux/udp.h>
 #include <uapi/linux/virtio_net.h>
@@ -102,25 +103,36 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
 		 */
 		if (gso_type && skb->network_header) {
 			struct flow_keys_basic keys;
+			__be16 protocol;
 
 			if (!skb->protocol) {
-				__be16 protocol = dev_parse_header_protocol(skb);
+				protocol = dev_parse_header_protocol(skb);
 
 				if (!protocol)
 					virtio_net_hdr_set_proto(skb, hdr);
-				else if (!virtio_net_hdr_match_proto(protocol, hdr->gso_type))
-					return -EINVAL;
 				else
 					skb->protocol = protocol;
+			} else {
+				protocol = skb->protocol;
 			}
+
+			/* Get L3 protocol if current protocol is VLAN */
+			if (likely(skb->dev->type == ARPHRD_ETHER) &&
+			    eth_type_vlan(protocol))
+				protocol = vlan_get_protocol(skb);
+
+			if (!virtio_net_hdr_match_proto(protocol, hdr->gso_type))
+				return -EINVAL;
+
 retry:
 			if (!skb_flow_dissect_flow_keys_basic(NULL, skb, &keys,
-							      NULL, 0, 0, 0,
-							      0)) {
+							      skb->data, protocol,
+							      skb_network_offset(skb),
+							      skb_headlen(skb), 0)) {
 				/* UFO does not specify ipv4 or 6: try both */
 				if (gso_type & SKB_GSO_UDP &&
-				    skb->protocol == htons(ETH_P_IP)) {
-					skb->protocol = htons(ETH_P_IPV6);
+				    protocol == htons(ETH_P_IP)) {
+					protocol = htons(ETH_P_IPV6);
 					goto retry;
 				}
 				return -EINVAL;
-- 
2.35.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ