RDMA/rtrs-clt: Validate peer-supplied IO completion msg_id
Subsystems (2)
PATCH 1/1 RDMA/rtrs-clt: Validate peer-supplied IO completion msg_id
process_io_rsp() indexes clt_path->reqs[] with the 19-bit msg_id taken from a WRITE_WITH_IMM immediate. That value is chosen by the peer. The only check was WARN_ON(msg_id >= queue_depth), which still lets a completion run after free_path_reqs() has set reqs to NULL, or against a slot whose FRWR is already gone. Either path dereferences req->mr and can GPF; KASAN reports a null-ptr-deref at offsetof(struct rtrs_clt_io_req, mr).
Treat a missing reqs array, an out-of-range msg_id, or a req without an MR as a protocol error and recover the connection.
--- drivers/infiniband/ulp/rtrs/rtrs-clt.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-)
drivers/infiniband/ulp/rtrs/rtrs-clt.c +16 -5
@@ -489,18 +489,22 @@ static int rtrs_post_send_rdma(struct rtrs_clt_con *con, imm, flags, wr, NULL); } -static void process_io_rsp (struct rtrs_clt_path *clt_path,u32 msg_id, +static bool process_io_rsp (struct rtrs_clt_path *clt_path,u32 msg_id,s16 errno,bool w_inval) {struct rtrs_clt_io_req *req; -if (WARN_ON (msg_id >= clt_path->queue_depth)) -return ; +if (!clt_path->reqs || msg_id >= clt_path->queue_depth) +return false; req = &clt_path->reqs[msg_id]; +if (!req->mr) +return false; +/* Drop need_inv if server responded with send with invalidation */ req->mr->need_inval &= !w_inval;complete_rdma_req (req, errno, true, false); +return true; }static void rtrs_clt_recv_done (struct rtrs_clt_con *con,struct ib_wc *wc)
@@ -562,7 +566,8 @@ static void rtrs_clt_rkey_rsp_done(struct rtrs_clt_con *con, struct ib_wc *wc)if (WARN_ON (buf_id != msg_id)) goto out; clt_path->rbufs[buf_id].rkey =le32_to_cpu (msg->rkey); -process_io_rsp (clt_path, msg_id, err, w_inval); +if (!process_io_rsp (clt_path, msg_id, err, w_inval)) + goto out; }ib_dma_sync_single_for_device (clt_path->s.dev->ib_dev, iu->dma_addr, iu->size,DMA_FROM_DEVICE );
@@ -634,7 +639,13 @@ static void rtrs_clt_rdma_done(struct ib_cq *cq, struct ib_wc *wc) w_inval = (imm_type ==RTRS_IO_RSP_W_INV_IMM );rtrs_from_io_rsp_imm (imm_payload, &msg_id, &err); -process_io_rsp (clt_path, msg_id, err, w_inval); +if (!process_io_rsp (clt_path, msg_id, err, w_inval)) { +rtrs_err (clt_path->clt, +"Invalid IO rsp: msg_id %u queue_depth %zu\n" , + msg_id, clt_path->queue_depth); +rtrs_rdma_error_recovery (con); +return ; + } }else if (imm_type ==RTRS_HB_MSG_IMM ) {WARN_ON (con->c.cid);rtrs_send_hb_ack (&clt_path->s);
---
base-commit: 93f51579e7df248780214094418f205253383cc5
change-id: 20260923-rtrs-warning-inrtrs-clt-rdma-done-3a72d73550b1
Best regards,
Signature · 1 line
Quanye Yang <[email protected]>
[email protected]
AI reviewSashiko has reviewed this patch and found no issues. It looks great!
Quoted 10 lines
From: Quanye Yang <[email protected]>
process_io_rsp()indexes clt_path->reqs[] with the 19-bitmsg_idtaken from aWRITE_WITH_IMMimmediate. That value is chosen by the peer. The only check wasWARN_ON(msg_id >= queue_depth), which still lets a completion run afterfree_path_reqs()has set reqs to NULL, or against a slot whose FRWR is already gone. Either path dereferencesreq->mrand can GPF; KASAN reports a null-ptr-deref atoffsetof(struct rtrs_clt_io_req, mr).
Quoted 7 lines
Treat a missing reqs array, an out-of-range
msg_id, or a req without an MR as a protocol error and recover the connection.Reported-by Farhad Alemi <[email protected]>Link https://lore.kernel.org/r/CA+0ovCiJZz6O8LzsS9Dq1-JE1OE1L_OTA6Mr-WratpUE6jczHw@mail.gmail.com open hereFixes 6a98d71daea1 ("RDMA/rtrs: client: main functionality")Signed-off-by Quanye Yang <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/20260923-rtrs-warning-inrtrs-clt-rdma-done-v1-1-0827a9a77c0b@proton.me?part=1
Quoted 11 lines · On Wed, Sep 23, 2026 at 12:52 PM Quanye Yang via B4 Relay…
From: Quanye Yang <[email protected]>
process_io_rsp()indexes clt_path->reqs[] with the 19-bitmsg_idtaken from aWRITE_WITH_IMMimmediate. That value is chosen by the peer. The only check wasWARN_ON(msg_id >= queue_depth), which still lets a completion run afterfree_path_reqs()has set reqs to NULL, or against a slot whose FRWR is already gone. Either path dereferencesreq->mrand can GPF; KASAN reports a null-ptr-deref atoffsetof(struct rtrs_clt_io_req, mr).
Quoted 7 lines
Treat a missing reqs array, an out-of-range
msg_id, or a req without an MR as a protocol error and recover the connection.Reported-by Farhad Alemi <[email protected]>Link https://lore.kernel.org/r/CA+0ovCiJZz6O8LzsS9Dq1-JE1OE1L_OTA6Mr-WratpUE6jczHw@mail.gmail.com open hereFixes 6a98d71daea1 ("RDMA/rtrs: client: main functionality")Signed-off-by Quanye Yang <[email protected]>
lgtm, thx!
Quoted 69 lines
--- drivers/infiniband/ulp/rtrs/rtrs-clt.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-)drivers/infiniband/ulp/rtrs/rtrs-clt.c +16
-6@@ -489,18 +489,22 @@ static int rtrs_post_send_rdma(struct rtrs_clt_con *con, imm, flags, wr, NULL); } -static void process_io_rsp (struct rtrs_clt_path *clt_path,u32 msg_id, +static bool process_io_rsp (struct rtrs_clt_path *clt_path,u32 msg_id,s16 errno,bool w_inval) {struct rtrs_clt_io_req *req; -if (WARN_ON (msg_id >= clt_path->queue_depth)) -return ; +if (!clt_path->reqs || msg_id >= clt_path->queue_depth) +return false; req = &clt_path->reqs[msg_id]; +if (!req->mr) +return false; +/* Drop need_inv if server responded with send with invalidation */ req->mr->need_inval &= !w_inval;complete_rdma_req (req, errno, true, false); +return true; }static void rtrs_clt_recv_done (struct rtrs_clt_con *con,struct ib_wc *wc)@@ -562,7 +566,8 @@ static void rtrs_clt_rkey_rsp_done(struct rtrs_clt_con *con, struct ib_wc *wc)if (WARN_ON (buf_id != msg_id)) goto out; clt_path->rbufs[buf_id].rkey =le32_to_cpu (msg->rkey); -process_io_rsp (clt_path, msg_id, err, w_inval); +if (!process_io_rsp (clt_path, msg_id, err, w_inval)) + goto out; }ib_dma_sync_single_for_device (clt_path->s.dev->ib_dev, iu->dma_addr, iu->size,DMA_FROM_DEVICE );@@ -634,7 +639,13 @@ static void rtrs_clt_rdma_done(struct ib_cq *cq, struct ib_wc *wc) w_inval = (imm_type ==RTRS_IO_RSP_W_INV_IMM );rtrs_from_io_rsp_imm (imm_payload, &msg_id, &err); -process_io_rsp (clt_path, msg_id, err, w_inval); +if (!process_io_rsp (clt_path, msg_id, err, w_inval)) { +rtrs_err (clt_path->clt, +"Invalid IO rsp: msg_id %u queue_depth %zu\n" , + msg_id, clt_path->queue_depth); +rtrs_rdma_error_recovery (con); +return ; + } }else if (imm_type ==RTRS_HB_MSG_IMM ) {WARN_ON (con->c.cid);rtrs_send_hb_ack (&clt_path->s); ---base-commit:
93f51579e7df248780214094418f205253383cc5
change-id: 20260923-rtrs-warning-inrtrs-clt-rdma-done-3a72d73550b1Best regards,
--
Quanye Yang <[email protected]>
Quoted 13 lines · Quanye Yang
From: Quanye Yang <[email protected]>
process_io_rsp()indexes clt_path->reqs[] with the 19-bitmsg_idtaken from aWRITE_WITH_IMMimmediate. That value is chosen by the peer. The only check wasWARN_ON(msg_id >= queue_depth), which still lets a completion run afterfree_path_reqs()has set reqs to NULL, or against a slot whose FRWR is already gone. Either path dereferencesreq->mrand can GPF; KASAN reports a null-ptr-deref atoffsetof(struct rtrs_clt_io_req, mr).Treat a missing reqs array, an out-of-range
msg_id, or a req without an MR as a protocol error and recover the connection.
Quoted 8 lines
Reported-by Farhad Alemi <[email protected]>Link https://lore.kernel.org/r/CA+0ovCiJZz6O8LzsS9Dq1-JE1OE1L_OTA6Mr-WratpUE6jczHw@mail.gmail.com open hereFixes 6a98d71daea1 ("RDMA/rtrs: client: main functionality")Signed-off-by Quanye Yang <[email protected]>Reviewed-by Jack Wang <[email protected]>--- drivers/infiniband/ulp/rtrs/rtrs-clt.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-)
Applied to for-next, thanks
Jason