From: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
To: netdev-bot+sashiko@kernel.org, willemdebruijn.kernel@gmail.com
Cc: netdev@vger.kernel.org, davem@davemloft.net, kuba@kernel.org,
edumazet@google.com, pabeni@redhat.com, horms@kernel.org,
andrew+netdev@lunn.ch, xietangxin@yeah.net,
willemb@google.com, stable@vger.kernel.org
Subject: Re: [PATCH net] net: extend IPv6 exthdr detection of tunneled packets
Date: Fri, 25 Sep 2026 22:06:29 -0400 [thread overview]
Message-ID: <willemdebruijn.kernel.386226098beef@gmail.com> (raw)
In-Reply-To: <179036410829.2160803.1955366625960078958@kernel.org>
netdev-bot+sashiko@ wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential
> issue(s) to consider.
>
> Critical: 0 · High: 1 · Medium: 0 · Low: 0
>
> If you believe none of the issues are legitimate, please reply to each
> issue of Medium severity or higher and explain why the AI is wrong.
> If any of them are legitimate and you plan to respin, please let patchwork
> know by including "pw-bot: cr" as a separate line at the end of your reply
> (one such reply per series is enough).
>
> - [High] Regression for non-encapsulated IPv6 CHECKSUM_PARTIAL skbs in
> skb_csum_hwoffload_help(), plus a matching gap in…
>
> --
>
> net: extend IPv6 exthdr detection of tunneled packets
>
> This patch replaces skb_gso_has_extension_hdr() with
> skb_has_ipv6_extension_hdr(). The new helper runs ipv6_ext_hdr() on the
> outer IPv6 nexthdr. For encapsulated skbs that have an inner network
> header, it also runs it on the inner IPv6 nexthdr. skb_csum_hwoffload_help()
> now uses the same helper instead of its open coded skb_network_header_len()
> test.
>
> > diff --git a/net/core/dev.c b/net/core/dev.c
> > index f660fccfc0dbc..992b78308c13f 100644
> > --- a/net/core/dev.c
> > +++ b/net/core/dev.c
> > @@ -3818,20 +3818,29 @@ static netdev_features_t dflt_features_check(struct sk_buff *skb,
> > return vlan_features_check(skb, features);
> > }
> >
> > -static bool skb_gso_has_extension_hdr(const struct sk_buff *skb)
> > -{
> > - if (!skb->encapsulation)
> > - return ((skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6 ||
> > - (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4 &&
> > - vlan_get_protocol(skb) == htons(ETH_P_IPV6))) &&
> > - skb_transport_header_was_set(skb) &&
> > - skb_network_header_len(skb) != sizeof(struct ipv6hdr));
>
> [ ... ]
>
> > +static bool __skb_has_ipv6_ext_hdr(const struct sk_buff *skb, int nhoff)
> > +{
> > + const struct ipv6hdr *ip6h;
> > + struct ipv6hdr _ip6h;
> > +
> > + ip6h = skb_header_pointer(skb, nhoff, sizeof(_ip6h), &_ip6h);
> > + return ip6h && ip6h->version == 6 && ipv6_ext_hdr(ip6h->nexthdr);
> > +}
> > +
> > +static bool skb_has_ipv6_extension_hdr(const struct sk_buff *skb)
> > +{
> > + if (vlan_get_protocol(skb) == htons(ETH_P_IPV6) &&
> > + __skb_has_ipv6_ext_hdr(skb, skb_network_offset(skb)))
> > + return true;
> > +
> > + /* Tunnels without an inner network header, such as SCTP-in-UDP or
> > + * PSP, have no inner IP header and thus no inner extension header.
> > + */
> > + if (skb->encapsulation && skb_inner_network_header_was_set(skb) &&
> > + __skb_has_ipv6_ext_hdr(skb, skb_inner_network_offset(skb)))
> > + return true;
> > +
> > + return false;
> > }
>
> [ ... ]
>
> > @@ -3988,8 +3997,7 @@ int skb_csum_hwoffload_help(struct sk_buff *skb,
> > return 0;
> >
> > if (features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) {
> > - if (vlan_get_protocol(skb) == htons(ETH_P_IPV6) &&
> > - skb_network_header_len(skb) != sizeof(struct ipv6hdr))
> > + if (skb_has_ipv6_extension_hdr(skb))
> > goto sw_checksum;
>
> [Severity: High]
> Does this weaken the check for non-encapsulated IPv6 CHECKSUM_PARTIAL
> skbs?
>
> When !skb->encapsulation, validate_xmit_skb() sets the transport header to
> csum_start just before it calls skb_csum_hwoffload_help():
>
> net/core/dev.c:validate_xmit_skb() {
> ...
> if (skb->ip_summed == CHECKSUM_PARTIAL) {
> if (skb->encapsulation)
> skb_set_inner_transport_header(skb,
> skb_checksum_start_offset(skb));
> else
> skb_set_transport_header(skb,
> skb_checksum_start_offset(skb));
> if (skb_csum_hwoffload_help(skb, features))
> goto out_kfree_skb;
> ...
> }
>
> That means the removed skb_network_header_len() test checked that
> csum_start sits right after the 40 byte IPv6 header.
>
> The new helper only checks whether the outer nexthdr is one of the six
> values listed in ipv6_ext_hdr(). It skips the inner check because
> encapsulation is 0.
>
> Take IPv6|UDP|VXLAN|Eth|IP|TCP, or IPv6|IPv6|TCP (nexthdr 41), with
> csum_start at the inner TCP header and csum_offset 16. Would that packet
> now reach the csum_offset switch and return 0?
>
> Such skbs can come from untrusted input. __virtio_net_hdr_to_skb() is
> used by tap, vhost-net and AF_PACKET with PACKET_VNET_HDR. It accepts
> VIRTIO_NET_HDR_F_NEEDS_CSUM with any csum_start via
> skb_partial_csum_set(). It does not look at nexthdr and does not set
> skb->encapsulation.
This is correct. virtio_net_hdr can insert packets with tunnels,
without setting skb->encapsulation.
> One case: a guest sends IPv6 VXLAN traffic with a CHECKSUM_PARTIAL inner
> TCP header (LCO). The host bridges it to a device that has
> NETIF_F_IPV6_CSUM but not NETIF_F_HW_CSUM.
>
> On a device that parses headers itself, such as bnxt, bnxt_exthdr_check()
> accepts an outer nexthdr of UDP for non-encapsulated skbs. The hardware
> would then fill in the outer UDP checksum and leave the inner TCP checksum
> holding only the pseudo-header seed. Before this patch, the kernel
> computed these checksums in software.
>
> The skbuff.h description of NETIF_F_IPV6_CSUM covers only "unencapsulated
> packets of the form IPv6|TCP or IPv6|UDP where the Next Header field in
> the IPv6 header is either TCP or UDP."
>
> gso_features_check() has the same gap. For non-encapsulated skbs, the old
> branch removed NETIF_F_TSO6 and NETIF_F_GSO_UDP_L4 whenever the transport
> header was not at nh + 40. The new code removes them only when the outer
> nexthdr is an extension header.
>
> The commit message talks about removing false positives, but it doesn't
> mention this relaxation for non-encapsulated skbs.
>
> Could the offset test stay for the !skb->encapsulation case? For example:
>
> skb_checksum_start_offset(skb) - skb_network_offset(skb) != sizeof(struct ipv6hdr)
Will do in v2.
Reintroducing this check is the safest way to detect this edge case.
> Or could the check require nexthdr to be IPPROTO_TCP or IPPROTO_UDP,
> instead of testing ipv6_ext_hdr()?
Only checking two transport types is insufficient.
> --
> Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260924192128.1197118-1-willemdebruijn.kernel%40gmail.com
prev parent reply other threads:[~2026-09-26 2:06 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-24 19:20 [PATCH net] net: extend IPv6 exthdr detection of tunneled packets Willem de Bruijn
2026-09-25 19:21 ` netdev-bot+sashiko
2026-09-26 2:06 ` Willem de Bruijn [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=willemdebruijn.kernel.386226098beef@gmail.com \
--to=willemdebruijn.kernel@gmail.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=netdev-bot+sashiko@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=stable@vger.kernel.org \
--cc=willemb@google.com \
--cc=xietangxin@yeah.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox