* [PATCH] rxrpc: Serialize client connection IDR updates
@ 2026-10-30 4:21 Kyle Zeng
2026-10-30 4:23 ` netdev-bot+sinfo
0 siblings, 1 reply; 2+ messages in thread
From: Kyle Zeng @ 2026-10-30 4:21 UTC (permalink / raw)
To: linux-afs
Cc: David Howells, Marc Dionne, netdev, linux-kernel, outbounddisclosures
The common connection destructor calls rxrpc_kill_client_conn() for
service connections as well as client connections. A service connection
gets its CID from the peer and never owns an entry in local->conn_ids.
Its destruction can therefore remove an unrelated client connection.
The final reference can be dropped by the service reaper or a call
destruction worker, outside the owning local endpoint's I/O thread.
Client connection destruction can also run off-thread, and can remove an
ID already released by rxrpc_unbundle_conn(). These writers can race
idr_alloc_cyclic(), corrupting the radix tree and its RCU callbacks. A
second removal can also delete a new owner after an ID has been reused.
Only run client cleanup for client connections. Restore a per-local IDR
writer lock and the client-ID ownership flag, clearing the flag under the
lock when releasing the ID. Serialize IDR destruction with the same
lock. This covers deferred final puts without changing connection
expiry or the RCU lookup path.
Fixes: 9d35d880e0e4 ("rxrpc: Move client call connection to the I/O thread")
Signed-off-by: Kyle Zeng <kylebot@openai.com>
---
I have a reproducer for this issue and can share via DM
net/rxrpc/ar-internal.h | 2 ++
net/rxrpc/conn_client.c | 17 ++++++++++++++---
net/rxrpc/conn_object.c | 3 ++-
net/rxrpc/local_object.c | 1 +
4 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 865f05fe37ab..5e49fe0f4a6f 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -377,6 +377,7 @@ struct rxrpc_local {
bool dead;
bool service_closed; /* Service socket closed */
struct idr conn_ids; /* List of connection IDs */
+ spinlock_t conn_ids_lock; /* Lock for conn_ids */
struct list_head new_client_calls; /* Newly created client calls need connection */
spinlock_t client_call_lock; /* Lock for ->new_client_calls */
struct sockaddr_rxrpc srx; /* local address */
@@ -472,6 +473,7 @@ enum rxrpc_call_completion {
* Bits in the connection flags.
*/
enum rxrpc_conn_flag {
+ RXRPC_CONN_HAS_IDR, /* Has a client conn ID assigned */
RXRPC_CONN_IN_SERVICE_CONNS, /* Conn is in peer->service_conns */
RXRPC_CONN_DONT_REUSE, /* Don't reuse this connection */
RXRPC_CONN_PROBING_FOR_UPGRADE, /* Probing for service upgrade */
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index 48519f0de185..4c2db83fceae 100644
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -40,12 +40,16 @@ static void rxrpc_activate_bundle(struct rxrpc_bundle *bundle)
}
/*
- * Release a connection ID for a client connection.
+ * Release a client connection ID exactly once. The final reference may be
+ * dropped outside the local endpoint's I/O thread.
*/
static void rxrpc_put_client_connection_id(struct rxrpc_local *local,
struct rxrpc_connection *conn)
{
- idr_remove(&local->conn_ids, conn->proto.cid >> RXRPC_CIDSHIFT);
+ spin_lock(&local->conn_ids_lock);
+ if (test_and_clear_bit(RXRPC_CONN_HAS_IDR, &conn->flags))
+ idr_remove(&local->conn_ids, conn->proto.cid >> RXRPC_CIDSHIFT);
+ spin_unlock(&local->conn_ids_lock);
}
/*
@@ -56,6 +60,7 @@ static void rxrpc_destroy_client_conn_ids(struct rxrpc_local *local)
struct rxrpc_connection *conn;
int id;
+ spin_lock(&local->conn_ids_lock);
if (!idr_is_empty(&local->conn_ids)) {
idr_for_each_entry(&local->conn_ids, conn, id) {
pr_err("AF_RXRPC: Leaked client conn %p {%d}\n",
@@ -65,6 +70,7 @@ static void rxrpc_destroy_client_conn_ids(struct rxrpc_local *local)
}
idr_destroy(&local->conn_ids);
+ spin_unlock(&local->conn_ids_lock);
}
/*
@@ -162,15 +168,20 @@ rxrpc_alloc_client_connection(struct rxrpc_bundle *bundle)
if (!conn)
return ERR_PTR(-ENOMEM);
+ spin_lock(&local->conn_ids_lock);
id = idr_alloc_cyclic(&local->conn_ids, conn, 1, 0x40000000,
GFP_ATOMIC | __GFP_NOWARN);
+ if (id >= 0) {
+ conn->proto.cid = id << RXRPC_CIDSHIFT;
+ set_bit(RXRPC_CONN_HAS_IDR, &conn->flags);
+ }
+ spin_unlock(&local->conn_ids_lock);
if (id < 0) {
kfree(conn);
return ERR_PTR(id);
}
refcount_set(&conn->ref, 1);
- conn->proto.cid = id << RXRPC_CIDSHIFT;
conn->proto.epoch = local->rxnet->epoch;
conn->out_clientflag = RXRPC_CLIENT_INITIATED;
conn->bundle = rxrpc_get_bundle(bundle, rxrpc_bundle_get_client_conn);
diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c
index 0ece717db0f8..bae95cadd72b 100644
--- a/net/rxrpc/conn_object.c
+++ b/net/rxrpc/conn_object.c
@@ -332,7 +332,8 @@ static void rxrpc_clean_up_connection(struct work_struct *work)
rxrpc_purge_queue(&conn->rx_queue);
rxrpc_free_skb(conn->tx_response, rxrpc_skb_put_response);
- rxrpc_kill_client_conn(conn);
+ if (rxrpc_conn_is_client(conn))
+ rxrpc_kill_client_conn(conn);
conn->security->clear(conn);
key_put(conn->key);
diff --git a/net/rxrpc/local_object.c b/net/rxrpc/local_object.c
index 169f9dfdaa77..5a7acd595e11 100644
--- a/net/rxrpc/local_object.c
+++ b/net/rxrpc/local_object.c
@@ -140,6 +140,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct net *net,
memcpy(&local->srx, srx, sizeof(*srx));
local->srx.srx_service = 0;
idr_init(&local->conn_ids);
+ spin_lock_init(&local->conn_ids_lock);
get_random_bytes(&tmp, sizeof(tmp));
tmp &= 0x3fffffff;
if (tmp == 0)
base-commit: d89e1d186ec9271bf78e62771779e9fc03bf0fc3
--
2.56.0
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [PATCH] rxrpc: Serialize client connection IDR updates
2026-10-30 4:21 [PATCH] rxrpc: Serialize client connection IDR updates Kyle Zeng
@ 2026-10-30 4:23 ` netdev-bot+sinfo
0 siblings, 0 replies; 2+ messages in thread
From: netdev-bot+sinfo @ 2026-10-30 4:23 UTC (permalink / raw)
To: Kyle Zeng
Cc: linux-afs, David Howells, Marc Dionne, netdev, linux-kernel,
outbounddisclosures
Hi!
This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:
- How the issue was discovered, e.g. hit in production, hit during
development, syzbot report, manual code inspection, LLM or static
analysis tool scan.
Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.
The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-30 4:23 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-30 4:21 [PATCH] rxrpc: Serialize client connection IDR updates Kyle Zeng
2026-10-30 4:23 ` netdev-bot+sinfo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®