an icmpv6 error quotes as much of the invoking packet as fits in the minimum ipv6 mtu. if the device had decrypted the packet (as indicated by skb->decrypted) then the icmpv6 error is sending part of it back out onto the network in cleartext. as in the previous patch for icmp: ktls rx device offload and psp can't be told apart reliably, and psp also encrypts the l4 header, so don't send an error about a received decrypted skb at all. linux receivers would drop an error whose quote stops before the l4 header anyway (icmpv6_notify()). 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 its route goes to a local address (RTF_LOCAL), like RTCF_LOCAL in the previous patch. an error about a received decrypted skb is dropped before the rate limit, so that it doesn't use up the peer's and the global icmpv6 credit. 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/ipv6/icmp.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index d8203ebad882..949025d83e15 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -778,6 +778,13 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, np = inet6_sk(sk); + /* Don't send parts of a decrypted skb onto the network, see + * __icmp_send(): no error about a received skb. Before the rate + * limit, so that a suppressed error costs no credit. + */ + if (unlikely(skb_is_decrypted(skb) && skb->skb_iif)) + goto out_unlock; + if (!icmpv6_xrlim_allow(sk, type, &fl6, apply_ratelimit)) goto out_unlock; @@ -799,6 +806,15 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, if (IS_ERR(dst)) goto out_unlock; + /* An error about a locally originated decrypted skb is sent only if + * it is routed to a local address. + */ + if (unlikely(skb_is_decrypted(skb)) && + !(dst_rt6_info(dst)->rt6i_flags & RTF_LOCAL)) { + dst_release(dst); + goto out_unlock; + } + ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst); msg.skb = skb; -- 2.53.0-Meta