Netdev List
 help / color / mirror / Atom feed
From: Simon Horman <horms@kernel.org>
To: steffen.klassert@secunet.com
Cc: 'Simon Horman' <horms@kernel.org>,
	netdev@vger.kernel.org, sd@queasysnail.net,
	tobias@strongswan.org, herbert@gondor.apana.org.au,
	devel@linux-ipsec.org
Subject: Re: [PATCH ipsec-next v2] esp: Consolidate esp4 and esp6
Date: Sat,  9 May 2026 14:56:40 +0100	[thread overview]
Message-ID: <20260509135639.1309815-2-horms@kernel.org> (raw)
In-Reply-To: <afr4ipktV91sA8WU@secunet.com>

From: 'Simon Horman' <horms@kernel.org>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://sashiko.dev
---
Now I have enough to produce the report.

commit 64848fd4fb36bc803f3ebb41951e5c02a19f0280
Author: Steffen Klassert <steffen.klassert@secunet.com>

esp: Consolidate esp4 and esp6

This patch merges common code of esp4.c and esp6.c into a new
xfrm_esp.c. ESP output/input, AEAD setup and the TCP/UDP encapsulation
helpers are shared between IPv4 and IPv6, with three family-specific
hooks (input_encap, find_tcp_sk, output_encap_csum) added to struct
xfrm_type.

> diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c
> index 22895521a57d..b1c38d7d286e 100644
> --- a/net/ipv6/esp6_offload.c
> +++ b/net/ipv6/esp6_offload.c
> @@ -290,14 +290,18 @@ static int esp6_input_tail(struct xfrm_state *x, struct sk_buff *skb)
>  {
>  	struct crypto_aead *aead = x->data;
>  	struct xfrm_offload *xo = xfrm_offload(skb);
> +	int hlen = sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead);
>  
> -	if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead)))
> +	if (!pskb_may_pull(skb, hlen))
>  		return -EINVAL;
>  
>  	if (!(xo->flags & CRYPTO_DONE))
>  		skb->ip_summed = CHECKSUM_NONE;
> +	else
> +		skb_postpull_rcsum(skb, skb_network_header(skb),
> +				   skb_network_header_len(skb));
>  
> -	return esp6_input_done2(skb, 0);
> +	return esp_input_done2(skb, 0);
>  }

Has the non-offload IPv6 ESP input path lost its skb_postpull_rcsum()
for the IPv6 header?

Before this patch, esp6_input_done2() did:

    skb_postpull_rcsum(skb, skb_network_header(skb),
                       skb_network_header_len(skb));
    skb_pull_rcsum(skb, hlen);

and that call was introduced by commit a9b28c2bf05d ("esp6: Fix RX
checksum after header pull") to compensate for ip6_input_finish()
stripping the IPv6 header without adjusting skb->csum, fixing
"hw csum failure" warnings on devices delivering CHECKSUM_COMPLETE.

The new esp_input_done2() in net/xfrm/xfrm_esp.c only does:

    hlen = sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead);
    skb_pull_rcsum(skb, hlen);

and the postpull is reinstated only in esp6_input_tail() under the
"xo->flags & CRYPTO_DONE" branch. Non-offload software-decrypt IPv6
ESP RX therefore no longer compensates skb->csum for the outer IPv6
header bytes. Is this an intentional change, and if so what replaces
the fix from a9b28c2bf05d?

The commit message says "Move the skb_postpull_rcsum() call to the
offloading codepath, it is needed only there", which seems to
contradict the stated reason for a9b28c2bf05d. Is there a later commit
or code change that makes it unnecessary in the non-offload path?

> diff --git a/net/xfrm/xfrm_esp.c b/net/xfrm/xfrm_esp.c
> new file mode 100644
> index 000000000000..4f75e1ace3bb
> --- /dev/null
> +++ b/net/xfrm/xfrm_esp.c

[ ... ]

