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 Closes: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261023234640.1459291-1-toddfreed%40meta.com Suggested-by: Jakub Kicinski Suggested-by: Björn Töpel Fixes: 784abe24c903 ("net: Add decrypted field to skb") Signed-off-by: Todd Freed --- 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