mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Michael Bommarito <michael.bommarito@gmail.com>
To: Bart Van Assche <bvanassche@acm.org>,
	Jason Gunthorpe <jgg@ziepe.ca>, Leon Romanovsky <leon@kernel.org>
Cc: linux-rdma@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH] RDMA/srp: bound SRP_RSP sense copy by the received length
Date: Tue,  2 Jun 2026 15:46:19 -0400	[thread overview]
Message-ID: <20260602194619.2272486-1-michael.bommarito@gmail.com> (raw)

srp_process_rsp() in drivers/infiniband/ulp/srp/ib_srp.c copies sense
data with the source pointer rsp->data + be32_to_cpu(rsp->resp_data_len),
where resp_data_len is the full 32-bit value supplied by the SRP target
and is never checked against the size of the receive buffer or the
number of bytes actually received (wc->byte_len).

A malicious or compromised SRP target on the InfiniBand/RoCE fabric that
the initiator has logged into can return an SRP_RSP with
SRP_RSP_FLAG_SNSVALID set and resp_data_len set to a large value such as
0xFFFFFFFF. The receive buffer is allocated at the target-chosen
max_ti_iu_len, so the copy source lands far past the allocation.

The memcpy then reads out of bounds of the kzalloc'd receive IU; with
resp_data_len near 0xFFFFFFFF the source is multiple gigabytes past the
buffer and faults.

Pass wc->byte_len into srp_process_rsp() and copy the sense data only
when the response header, the response data, and the sense region fit
within the bytes actually received; otherwise drop the sense and log.
The in-tree iSER and NVMe-RDMA receive paths already bound their parse
by wc->byte_len; this brings ib_srp into line with them.

Fixes: aef9ec39c40c ("IB: Add SCSI RDMA Protocol (SRP) initiator")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---

Impact: a malicious or compromised SRP target the initiator has logged
into can trigger an out-of-bounds read in srp_process_rsp() by returning
an SRP_RSP with SRP_RSP_FLAG_SNSVALID and a large resp_data_len, faulting
the initiator's SRP completion path.

 drivers/infiniband/ulp/srp/ib_srp.c | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index b58868e1cf11c..199d46fb12146 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1932,7 +1932,8 @@ static int srp_post_recv(struct srp_rdma_ch *ch, struct srp_iu *iu)
 	return ib_post_recv(ch->qp, &wr, NULL);
 }
 
-static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp)
+static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp,
+			    u32 byte_len)
 {
 	struct srp_target_port *target = ch->target;
 	struct srp_request *req;
@@ -1973,10 +1974,26 @@ static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp)
 		scmnd->result = rsp->status;
 
 		if (rsp->flags & SRP_RSP_FLAG_SNSVALID) {
-			memcpy(scmnd->sense_buffer, rsp->data +
-			       be32_to_cpu(rsp->resp_data_len),
-			       min_t(int, be32_to_cpu(rsp->sense_data_len),
-				     SCSI_SENSE_BUFFERSIZE));
+			u32 resp_len = be32_to_cpu(rsp->resp_data_len);
+			u32 sense_len = min_t(u32,
+					      be32_to_cpu(rsp->sense_data_len),
+					      SCSI_SENSE_BUFFERSIZE);
+
+			/*
+			 * The sense data starts resp_data_len bytes past the
+			 * response data area.  Both lengths are taken from the
+			 * target controlled response, so reject a response
+			 * whose sense region would run past the bytes actually
+			 * received rather than reading out of bounds of the
+			 * receive buffer.
+			 */
+			if (sizeof(*rsp) + (u64)resp_len + sense_len <= byte_len)
+				memcpy(scmnd->sense_buffer,
+				       rsp->data + resp_len, sense_len);
+			else
+				shost_printk(KERN_ERR, target->scsi_host,
+					     "dropping oversized sense (resp_data_len %u sense_data_len %u) in %u-byte RSP\n",
+					     resp_len, sense_len, byte_len);
 		}
 
 		if (unlikely(rsp->flags & SRP_RSP_FLAG_DIUNDER))
@@ -2086,7 +2103,7 @@ static void srp_recv_done(struct ib_cq *cq, struct ib_wc *wc)
 
 	switch (opcode) {
 	case SRP_RSP:
-		srp_process_rsp(ch, iu->buf);
+		srp_process_rsp(ch, iu->buf, wc->byte_len);
 		break;
 
 	case SRP_CRED_REQ:
-- 
2.53.0


             reply	other threads:[~2026-06-02 19:46 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-02 19:46 Michael Bommarito [this message]
2026-06-02 20:19 ` Bart Van Assche

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260602194619.2272486-1-michael.bommarito@gmail.com \
    --to=michael.bommarito@gmail.com \
    --cc=bvanassche@acm.org \
    --cc=jgg@ziepe.ca \
    --cc=leon@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rdma@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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®