[PATCH RFC v3] rxrpc: Fix use-after-free in rxrpc_destroy_all_peers()

"syzbot" <[email protected]>
Newsgroups dev.linux.lists.syzbot
Message-ID <[email protected]>
During network namespace teardown, rxrpc_destroy_all_peers() iterates over
the rxnet->peer_hash table to print leaked peers. However, it does so
without holding rxnet->peer_hash_lock. This allows a race condition with
asynchronous peer destruction, where RCU callbacks concurrently remove
peers from the hash table and free them. When rxrpc_destroy_all_peers()
accesses the freed peer, it results in a KASAN slab-use-after-free.

BUG: KASAN: slab-use-after-free in rxrpc_destroy_all_peers+0xcc/0x150
net/rxrpc/peer_object.c:461
Read of size 8 at addr ffff88811089e420 by task kworker/u8:1/13
Call Trace:
 <TASK>
 rxrpc_destroy_all_peers+0xcc/0x150 net/rxrpc/peer_object.c:461
 rxrpc_exit_net+0x7f/0xc0 net/rxrpc/net_ns.c:114
 ops_exit_list net/core/net_namespace.c:199 [inline]
 ops_undo_list+0x43d/0x8d0 net/core/net_namespace.c:252
 cleanup_net+0x572/0x810 net/core/net_namespace.c:702
 process_one_work kernel/workqueue.c:3322 [inline]
 process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
 worker_thread+0x92d/0xe10 kernel/workqueue.c:3486
 kthread+0x388/0x470 kernel/kthread.c:436
 ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
 </TASK>

To fix the slab-use-after-free, acquire rxnet->peer_hash_lock with
spin_lock_bh() while iterating over rxnet->peer_hash in
rxrpc_destroy_all_peers().

Additionally, insert rcu_barrier() in rxrpc_exit_net() prior to destroying
peers and local endpoints. Without rcu_barrier(), rxrpc_destroy_all_peers()
races with pending RCU callbacks that drop peer and local references,
logging spurious leak warnings. Furthermore, this missing synchronization
causes a downstream panic hazard in rxrpc_destroy_all_locals() because
in-flight peer releases leave rxnet->local_endpoints populated. Calling
rcu_barrier() ensures all pending RCU callbacks that drop peer and local
references complete prior to leak checks and local endpoint destruction.

Fixes: 17226f124038 ("rxrpc: Fix leak of rxrpc_peer objects")
Assisted-by: Gemini:gemini-3.6-flash Gemini:gemini-3.1-pro-preview syzbot
Reported-by: [email protected]
Closes: https://syzkaller.appspot.com/bug?extid=c876adfab6362679008c
Link: https://syzkaller.appspot.com/ai_job?id=7fecbeb2-cd9b-4ca2-8149-48663e20b153
To: "David S. Miller" <[email protected]>
To: "David Howells" <[email protected]>
To: "Eric Dumazet" <[email protected]>
To: "Jakub Kicinski" <[email protected]>
To: <[email protected]>
To: "Marc Dionne" <[email protected]>
To: <[email protected]>
To: "Paolo Abeni" <[email protected]>
Cc: "Simon Horman" <[email protected]>
Cc: <[email protected]>

---
v3:
- Added inline comments explaining the purpose of rcu_barrier() in rxrpc_exit_net() and peer_hash_lock acquisition in rxrpc_destroy_all_peers().

v2:
- Added rcu_barrier() in rxrpc_exit_net() before peer and local endpoint teardown.
- Updated commit message to detail how rcu_barrier() prevents spurious leak warnings and downstream panics in rxrpc_destroy_all_locals().
https://lore.kernel.org/all/[email protected]/T/

v1:
https://lore.kernel.org/all/[email protected]/T/
---
diff --git a/net/rxrpc/net_ns.c b/net/rxrpc/net_ns.c
index 9a9834145..c00cddfd3 100644
--- a/net/rxrpc/net_ns.c
+++ b/net/rxrpc/net_ns.c
@@ -111,6 +111,11 @@ static __net_exit void rxrpc_exit_net(struct net *net)
 	timer_delete_sync(&rxnet->peer_keepalive_timer);
 	rxrpc_destroy_all_calls(rxnet);
 	rxrpc_destroy_all_connections(rxnet);
+	/*
+	 * Wait for pending RCU callbacks that drop peer and local
+	 * references to avoid spurious leak warnings and panics.
+	 */
+	rcu_barrier();
 	rxrpc_destroy_all_peers(rxnet);
 	rxrpc_destroy_all_locals(rxnet);
 	proc_remove(rxnet->proc_net);
diff --git a/net/rxrpc/peer_object.c b/net/rxrpc/peer_object.c
index fa9a406e1..32da76256 100644
--- a/net/rxrpc/peer_object.c
+++ b/net/rxrpc/peer_object.c
@@ -454,6 +454,12 @@ void rxrpc_destroy_all_peers(struct rxrpc_net *rxnet)
 	struct rxrpc_peer *peer;
 	int i;
 
+	/*
+	 * The lock is needed to prevent use-after-free if a peer is being
+	 * destroyed concurrently by an RCU callback.
+	 */
+	spin_lock_bh(&rxnet->peer_hash_lock);
+
 	for (i = 0; i < HASH_SIZE(rxnet->peer_hash); i++) {
 		if (hlist_empty(&rxnet->peer_hash[i]))
 			continue;
@@ -465,6 +471,8 @@ void rxrpc_destroy_all_peers(struct rxrpc_net *rxnet)
 			       &peer->srx.transport);
 		}
 	}
+
+	spin_unlock_bh(&rxnet->peer_hash_lock);
 }
 
 /**


base-commit: db2ddb87143519e20a95aa36c60b36107b736a58
-- 
This is an AI-generated patch subject to moderation.
Reply with '#syz upstream' to Sign-off the patch as a human author
and send it to the upstream kernel mailing lists.
Reply with '#syz reject' to reject it ('#syz unreject' to undo).

See https://goo.gle/syzbot-ai-patches for information about AI-generated patches.
You can comment on the patch as usual, syzbot will try to address
the comments and send a new version of the patch if necessary.
syzbot engineers can be reached at [email protected].
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.