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?
next prev parent 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.