[PATCH] RDMA/rtrs-clt: Reject a zero queue_depth in the connection response

From: Yehyeong Lee

Date: Tue Sep 29 2026 - 01:44:17 EST


rtrs_rdma_conn_established() stores the queue_depth the server advertises
in its cid 0 connection response without checking that it is usable. The
only bound it ever had was an upper one, dropped in commit 0e8558476faf
("RDMA/rtrs: Avoid Wtautological-constant-out-of-range-compare") because
it cannot fail for a u16; a lower bound was never there. A server that
reports zero therefore leaves clt_path->queue_depth at 0, and setting up
the first I/O connection trips

if (WARN_ON(!clt_path->queue_depth))

in create_con_cq_qp(). The connect is aborted, but the peer has already
tainted the kernel, and on a kernel built with panic_on_warn it panics
outright -- all from one field in the response to a connect.

The rbufs array is sized from the same value one statement earlier, so it
is also allocated with zero elements, which kzalloc_objs() returns as
ZERO_SIZE_PTR. Nothing dereferences it: the WARN aborts the connect
before any buffer is registered and the path is then freed, and a path
that already carries a nonzero depth is caught on reconnect by the
existing "queue depth changed" test. The WARN is the whole of the damage.

The in-tree server never sends zero -- check_module_params() rejects
sess_queue_depth < 1 -- so this needs a hostile or broken server, but the
client should not rely on the peer for that. Reject it before rbufs is
sized from it and before it is stored, but after the existing "queue depth
changed" test, so that a server which drops a nonzero depth to zero across
a reconnect still takes that path and still disables auto-reconnect.

Reproduced with rnbd-client over soft-RoCE against an rtrs-server patched
to advertise queue_depth = 0:

WARNING: drivers/infiniband/ulp/rtrs/rtrs-clt.c:1688 at
rtrs_clt_rdma_cm_handler+0x1b27/0x29f0, CPU#0: kworker/u8:5/56
Modules linked in:
CPU: 0 UID: 0 PID: 56 Comm: kworker/u8:5 Not tainted
7.3.0-rc5-nvmerdma-atk-g72d3fcf802c4-dirty #23 PREEMPT(lazy)
Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix,
1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
Workqueue: ib_addr process_one_req
RIP: 0010:rtrs_clt_rdma_cm_handler+0x1b27/0x29f0
Call Trace:
<TASK>
? arch_stack_walk+0x94/0xf0
? __pfx_rtrs_clt_rdma_cm_handler+0x10/0x10
? ret_from_fork_asm+0x1a/0x30
? process_one_work+0x6b4/0x10e0
? stack_trace_save+0x8e/0xc0
? __pfx_stack_trace_save+0x10/0x10
? __kasan_slab_free+0x43/0x70
? stack_depot_save_flags+0x29/0x7e0
? worker_thread+0x45b/0xd10
? kthread+0x2c8/0x3b0
? ret_from_fork+0x36e/0x5a0
? _raw_spin_lock_irqsave+0x86/0xe0
cma_cm_event_handler+0x3e/0x240
addr_handler+0x1e0/0x300
? __pfx_addr_handler+0x10/0x10
? pick_task_fair+0x46f/0x1a60
process_one_req+0x10d/0x510
? finish_task_switch.isra.0+0x1d9/0xa70
? __pfx_process_one_req+0x10/0x10
process_one_work+0x6b4/0x10e0
? __pfx___schedule+0x10/0x10
? __pfx_process_one_work+0x10/0x10
? _raw_spin_lock_irq+0x81/0xe0
? __pfx_process_one_req+0x10/0x10
? assign_work+0x11d/0x370
worker_thread+0x45b/0xd10
? __pfx_worker_thread+0x10/0x10
? __pfx_worker_thread+0x10/0x10
kthread+0x2c8/0x3b0
? recalc_sigpending+0x15c/0x1e0
? __pfx_kthread+0x10/0x10
ret_from_fork+0x36e/0x5a0
? __pfx_ret_from_fork+0x10/0x10
? __switch_to+0x572/0xdd0
? __pfx_kthread+0x10/0x10
ret_from_fork_asm+0x1a/0x30
</TASK>
---[ end trace 0000000000000000 ]---

rtrs_client L2644: <s1>: init_conns() failed: err=-EINVAL
path=<invalid address family>@ip:10.0.0.1 [rxe0:1]

With the check in place the same server is refused without a splat, and an
honest server is unaffected:

rtrs_client L1870: <s1>: Invalid RTRS message: queue_depth is 0
rtrs_client L2649: <s1>: init_conns() failed: err=-ECONNRESET
path=<invalid address family>@ip:10.0.0.1 [:0]

Fixes: 6a98d71daea1 ("RDMA/rtrs: client: main functionality")
Reported-by: Farhad Alemi <farhad.alemi@xxxxxxxxxxxx>
Closes: https://lore.kernel.org/linux-rdma/CA+0ovCg_sG8gaZXXj9zmOrpxRt=8+-x9wvycVNUKwWmMbr6-Yg@xxxxxxxxxxxxxx/
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Yehyeong Lee <yhlee@xxxxxxxxxxxxxxxxxx>
---
drivers/infiniband/ulp/rtrs/rtrs-clt.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
index eac38b57b00d7..5c2c65c15a65a 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
@@ -1866,6 +1866,11 @@ static int rtrs_rdma_conn_established(struct rtrs_clt_con *con,
return -ECONNRESET;
}

+ if (!queue_depth) {
+ rtrs_err(clt, "Invalid RTRS message: queue_depth is 0\n");
+ return -ECONNRESET;
+ }
+
if (!clt_path->rbufs) {
clt_path->rbufs = kzalloc_objs(*clt_path->rbufs,
queue_depth);
--
2.43.0