Patch "rxrpc: Fix potential UAF after skb_unshare() failure" has been added to the 6.12-stable tree

gregkh at linuxfoundation.org gregkh at linuxfoundation.org
Mon May 4 05:04:40 PDT 2026


This is a note to let you know that I've just added the patch titled

    rxrpc: Fix potential UAF after skb_unshare() failure

to the 6.12-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     rxrpc-fix-potential-uaf-after-skb_unshare-failure.patch
and it can be found in the queue-6.12 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-242653-greg=kroah.com at vger.kernel.org Sun May  3 12:59:43 2026
From: Sasha Levin <sashal at kernel.org>
Date: Sun,  3 May 2026 06:59:34 -0400
Subject: rxrpc: Fix potential UAF after skb_unshare() failure
To: stable at vger.kernel.org
Cc: David Howells <dhowells at redhat.com>, Marc Dionne <marc.dionne at auristor.com>, Jeffrey Altman <jaltman at auristor.com>, Simon Horman <horms at kernel.org>, linux-afs at lists.infradead.org, stable at kernel.org, Jakub Kicinski <kuba at kernel.org>, Sasha Levin <sashal at kernel.org>
Message-ID: <20260503105934.1030665-1-sashal at kernel.org>

From: David Howells <dhowells at redhat.com>

[ Upstream commit 1f2740150f904bfa60e4bad74d65add3ccb5e7f8 ]

If skb_unshare() fails to unshare a packet due to allocation failure in
rxrpc_input_packet(), the skb pointer in the parent (rxrpc_io_thread())
will be NULL'd out.  This will likely cause the call to
trace_rxrpc_rx_done() to oops.

Fix this by moving the unsharing down to where rxrpc_input_call_event()
calls rxrpc_input_call_packet().  There are a number of places prior to
that where we ignore DATA packets for a variety of reasons (such as the
call already being complete) for which an unshare is then avoided.

And with that, rxrpc_input_packet() doesn't need to take a pointer to the
pointer to the packet, so change that to just a pointer.

Fixes: 2d1faf7a0ca3 ("rxrpc: Simplify skbuff accounting in receive path")
Closes: https://sashiko.dev/#/patchset/20260408121252.2249051-1-dhowells%40redhat.com
Signed-off-by: David Howells <dhowells at redhat.com>
cc: Marc Dionne <marc.dionne at auristor.com>
cc: Jeffrey Altman <jaltman at auristor.com>
cc: Simon Horman <horms at kernel.org>
cc: linux-afs at lists.infradead.org
cc: stable at kernel.org
Link: https://patch.msgid.link/20260422161438.2593376-4-dhowells@redhat.com
Signed-off-by: Jakub Kicinski <kuba at kernel.org>
[ adapted to per-skb rxrpc_input_call_event() signature ]
Signed-off-by: Sasha Levin <sashal at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 include/trace/events/rxrpc.h |    4 ++--
 net/rxrpc/ar-internal.h      |    1 -
 net/rxrpc/call_event.c       |   24 ++++++++++++++++++++++--
 net/rxrpc/io_thread.c        |   24 ++----------------------
 net/rxrpc/skbuff.c           |    9 ---------
 5 files changed, 26 insertions(+), 36 deletions(-)

--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -127,8 +127,7 @@
 	E_(rxrpc_call_poke_timer_now,		"Timer-now")
 
 #define rxrpc_skb_traces \
-	EM(rxrpc_skb_eaten_by_unshare,		"ETN unshare  ") \
-	EM(rxrpc_skb_eaten_by_unshare_nomem,	"ETN unshar-nm") \
+	EM(rxrpc_skb_get_call_rx,		"GET call-rx  ") \
 	EM(rxrpc_skb_get_conn_secured,		"GET conn-secd") \
 	EM(rxrpc_skb_get_conn_work,		"GET conn-work") \
 	EM(rxrpc_skb_get_last_nack,		"GET last-nack") \
@@ -153,6 +152,7 @@
 	EM(rxrpc_skb_see_recvmsg,		"SEE recvmsg  ") \
 	EM(rxrpc_skb_see_reject,		"SEE reject   ") \
 	EM(rxrpc_skb_see_rotate,		"SEE rotate   ") \
