# 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 
- List: virtualization
- Page: https://ratatoskr.run/virtualization/2026/11/17876704
- Thread: https://ratatoskr.run/sashiko-reviews/2026/11/17876704/t.md

```text
Le ven. 6 nov. 2026 à 09:16, [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 [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/
>
> > 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
>
> [ ... ]
>
> > @@ -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.
```
