From: Greg Kroah-Hartman Date: Fri, 8 May 2026 04:24:08 +0000 (+0200) Subject: 7.0-stable patches X-Git-Tag: v6.6.138~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ab2f6d6954ddb637a636376f5d43dcee42329fc7;p=thirdparty%2Fkernel%2Fstable-queue.git 7.0-stable patches added patches: xfrm-esp-avoid-in-place-decrypt-on-shared-skb-frags.patch --- diff --git a/queue-7.0/series b/queue-7.0/series index cca80fdaac..a4b273b08b 100644 --- a/queue-7.0/series +++ b/queue-7.0/series @@ -14,3 +14,4 @@ asoc-sof-don-t-allow-pointer-operations-on-unconfigured-streams.patch wifi-mt76-mt7925-fix-incorrect-tlv-length-in-clc-command.patch spi-rockchip-fix-controller-deregistration.patch ksmbd-rewrite-stop_sessions-with-restartable-iteration.patch +xfrm-esp-avoid-in-place-decrypt-on-shared-skb-frags.patch diff --git a/queue-7.0/xfrm-esp-avoid-in-place-decrypt-on-shared-skb-frags.patch b/queue-7.0/xfrm-esp-avoid-in-place-decrypt-on-shared-skb-frags.patch new file mode 100644 index 0000000000..534e121b5d --- /dev/null +++ b/queue-7.0/xfrm-esp-avoid-in-place-decrypt-on-shared-skb-frags.patch @@ -0,0 +1,96 @@ +From f4c50a4034e62ab75f1d5cdd191dd5f9c77fdff4 Mon Sep 17 00:00:00 2001 +From: Kuan-Ting Chen +Date: Mon, 4 May 2026 23:27:12 +0800 +Subject: xfrm: esp: avoid in-place decrypt on shared skb frags + +From: Kuan-Ting Chen + +commit f4c50a4034e62ab75f1d5cdd191dd5f9c77fdff4 upstream. + +MSG_SPLICE_PAGES can attach pages from a pipe directly to an skb. TCP +marks such skbs with SKBFL_SHARED_FRAG after skb_splice_from_iter(), +so later paths that may modify packet data can first make a private +copy. The IPv4/IPv6 datagram append paths did not set this flag when +splicing pages into UDP skbs. + +That leaves an ESP-in-UDP packet made from shared pipe pages looking +like an ordinary uncloned nonlinear skb. ESP input then takes the no-COW +fast path for uncloned skbs without a frag_list and decrypts in place +over data that is not owned privately by the skb. + +Mark IPv4/IPv6 datagram splice frags with SKBFL_SHARED_FRAG, matching +TCP. Also make ESP input fall back to skb_cow_data() when the flag is +present, so ESP does not decrypt externally backed frags in place. +Private nonlinear skb frags still use the existing fast path. + +This intentionally does not change ESP output. In esp_output_head(), +the path that appends the ESP trailer to existing skb tailroom without +calling skb_cow_data() is not reachable for nonlinear skbs: +skb_tailroom() returns zero when skb->data_len is nonzero, while ESP +tailen is positive. Thus ESP output will either use the separate +destination-frag path or fall back to skb_cow_data(). + +Fixes: cac2661c53f3 ("esp4: Avoid skb_cow_data whenever possible") +Fixes: 03e2a30f6a27 ("esp6: Avoid skb_cow_data whenever possible") +Fixes: 7da0dde68486 ("ip, udp: Support MSG_SPLICE_PAGES") +Fixes: 6d8192bd69bb ("ip6, udp6: Support MSG_SPLICE_PAGES") +Reported-by: Hyunwoo Kim +Reported-by: Kuan-Ting Chen +Tested-by: Hyunwoo Kim +Cc: stable@vger.kernel.org +Signed-off-by: Kuan-Ting Chen +Signed-off-by: Steffen Klassert +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/esp4.c | 3 ++- + net/ipv4/ip_output.c | 2 ++ + net/ipv6/esp6.c | 3 ++- + net/ipv6/ip6_output.c | 2 ++ + 4 files changed, 8 insertions(+), 2 deletions(-) + +--- a/net/ipv4/esp4.c ++++ b/net/ipv4/esp4.c +@@ -873,7 +873,8 @@ static int esp_input(struct xfrm_state * + nfrags = 1; + + goto skip_cow; +- } else if (!skb_has_frag_list(skb)) { ++ } else if (!skb_has_frag_list(skb) && ++ !skb_has_shared_frag(skb)) { + nfrags = skb_shinfo(skb)->nr_frags; + nfrags++; + +--- a/net/ipv4/ip_output.c ++++ b/net/ipv4/ip_output.c +@@ -1233,6 +1233,8 @@ alloc_new_skb: + if (err < 0) + goto error; + copy = err; ++ if (!(flags & MSG_NO_SHARED_FRAGS)) ++ skb_shinfo(skb)->flags |= SKBFL_SHARED_FRAG; + wmem_alloc_delta += copy; + } else if (!zc) { + int i = skb_shinfo(skb)->nr_frags; +--- a/net/ipv6/esp6.c ++++ b/net/ipv6/esp6.c +@@ -915,7 +915,8 @@ static int esp6_input(struct xfrm_state + nfrags = 1; + + goto skip_cow; +- } else if (!skb_has_frag_list(skb)) { ++ } else if (!skb_has_frag_list(skb) && ++ !skb_has_shared_frag(skb)) { + nfrags = skb_shinfo(skb)->nr_frags; + nfrags++; + +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1765,6 +1765,8 @@ alloc_new_skb: + if (err < 0) + goto error; + copy = err; ++ if (!(flags & MSG_NO_SHARED_FRAGS)) ++ skb_shinfo(skb)->flags |= SKBFL_SHARED_FRAG; + wmem_alloc_delta += copy; + } else if (!zc) { + int i = skb_shinfo(skb)->nr_frags;