+	EM(rxrpc_skb_see_unshare_nomem,		"SEE unshar-nm") \
 	E_(rxrpc_skb_see_version,		"SEE version  ")
 
 #define rxrpc_local_traces \
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -1260,7 +1260,6 @@ int rxrpc_server_keyring(struct rxrpc_so
 void rxrpc_kernel_data_consumed(struct rxrpc_call *, struct sk_buff *);
 void rxrpc_new_skb(struct sk_buff *, enum rxrpc_skb_trace);
 void rxrpc_see_skb(struct sk_buff *, enum rxrpc_skb_trace);
-void rxrpc_eaten_skb(struct sk_buff *, enum rxrpc_skb_trace);
 void rxrpc_get_skb(struct sk_buff *, enum rxrpc_skb_trace);
 void rxrpc_free_skb(struct sk_buff *, enum rxrpc_skb_trace);
 void rxrpc_purge_queue(struct sk_buff_head *);
--- a/net/rxrpc/call_event.c
+++ b/net/rxrpc/call_event.c
@@ -342,8 +342,28 @@ bool rxrpc_input_call_event(struct rxrpc
 	if (skb && skb->mark == RXRPC_SKB_MARK_ERROR)
 		goto out;
 
-	if (skb)
-		rxrpc_input_call_packet(call, skb);
+	if (skb) {
+		struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+
+		if (sp->hdr.securityIndex != 0 &&
+		    skb_cloned(skb)) {
+			/* Unshare the packet so that it can be modified for
+			 * in-place decryption.
+			 */
+			struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC);
+
+			if (nskb) {
+				rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
+				rxrpc_input_call_packet(call, nskb);
+				rxrpc_free_skb(nskb, rxrpc_skb_put_input);
+			} else {
+				/* OOM - Drop the packet. */
+				rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
+			}
+		} else {
+			rxrpc_input_call_packet(call, skb);
+		}
+	}
 
 	/* If we see our async-event poke, check for timeout trippage. */
 	now = ktime_get_real();
--- a/net/rxrpc/io_thread.c
+++ b/net/rxrpc/io_thread.c
@@ -178,13 +178,12 @@ static bool rxrpc_extract_abort(struct s
 /*
  * Process packets received on the local endpoint
  */
-static bool rxrpc_input_packet(struct rxrpc_local *local, struct sk_buff **_skb)
+static bool rxrpc_input_packet(struct rxrpc_local *local, struct sk_buff *skb)
 {
 	struct rxrpc_connection *conn;
 	struct sockaddr_rxrpc peer_srx;
 	struct rxrpc_skb_priv *sp;
 	struct rxrpc_peer *peer = NULL;
-	struct sk_buff *skb = *_skb;
 	bool ret = false;
 
 	skb_pull(skb, sizeof(struct udphdr));
@@ -230,25 +229,6 @@ static bool rxrpc_input_packet(struct rx
 			return rxrpc_bad_message(skb, rxrpc_badmsg_zero_call);
 		if (sp->hdr.seq == 0)
 			return rxrpc_bad_message(skb, rxrpc_badmsg_zero_seq);
-
-		/* Unshare the packet so that it can be modified for in-place
-		 * decryption.
-		 */
-		if (sp->hdr.securityIndex != 0) {
-			skb = skb_unshare(skb, GFP_ATOMIC);
-			if (!skb) {
-				rxrpc_eaten_skb(*_skb, rxrpc_skb_eaten_by_unshare_nomem);
-				*_skb = NULL;
-				return just_discard;
-			}
-
-			if (skb != *_skb) {
-				rxrpc_eaten_skb(*_skb, rxrpc_skb_eaten_by_unshare);
-				*_skb = skb;
-				rxrpc_new_skb(skb, rxrpc_skb_new_unshared);
-				sp = rxrpc_skb(skb);
-			}
-		}
 		break;
 
 	case RXRPC_PACKET_TYPE_CHALLENGE:
@@ -490,7 +470,7 @@ int rxrpc_io_thread(void *data)
 			switch (skb->mark) {
 			case RXRPC_SKB_MARK_PACKET:
 				skb->priority = 0;
-				if (!rxrpc_input_packet(local, &skb))
+				if (!rxrpc_input_packet(local, skb))
 					rxrpc_reject_packet(local, skb);
 				trace_rxrpc_rx_done(skb->mark, skb->priority);
 				rxrpc_free_skb(skb, rxrpc_skb_put_input);
--- a/net/rxrpc/skbuff.c
+++ b/net/rxrpc/skbuff.c
@@ -47,15 +47,6 @@ void rxrpc_get_skb(struct sk_buff *skb,
 }
 
 /*
- * Note the dropping of a ref on a socket buffer by the core.
- */
-void rxrpc_eaten_skb(struct sk_buff *skb, enum rxrpc_skb_trace why)
-{
-	int n = atomic_inc_return(&rxrpc_n_rx_skbs);
-	trace_rxrpc_skb(skb, 0, n, why);
-}
-
-/*
  * Note the destruction of a socket buffer.
  */
 void rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace why)


Patches currently in stable-queue which might be from sashal at kernel.org are

queue-6.12/mm-migrate-factor-out-movable_ops-page-handling-into-migrate_movable_ops_page.patch
queue-6.12/mm-zsmalloc-copy-kmsan-metadata-in-zs_page_migrate.patch
queue-6.12/rdma-mana_ib-disable-rx-steering-on-rss-qp-destroy.patch
queue-6.12/mm-migrate-requeue-destination-folio-on-deferred-split-queue.patch
queue-6.12/ksmbd-use-msleep-instaed-of-schedule_timeout_interruptible.patch
queue-6.12/spi-fix-resource-leaks-on-device-setup-failure.patch
queue-6.12/mm-memory_hotplug-fix-hwpoisoned-large-folio-handlin.patch
queue-6.12/net-qrtr-ns-limit-the-maximum-number-of-lookups.patch
queue-6.12/net-bridge-use-a-stable-fdb-dst-snapshot-in-rcu-readers.patch
queue-6.12/wifi-mt76-mt792x-fix-mt7925u-usb-wfsys-reset-handling.patch
queue-6.12/alsa-aoa-use-guard-for-mutex-locks.patch
queue-6.12/padata-remove-comment-for-reorder_work.patch
queue-6.12/net-mctp-fix-don-t-require-received-header-reserved-bits-to-be-zero.patch
queue-6.12/alsa-aoa-i2sbus-clear-stale-prepared-state.patch
queue-6.12/net-qrtr-ns-limit-the-total-number-of-nodes.patch
queue-6.12/thermal-core-fix-thermal-zone-governor-cleanup-issues.patch
queue-6.12/f2fs-fix-to-do-sanity-check-on-dcc-discard_cmd_cnt-conditionally.patch
queue-6.12/drm-amdgpu-use-vmemdup_array_user-in-amdgpu_bo_creat.patch
queue-6.12/block-relax-pgmap-check-in-bio_add_page-for-compatible-zone-device-pages.patch
queue-6.12/perf-annotate-use-jump__delete-when-freeing-loongarc.patch
queue-6.12/iio-frequency-admv1013-add-dev-variable.patch
queue-6.12/iio-frequency-admv1013-fix-null-pointer-dereference-on-str.patch
queue-6.12/mm-migrate-move-movable_ops-page-handling-out-of-move_to_new_folio.patch
queue-6.12/net-qrtr-ns-limit-the-maximum-server-registration-per-node.patch
queue-6.12/rust-init-fix-clippy-undocumented_unsafe_blocks-warn.patch
queue-6.12/ksmbd-reset-rcount-per-connection-in-ksmbd_conn_wait_idle_sess_id.patch
queue-6.12/wifi-mt76-mt792x-describe-usb-wfsys-reset-with-a-descriptor.patch
queue-6.12/media-rc-igorplugusb-heed-coherency-rules.patch
queue-6.12/padata-fix-pd-uaf-once-and-for-all.patch
queue-6.12/ksmbd-replace-connection-list-with-hash-table.patch
queue-6.12/rxrpc-fix-potential-uaf-after-skb_unshare-failure.patch
queue-6.12/drm-amdgpu-limit-bo-list-entry-count-to-prevent-reso.patch
queue-6.12/lib-test_hmm-evict-device-pages-on-file-close-to-avoid-use-after-free.patch
queue-6.12/alsa-aoa-skip-devices-with-no-codecs-in-i2sbus_resume.patch
queue-6.12/smb-client-validate-the-whole-dacl-before-rewriting-it-in-cifsacl.patch
queue-6.12/wifi-mwifiex-fix-use-after-free-in-mwifiex_adapter_cleanup.patch
queue-6.12/io_uring-poll-fix-multishot-recv-missing-eof-on-wake.patch
queue-6.12/f2fs-fix-uaf-caused-by-decrementing-sbi-nr_pages-in-f2fs_write_end_io.patch
queue-6.12/media-rc-ttusbir-respect-dma-coherency-rules.patch



More information about the linux-afs mailing list