Linux RDMA and InfiniBand development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Jérémy Jean" <Jeremy.Jean@oss.cyber.gouv.fr>
Cc: linux-rdma@vger.kernel.org
Subject: Re: [PATCH ipsec v2 6/7] xfrm: segment untrusted GSO packets before sequence allocation
Date: Mon, 09 Nov 2026 14:27:13 +0000	[thread overview]
Message-ID: <sashiko-outbox-205099@kernel.org> (raw)
In-Reply-To: <20261108142652.1330952-7-Jeremy.Jean@oss.cyber.gouv.fr>

Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [Medium] xfrm: skb->encapsulation set in xfrm_output_one() before
  inner headers
- [Medium] xfrm: early IPv6 UFO segmentation corrupts xo->proto in
  esp6_gso_encap()
--

commit 0279671c95c12bb5bd51f663fc7acf801cb6d765
Author: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>

xfrm: segment untrusted GSO packets before sequence allocation

This commit segments SKB_GSO_DODGY packets in xfrm_output() before
allocating sequence numbers and moves setting skb->encapsulation into
xfrm_output_one().

> diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
> index 99d1b33db52a6..a1fb60971c6bc 100644
> --- a/net/xfrm/xfrm_output.c
> +++ b/net/xfrm/xfrm_output.c
> @@ -505,6 +505,9 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
>  	if (err <= 0 || x->xso.type == XFRM_DEV_OFFLOAD_PACKET)
>  		goto resume;
>  
> +	if (xfrm_offload(skb))
> +		skb->encapsulation = 1;
> +
>  	do {
>  		err = xfrm_skb_check_space(skb);
>  		if (err) {

[Severity: Medium]
Does setting skb->encapsulation = 1 before xfrm_outer_mode_output() cause
xfrm4_tunnel_check_size() and xfrm6_tunnel_check_size() to read inner
headers before skb->inner_network_header and skb->inner_transport_header
are initialized?

In tunnel and BEET modes, xfrm_outer_mode_output() runs
xfrm_inner_extract_output() before xfrm4_tunnel_encap_add() or
xfrm6_tunnel_encap_add() sets the inner header offsets.  When
skb->encapsulation is already set on a packet whose inner header offsets
are still zero:

net/core/gso.c:skb_gso_transport_seglen() {
	...
	if (skb->encapsulation) {
		thlen = skb_inner_transport_header(skb) -
			skb_transport_header(skb);

		if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
			thlen += inner_tcp_hdrlen(skb);
	}
	...
}

For non-dodgy GSO packets with ESP offload enabled,
skb_gso_validate_network_len() reads inner_tcp_hdrlen(skb) from skb->head
and subtracts skb->transport_header, underflowing the unsigned segment
length when gso_size is small and dropping valid packets with -EMSGSIZE.
If the size check fails on a socket-owned packet, xfrm4_local_error() and
xfrm6_local_error() also take the skb->encapsulation branch and read
hdr->daddr from skb->head into the socket error queue.

Setting skb->encapsulation = 1 inside the if (xfrm_offload(skb)) branch
right before x->type_offload->encap(x, skb), matching where the else
branch clears it, avoids setting it before xfrm_outer_mode_output() has
initialized the inner headers.

> @@ -814,10 +817,10 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb)
>  		xfrm_state_hold(x);
>  
>  		xfrm_get_inner_ipproto(skb, x);
> -		skb->encapsulation = 1;
>  
>  		if (skb_is_gso(skb)) {
> -			if (skb->inner_protocol && x->props.mode == XFRM_MODE_TUNNEL)
> +			if ((skb_shinfo(skb)->gso_type & SKB_GSO_DODGY) ||
> +			    (skb->inner_protocol && x->props.mode == XFRM_MODE_TUNNEL))
>  				return xfrm_output_gso(net, sk, skb);
>  
>  			skb_shinfo(skb)->gso_type |= SKB_GSO_ESP;

[Severity: Medium]
Can segmenting an IPv6 UFO packet (SKB_GSO_UDP | SKB_GSO_DODGY) here
after xfrm_dev_offload_ok() has already attached an offload sec_path
corrupt xo->proto in esp6_gso_encap()?

When xfrm_dev_offload_ok() runs on the unsegmented UFO packet,
ipv6_hdr(skb)->nexthdr is IPPROTO_UDP, so offload is enabled.
xfrm_output_gso() then calls udp6_ufo_fragment(), which inserts a
struct frag_hdr and sets ipv6_hdr(seg)->nexthdr = NEXTHDR_FRAGMENT on
each segment.  In transport mode, xfrm6_transport_output() stops at
NEXTHDR_FRAGMENT and moves only the 40-byte struct ipv6hdr backwards to
make room for the ESP header, leaving the old iph->daddr bytes in the
uninitialized ESP header slot at offset 40:

net/ipv6/esp6_offload.c:esp6_gso_encap() {
	...
	proto = iph->nexthdr;

	if (x->outer_mode.encap == XFRM_MODE_TRANSPORT) {
		__be16 frag;

		ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &proto, &frag);
	}
	...
}

Because proto is NEXTHDR_FRAGMENT, ipv6_skip_exthdr() parses offset 40 as
a fragment header before the ESP header is written and overwrites
xo->proto with leftover destination address bytes whenever those bytes
have a zero fragment offset.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261108142652.1330952-1-Jeremy.Jean@oss.cyber.gouv.fr?part=6

  reply	other threads:[~2026-11-09 14:27 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-08 14:26 [PATCH ipsec v2 0/7] xfrm: fix ESP IV generation and ESN authentication Jérémy Jean
2026-11-08 14:26 ` [PATCH ipsec v2 1/7] xfrm: esp6: use the current sequence number for the IV Jérémy Jean
2026-11-09 14:27   ` sashiko-bot
2026-11-08 14:26 ` [PATCH ipsec v2 2/7] xfrm: esp4: " Jérémy Jean
2026-11-09 14:27   ` sashiko-bot
2026-11-08 14:26 ` [PATCH ipsec v2 3/7] xfrm: esp: use the current sequence number for AAD and offload Jérémy Jean
2026-11-09 14:27   ` sashiko-bot
2026-11-09 15:08   ` netdev-bot+sashiko
2026-11-08 14:26 ` [PATCH ipsec v2 4/7] xfrm: prevent AES-GCM nonce reuse after early GSO Jérémy Jean
2026-11-09 14:27   ` sashiko-bot
2026-11-09 15:08   ` netdev-bot+sashiko
2026-11-08 14:26 ` [PATCH ipsec v2 5/7] net/mlx5e: Use the packet sequence number for the IPsec IV Jérémy Jean
2026-11-09 14:27   ` sashiko-bot
2026-11-08 14:26 ` [PATCH ipsec v2 6/7] xfrm: segment untrusted GSO packets before sequence allocation Jérémy Jean
2026-11-09 14:27   ` sashiko-bot [this message]
2026-11-09 15:08   ` netdev-bot+sashiko
2026-11-08 14:26 ` [PATCH ipsec v2 7/7] xfrm: leave the sequence counter unchanged on ESN overflow Jérémy Jean
2026-11-09 14:27   ` sashiko-bot
2026-11-08 14:32 ` [PATCH ipsec v2 0/7] xfrm: fix ESP IV generation and ESN authentication netdev-bot+sinfo

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=sashiko-outbox-205099@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=Jeremy.Jean@oss.cyber.gouv.fr \
    --cc=linux-rdma@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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