> +#ifdef CONFIG_INET_ESPINTCP
> +static int esp_output_tcp_finish(struct xfrm_state *x, struct sk_buff *skb)
> +{
> +	struct sock *sk;
> +	int err;
> +
> +	rcu_read_lock();
> +
> +	sk = x->type->find_tcp_sk(x);
[ ... ]
> +static int esp_output_tail_tcp(struct xfrm_state *x, struct sk_buff *skb)
> +{
> +	int err;
> +
> +	local_bh_disable();
> +	err = xfrm_trans_queue_net(xs_net(x), skb, esp_output_tcp_encap_cb);
> +	local_bh_enable();
[ ... ]
> +}
> +#else
> +static int esp_output_tail_tcp(struct xfrm_state *x, struct sk_buff *skb)
> +{
> +	WARN_ON(1);
> +	return -EOPNOTSUPP;
> +}
> +#endif

Is CONFIG_INET_ESPINTCP the right guard for this shared file?

This new xfrm_esp.c is compiled for both IPv4 and IPv6 ESP, but the
TCP-encap helpers are wrapped with #ifdef CONFIG_INET_ESPINTCP, which
is the IPv4-only Kconfig symbol. The IPv6 counterpart is
CONFIG_INET6_ESPINTCP, and both symbols "select XFRM_ESPINTCP" as the
common hidden symbol (see net/xfrm/Kconfig and net/xfrm/Makefile,
which uses obj-$(CONFIG_XFRM_ESPINTCP) += espintcp.o).

For a kernel configured with CONFIG_INET_ESPINTCP=n and
CONFIG_INET6_ESPINTCP=y, the full esp_output_tcp_encap() /
esp_output_tail_tcp() are not compiled in, so the stub returning
-EOPNOTSUPP with WARN_ON(1) is selected, and any IPv6 ESP-in-TCP
output call ending up in esp_output_head() -> esp_output_encap() ->
esp_output_tcp_encap() will fail. The same #ifdef also appears further
down around esp_output_tcp_encap().

Should these two blocks be guarded by CONFIG_XFRM_ESPINTCP instead?

> +static struct ip_esp_hdr *esp_output_udp_encap(struct sk_buff *skb,
> +					       int encap_type,
> +					       struct esp_info *esp,
> +					       __be16 sport,
> +					       __be16 dport)
> +{
> +	struct udphdr *uh;
> +	unsigned int len;
> +	struct xfrm_offload *xo = xfrm_offload(skb);
> +
> +	len = skb->len + esp->tailen - skb_transport_offset(skb);
> +
> +	uh = (struct udphdr *)esp->esph;
> +	uh->source = sport;
> +	uh->dest = dport;
> +	uh->len = htons(len);
> +	uh->check = 0;

Can this silently truncate uh->len?

The old esp6_output_udp_encap() explicitly rejected len > U16_MAX with
-EMSGSIZE before writing htons(len) into the 16-bit UDP length field,
and the old IPv4 esp_output_udp_encap() rejected len + sizeof(iphdr)
> IP_MAX_MTU. Both bounds are gone from this consolidated helper.

The commit message says:

    "Remove the IP_MAX_MTU check from UDP/TCP encap.
     The IPv4/IPv6 local_out function will do that ceck later."

local_out checks the outer IP packet length, not the UDP 16-bit length
field. In the software-fallback branch of esp6_xmit() (the !hw_offload
path calling esp_output_head()), skb->len of a GSO skb can exceed
65535 pre-segmentation, so the htons() can truncate uh->len without
any earlier check rejecting the packet.

Should the >U16_MAX check be retained in esp_output_udp_encap(), at
least for IPv6?

> +#ifdef CONFIG_INET_ESPINTCP
> +static struct ip_esp_hdr *esp_output_tcp_encap(struct xfrm_state *x,
> +					       struct sk_buff *skb,
> +					       struct esp_info *esp)
> +{
> +	__be16 *lenp = (void *)esp->esph;
> +	struct ip_esp_hdr *esph;
> +	unsigned int len;
> +	struct sock *sk;
> +
> +	len = skb->len + esp->tailen - skb_transport_offset(skb);
> +
> +	rcu_read_lock();
> +	sk = x->type->find_tcp_sk(x);
> +	rcu_read_unlock();
> +
> +	if (IS_ERR(sk))
> +		return ERR_CAST(sk);
> +
> +	sock_put(sk);
> +
> +	*lenp = htons(len);

Can *lenp be truncated here?

The previous IPv4 and IPv6 versions both had "if (len > IP_MAX_MTU)
return ERR_PTR(-EMSGSIZE)" before writing the 2-byte espintcp length
prefix. espintcp frames ride over TCP and are not bounded by any IP
MTU that local_out will later enforce on the outer header, so the
local_out justification in the commit message does not seem to cover
this case. Should the len > 65535 check be preserved here?

  reply	other threads:[~2026-05-09 13:57 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-06  8:15 [PATCH ipsec-next v2] esp: Consolidate esp4 and esp6 Steffen Klassert
2026-05-09 13:56 ` Simon Horman [this message]
2026-05-10  8:06   ` Steffen Klassert
2026-05-09 14:00 ` Simon Horman
2026-05-10 11:20 ` David Laight

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=20260509135639.1309815-2-horms@kernel.org \
    --to=horms@kernel.org \
    --cc=devel@linux-ipsec.org \
    --cc=herbert@gondor.apana.org.au \
    --cc=netdev@vger.kernel.org \
    --cc=sd@queasysnail.net \
    --cc=steffen.klassert@secunet.com \
    --cc=tobias@strongswan.org \
    /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