[PATCH net v5 4/8] ipv4: icmp: don't quote decrypted payload in icmp errors

From: Todd Freed

Date: Tue Nov 10 2026 - 19:19:54 EST


an icmp error quotes as much of the invoking packet as fits in 576
bytes. if the device had decrypted the packet (as indicated by
skb->decrypted) then the icmp error is sending part of it back out onto
the network in cleartext.

the two offloads encrypt different parts of the packet:

- ktls encrypts the tcp payload. the tcp header is in the clear on the
wire, so a quote of the ip header and the tcp header, without the
payload, would be fine.

- psp encryption also covers the tcp header. the quote could include
just the ip header, but then that's not really useful. linux receivers
want to look at the l4 layer on the quoted packet to look up the
related flow, so such a truncated icmp error packet is just dropped
(icmp_socket_deliver()).

the two offloads can't be told apart reliably. a decrypted psp skb has
SKB_EXT_PSP, but some paths drop it and keep skb->decrypted
(skb_scrub_packet(), e.g. on bpf redirects and tunnel decap). so don't
send an error about a received decrypted skb at all.

on tx, skb->decrypted is also set. an error about a locally originated
skb (skb_iif is 0) is sent in full as before, if it is routed to a local
address (RTCF_LOCAL on the route to the packet's source address).

a reject rule (iptables REJECT, nft reject) sends its icmp error with
icmp_send(), through nf_send_unreach(). so now, a received packet which
the device decrypted, and which hits a reject rule in the INPUT or
FORWARD chain, is now dropped without a reply, like a drop rule.

packets which weren't decrypted are rejected as before, and so are
locally originated ones in the OUTPUT chain, if the error goes to a
local address as above.

the next patch does the same for icmpv6.

Reported-by: Sashiko <sashiko-bot@xxxxxxxxxx>
Closes: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261023234640.1459291-1-toddfreed%40meta.com
Suggested-by: Jakub Kicinski <kuba@xxxxxxxxxx>
Suggested-by: Björn Töpel <bjorn@xxxxxxxxxx>
Fixes: 784abe24c903 ("net: Add decrypted field to skb")
Signed-off-by: Todd Freed <toddfreed@xxxxxxxx>
---
net/ipv4/icmp.c | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 90c0e22c29be..e11008aa4cec 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -979,6 +979,18 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info,
if (rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
goto ende;

+ /* Don't send parts of a decrypted skb onto the network. A received skb
+ * was decrypted by the device, and the transport header may have been
+ * encrypted. The different offloads can't be distinguished in all cases
+ * so simply don't send the error.
+ *
+ * A locally originated skb to be encrypted may be quoted if its source
+ * address (target of the error) is local.
+ */
+ if (unlikely(skb_is_decrypted(skb_in)) &&
+ (skb_in->skb_iif || !(rt->rt_flags & RTCF_LOCAL)))
+ goto ende;
+
/* peer icmp_ratelimit */
if (!icmpv4_xrlim_allow(net, rt, &fl4, type, code, apply_ratelimit))
goto ende;
--
2.53.0-Meta