Re: [PATCH net v3 2/8] net: virtio: do not use dev->type to find the outer L3 header

From
Eric Dumazet <edumazet@kernel.org>
Date
2026-11-06 08:50:51
Also in
sashiko-reviews
Reply to
sashiko-bot@kernel.org, 2026-11-06
Le ven. 6 nov. 2026 à 09:16, [off-list ref] a écrit :
Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [Medium] net: virtio: outer_l3min includes ETH_HLEN in
  virtio_net_hdr_tnl_to_skb()
--

commit b246747b62fc4e9502b5e1a6192ecf203f97d1f4
Author: Eric Dumazet [off-list ref]

net: virtio: do not use dev->type to find the outer L3 header

This commit adds a has_eth parameter to virtio_net_hdr_tnl_to_skb() and
virtio_net_l3_start() so callers specify whether the frame begins with an
Ethernet header instead of relying on skb->dev->type.

Link: https://lore.kernel.org/netdev/179387332014.488856.9111956413610107951@kernel.org/ (local)
quoted
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
index 357116c2a1489..b7b6b542f4763 100644
--- a/include/linux/virtio_net.h
+++ b/include/linux/virtio_net.h
[ ... ]
quoted
@@ -452,6 +450,7 @@ virtio_net_tnl_offsets_ok(struct sk_buff *skb, bool outer_isv6,
 static inline int
 virtio_net_hdr_tnl_to_skb(struct sk_buff *skb,
                        const struct virtio_net_hdr_v1_hash_tunnel *vhdr,
+                       bool has_eth,
                        bool tnl_hdr_negotiated,
                        bool tnl_csum_negotiated,
                        bool little_endian)
@@ -505,7 +504,7 @@ virtio_net_hdr_tnl_to_skb(struct sk_buff *skb,
      if (ret)
              return ret;

-     if (!virtio_net_tnl_offsets_ok(skb, outer_isv6, outer_th))
+     if (!virtio_net_tnl_offsets_ok(skb, has_eth, outer_isv6, outer_th))
              return -EINVAL;
[Severity: Medium]
When tun_get_user() processes an IFF_TUN device, it resets the network header
offset to 0 and calls tun_vnet_hdr_tnl_to_skb() -> virtio_net_hdr_tnl_to_skb()
with has_eth set to false.

However, earlier in virtio_net_hdr_tnl_to_skb(), outer_l3min still
unconditionally includes ETH_HLEN:

        outer_l3min = ETH_HLEN + virtio_l3min(outer_isv6);

        inner_th = __virtio16_to_cpu(little_endian, hdr->csum_start);
        inner_nh = le16_to_cpu(vhdr->inner_nh_offset);
        outer_th = le16_to_cpu(vhdr->outer_th_offset);
        if (outer_th < outer_l3min ||
            inner_nh < outer_th + sizeof(struct udphdr) ||
            inner_th < inner_nh + inner_l3min)
                return -EINVAL;

For an IFF_TUN packet without outer IPv4 options or IPv6 extension headers,
virtio_net_tnl_offsets_ok() -> virtio_net_l3_start() sets nhoff to 0, and
virtio_net_l4_start() computes thoff as 20 (IPv4) or 40 (IPv6), requiring
outer_th == thoff. Because outer_th < outer_l3min rejects outer_th < 34 for
IPv4 or outer_th < 54 for IPv6, won't valid UDP-tunneled GSO packets on
IFF_TUN devices be rejected with -EINVAL unless outer_l3min only adds
ETH_HLEN when has_eth is true?
Yes, but this predates the series: since UDP tunnel GSO support was
added to tun, IFF_TUN frames are only accepted when the outer IP
header is long enough to cover the missing Ethernet header. Willem
pointed this out on v2.

This only rejects packets, it does not crash anything, and changing
it would enable a feature that never worked on IFF_TUN. I will send
that separately to net-next, now that has_eth makes it simple.
Thread (27 messages) 27 messages, 4 authors, last reply 2d ago
Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help