[PATCH] afs: Fix server UAF during peer appdata lookup

From: Jérémy Jean

Date: Tue Nov 03 2026 - 18:28:17 EST


AF_RXRPC does not take a reference on objects stored in peer appdata, so
afs_find_server() can race with afs_server_destroyer(): it may read an old
server pointer and pass it to afs_use_server() after the object has been
freed through RCU. KASAN reports the UAF as:

BUG: KASAN: slab-use-after-free in afs_use_server+0x2e/0x250
Write of size 4 at addr ffff888002b910f0 by task afs-peer-uaf/87

Keep the peer appdata lookup under RCU and use
__refcount_inc_not_zero() to get a server reference before leaving RCU.

Fixes: 40e8b52fe8c8 ("afs: Use the per-peer app data provided by rxrpc")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Jérémy Jean <Jeremy.Jean@xxxxxxxxxxxxxxxxx>
---
fs/afs/server.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/fs/afs/server.c b/fs/afs/server.c
index 189138bd6d712..506119f9b1d32 100644
--- a/fs/afs/server.c
+++ b/fs/afs/server.c
@@ -23,11 +23,21 @@ static void afs_server_destroyer(struct work_struct *work);
*/
struct afs_server *afs_find_server(const struct rxrpc_peer *peer)
{
- struct afs_server *server = (struct afs_server *)rxrpc_kernel_get_peer_data(peer);
+ struct afs_server *server;
+ unsigned int a;
+ int r;

- if (!server)
- return NULL;
- return afs_use_server(server, false, afs_server_trace_use_cm_call);
+ rcu_read_lock();
+ server = (struct afs_server *)rxrpc_kernel_get_peer_data(peer);
+ if (server && __refcount_inc_not_zero(&server->ref, &r)) {
+ a = atomic_inc_return(&server->active);
+ trace_afs_server(server->debug_id, r + 1, a,
+ afs_server_trace_use_cm_call);
+ } else {
+ server = NULL;
+ }
+ rcu_read_unlock();
+ return server;
}

/*
--
2.47.3