[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <03ee62602dd7b7101f78e0802249a6e2e4c10b7f.camel@infradead.org>
Date: Sat, 19 Jun 2021 14:33:04 +0100
From: David Woodhouse <dwmw2@...radead.org>
To: netdev <netdev@...r.kernel.org>
Cc: Jason Wang <jasowang@...hat.com>
Subject: [PATCH] net: tun: fix tun_xdp_one() for IFF_TUN mode
From: David Woodhouse <dwmw@...zon.co.uk>
In tun_get_user(), skb->protocol is either taken from the tun_pi header
or inferred from the first byte of the packet in IFF_TUN mode, while
eth_type_trans() is called only in the IFF_TAP mode where the payload
is expected to be an Ethernet frame.
The alternative path in tun_xdp_one() was unconditionally using
eth_type_trans(), which corrupts packets in IFF_TUN mode. Fix it to
do the correct thing for IFF_TUN mode, as tun_get_user() does.
Signed-off-by: David Woodhouse <dwmw@...zon.co.uk>
Fixes: 043d222f93ab ("tuntap: accept an array of XDP buffs through sendmsg()")
---
How is my userspace application going to know that the kernel has this
fix? Should we add a flag to TUN_FEATURES to show that vhost-net in
*IFF_TUN* mode is supported?
drivers/net/tun.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 43 insertions(+), 1 deletion(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 4cf38be26dc9..f812dcdc640e 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -2394,8 +2394,50 @@ static int tun_xdp_one(struct tun_struct *tun,
err = -EINVAL;
goto out;
}
+ switch (tun->flags & TUN_TYPE_MASK) {
+ case IFF_TUN:
+ if (tun->flags & IFF_NO_PI) {
+ u8 ip_version = skb->len ? (skb->data[0] >> 4) : 0;
+
+ switch (ip_version) {
+ case 4:
+ skb->protocol = htons(ETH_P_IP);
+ break;
+ case 6:
+ skb->protocol = htons(ETH_P_IPV6);
+ break;
+ default:
+ atomic_long_inc(&tun->dev->rx_dropped);
+ kfree_skb(skb);
+ err = -EINVAL;
+ goto out;
+ }
+ } else {
+ struct tun_pi *pi = (struct tun_pi *)skb->data;
+ if (!pskb_may_pull(skb, sizeof(*pi))) {
+ atomic_long_inc(&tun->dev->rx_dropped);
+ kfree_skb(skb);
+ err = -ENOMEM;
+ goto out;
+ }
+ skb_pull_inline(skb, sizeof(*pi));
+ skb->protocol = pi->proto;
+ }
+
+ skb_reset_mac_header(skb);
+ skb->dev = tun->dev;
+ break;
+ case IFF_TAP:
+ if (!pskb_may_pull(skb, ETH_HLEN)) {
+ atomic_long_inc(&tun->dev->rx_dropped);
+ kfree_skb(skb);
+ err = -ENOMEM;
+ goto out;
+ }
+ skb->protocol = eth_type_trans(skb, tun->dev);
+ break;
+ }
- skb->protocol = eth_type_trans(skb, tun->dev);
skb_reset_network_header(skb);
skb_probe_transport_header(skb);
skb_record_rx_queue(skb, tfile->queue_index);
--
2.31.1
Download attachment "smime.p7s" of type "application/x-pkcs7-signature" (5174 bytes)
Powered by blists - more mailing lists