[PATCH] RDMA/rtrs-srv: Reject usr_len larger than off in process_{read,write}

From: Zhenhao Wan

Date: Tue Jun 16 2026 - 12:58:06 EST


process_read() and process_write() derive the data length of an I/O
request as:

usr_len = le16_to_cpu(req->usr_len);
data_len = off - usr_len;

off comes from the RDMA-Write-with-imm immediate and is only bounded
above (off < max_chunk_size) in rtrs_srv_rdma_done(). usr_len is read
from the chunk buffer the remote peer fills over RDMA, so it is peer
controlled over the full u16 range and is not checked against off.

If a peer sends usr_len > off, the size_t subtraction underflows and
the pointer data + data_len passed to the ->rdma_ev() callback points
before the chunk. The in-tree consumer rnbd_srv_rdma_ev() dereferences
it as the message header (le16_to_cpu(hdr->type)) before validating it;
this is an out-of-bounds read reachable from a remote peer.

Reject usr_len > off before computing data_len in both paths, via the
existing send_err_msg path. For a well-formed request off is the total
length data_len + usr_len, so usr_len <= off holds and valid requests
are unaffected.

Fixes: 9cb837480424 ("RDMA/rtrs: server: main functionality")
Reported-by: Yuhao Jiang <danisjiang@xxxxxxxxx>
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Zhenhao Wan <whi4ed0g@xxxxxxxxx>
---
drivers/infiniband/ulp/rtrs/rtrs-srv.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)

diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
index 6482ad859bd1..ec3f6c2fb0b9 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
@@ -1067,6 +1067,13 @@ static void process_read(struct rtrs_srv_con *con,
id->msg_id = buf_id;
id->rd_msg = msg;
usr_len = le16_to_cpu(msg->usr_len);
+ if (usr_len > off) {
+ rtrs_err_rl(s,
+ "Processing read request failed, invalid usr_len %zu > off %u\n",
+ usr_len, off);
+ ret = -EINVAL;
+ goto send_err_msg;
+ }
data_len = off - usr_len;
data = page_address(srv->chunks[buf_id]);
ret = ctx->ops.rdma_ev(srv->priv, id, data, data_len,
@@ -1120,6 +1127,13 @@ static void process_write(struct rtrs_srv_con *con,
id->msg_id = buf_id;

usr_len = le16_to_cpu(req->usr_len);
+ if (usr_len > off) {
+ rtrs_err_rl(s,
+ "Processing write request failed, invalid usr_len %zu > off %u\n",
+ usr_len, off);
+ ret = -EINVAL;
+ goto send_err_msg;
+ }
data_len = off - usr_len;
data = page_address(srv->chunks[buf_id]);
ret = ctx->ops.rdma_ev(srv->priv, id, data, data_len,

---
base-commit: a48671671df5158a0b8e564cd509e04a090a941b
change-id: 20260617-rtrs-srv-usr-len-underflow-e51072f76985

Best regards,
--
Zhenhao Wan <whi4ed0g@xxxxxxxxx>