[SRU][J][PATCH 1/1] rxrpc: Also unshare DATA/RESPONSE packets when paged frags are present

Cengiz Can cengiz.can at canonical.com
Thu May 21 16:52:33 UTC 2026


From: Hyunwoo Kim <imv4bel at gmail.com>

The DATA-packet handler in rxrpc_input_packet() copies the skb to a
linear one before calling into the security ops only when skb_cloned()
is true (via the existing skb_unshare() call).  An skb that is not
cloned but still carries externally-owned paged fragments (pages
deposited by splice() into a UDP socket via udp_sendpage and
ip_append_page on pre-v6.5 kernels, or via __ip_append_data on
v6.5+ kernels with MSG_SPLICE_PAGES) falls through to the in-place
decryption path, which binds the frag pages directly into the
AEAD/skcipher SGL via skb_to_sgvec().

Extend the gate to also unshare when the incoming skb is nonlinear.
This catches the splice-loopback vector regardless of how the shared
frags were deposited, while preserving the zero-copy fast path for
fully-linear skbs.

(backported from commit aa54b1d27fe0c2b78e664a34fd0fdf7cd1960d71)
[cengizcan: adjusted for v5.15 along two axes. First, the v7.1-rc1
 unshare-move refactors 1f2740150f90 ("rxrpc: Fix potential UAF
 after skb_unshare() failure") and 24481a7f5733 ("rxrpc: Fix
 conn-level packet handling to unshare RESPONSE packets") are not
 present in jammy, so the fix is applied to the older unconditional
 skb_unshare() call site in net/rxrpc/input.c rather than
 rxrpc_input_call_event() and rxrpc_verify_response(). Second, the
 upstream gate uses skb_has_frag_list() and skb_has_shared_frag().
 The SKBFL_SHARED_FRAG flag-setting in the receive path was added
 by the companion fix f4c50a4034e6 ("xfrm: esp: avoid in-place
 decrypt on shared skb frags") in __ip_append_data, which has not
 yet been backported to jammy. Without that flag-setter, an
 skb_has_shared_frag() check returns false for the very skbs we
 need to catch. Using skb_is_nonlinear() is a strict superset that
 catches the same skbs and is correct independent of which deposit
 path was used.]
CVE-2026-43500
Signed-off-by: Cengiz Can <cengiz.can at canonical.com>
---
 net/rxrpc/input.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 721d847ba92b..bd2c100d0d08 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -1314,7 +1314,12 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
 		 * decryption.
 		 */
 		if (sp->hdr.securityIndex != 0) {
-			struct sk_buff *nskb = skb_unshare(skb, GFP_ATOMIC);
+			struct sk_buff *nskb;
+
+			if (skb_cloned(skb) || skb_is_nonlinear(skb))
+				nskb = skb_copy(skb, GFP_ATOMIC);
+			else
+				nskb = skb;
 			if (!nskb) {
 				rxrpc_eaten_skb(skb, rxrpc_skb_unshared_nomem);
 				goto out;
-- 
2.43.0




More information about the kernel-team mailing list