[BUG] rxrpc: Client connection leak and BUG() call during kernel IO thread exit

From: Anderson Nascimento

Date: Wed Apr 01 2026 - 00:20:58 EST


Hello,

I have identified a reliable way to trigger a BUG() in the RxRPC
protocol at rxrpc_destroy_client_conn_ids(). This occurs because the
kernel IO thread can exit while there are still active connection
objects registered in the local IDR (local->conn_ids).

I did a quick analysis and the result is the following. When the IO
thread exits, it calls rxrpc_destroy_local(), which in turn calls
rxrpc_clean_up_local_conns(). However, that function only iterates
over the local->idle_client_conns list. If a connection was recently
created by rxrpc_connect_client_calls() (via
rxrpc_alloc_client_connection()) but has not yet been deactivated or
moved to the idle list, it is completely missed during this cleanup
phase.

Because the connection remains in the IDR, the subsequent call to
rxrpc_destroy_client_conn_ids() finds the entry, logs an "AF_RXRPC:
Leaked client conn" error, and hits a BUG().

I can reliably reproduce this using a client and server where the
server calls close() immediately after sendmsg().

My suggestion for a fix is to update rxrpc_clean_up_local_conns() to
check the local IDR instead of just the idle list, ensuring all
allocated connections are reaped during teardown. I don't have the
time to properly test a patch or verify if the teardown for a
brand-new conn differs significantly from an idle one, so I wanted to
report my quick analysis to the maintainers. I tested on Fedora 43 on
kernel 6.18.

420 void rxrpc_destroy_local(struct rxrpc_local *local)
421 {
...
433 rxrpc_clean_up_local_conns(local);
...
451 rxrpc_purge_client_connections(local);
...
453 }

813 void rxrpc_clean_up_local_conns(struct rxrpc_local *local)
814 {
815 struct rxrpc_connection *conn;
...
823 while ((conn = list_first_entry_or_null(&local->idle_client_conns,
824 struct
rxrpc_connection, cache_link))) {
825 list_del_init(&conn->cache_link);
826 atomic_dec(&conn->active);
827 trace_rxrpc_client(conn, -1, rxrpc_client_discard);
828 rxrpc_unbundle_conn(conn);
829 rxrpc_put_connection(conn, rxrpc_conn_put_local_dead);
830 }
...
833 }

54 static void rxrpc_destroy_client_conn_ids(struct rxrpc_local *local)
55 {
56 struct rxrpc_connection *conn;
57 int id;
58
59 if (!idr_is_empty(&local->conn_ids)) {
60 idr_for_each_entry(&local->conn_ids, conn, id) {
61 pr_err("AF_RXRPC: Leaked client conn %p {%d}\n",
62 conn, refcount_read(&conn->ref));
63 }
64 BUG();
65 }
66
67 idr_destroy(&local->conn_ids);
68 }

[88656.300130] rxrpc: AF_RXRPC: Leaked client conn 00000000cf1d5a14 {1}
[88656.300702] ------------[ cut here ]------------
[88656.301099] kernel BUG at net/rxrpc/conn_client.c:64!
[88656.301442] Oops: invalid opcode: 0000 [#17] SMP NOPTI
[88656.301765] CPU: 0 UID: 0 PID: 3989526 Comm: krxrpcio/7001 Tainted:
G D W 6.18.13-200.fc43.x86_64 #1 PREEMPT(lazy)
[88656.302039] Tainted: [D]=DIE, [W]=WARN
[88656.302323] Hardware name: VMware, Inc. VMware Virtual
Platform/440BX Desktop Reference Platform, BIOS 6.00 11/12/2020
[88656.302599] RIP: 0010:rxrpc_purge_client_connections+0x58/0xa0 [rxrpc]

Regards,

--
Anderson Nascimento
Allele Security Intelligence
https://www.allelesecurity.com