[<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