Linux RDMA and InfiniBand development
 help / color / mirror / Atom feed
* [PATCH v2 RESEND 0/2] RDMA/srp: bound the receive IU the target asks for
@ 2026-10-26  5:54 Yehyeong Lee
  2026-10-26  5:54 ` [PATCH v2 RESEND 1/2] RDMA/srp: refuse a target that cannot receive an SRP_RSP Yehyeong Lee
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Yehyeong Lee @ 2026-10-26  5:54 UTC (permalink / raw)
  To: Bart Van Assche
  Cc: Leon Romanovsky, Jason Gunthorpe, linux-rdma, linux-kernel,
	stable, yhlee

The target decides how large the initiator's receive buffers are, and the
initiator never checks the answer.

srp_cm_rep_handler() takes max_ti_iu_len out of the SRP_LOGIN_RSP and
srp_alloc_iu_bufs() sizes every receive IU with it. The first patch refuses
a login that reports less than an SRP_RSP, because such a login hands the
receive path undersized buffers, and a report of zero is worse: kzalloc()
answers it with ZERO_SIZE_PTR, which ib_dma_map_single() accepts on a
virtually mapped transport without looking at the length.

The second patch stops srp_recv_done() from syncing those buffers with
ch->max_ti_iu_len. The receive ring is allocated once and kept across a
reconnect while max_ti_iu_len is taken from every login response, so a
target that reports a larger value the second time around makes the driver
sync past the end of the mapping. iu->size is the length that was mapped,
and the length srp_post_recv() posts.

Resending as a standalone thread; the v2 I sent earlier went out
In-Reply-To v1 by mistake. No code changes. Apologies for the noise.

Changes since v1:
1/2 unchanged. Dropped v1 2/2 (drop a truncated SRP_RSP): the floor makes
the buffer always >= sizeof(srp_rsp) so there is no out-of-bounds read, and
dropping the response would lose its req_lim_delta credit (per review). New
2/2 bounds the two srp_recv_done() DMA syncs to iu->size, the reconnect
case review noted 1/2 did not cover.

Yehyeong Lee (2):
  RDMA/srp: refuse a target that cannot receive an SRP_RSP
  RDMA/srp: do not DMA-sync a receive IU past its mapped length

 drivers/infiniband/ulp/srp/ib_srp.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)


base-commit: 21a7f44fd0765fcc5194130b28767786eba1d1e7

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 RESEND 1/2] RDMA/srp: refuse a target that cannot receive an SRP_RSP
  2026-10-26  5:54 [PATCH v2 RESEND 0/2] RDMA/srp: bound the receive IU the target asks for Yehyeong Lee
@ 2026-10-26  5:54 ` Yehyeong Lee
  2026-10-26  9:00   ` sashiko-bot
  2026-10-26  5:54 ` [PATCH v2 RESEND 2/2] RDMA/srp: do not DMA-sync a receive IU past its mapped length Yehyeong Lee
  2026-10-26 17:16 ` [PATCH v2 RESEND 0/2] RDMA/srp: bound the receive IU the target asks for Bart Van Assche
  2 siblings, 1 reply; 6+ messages in thread
From: Yehyeong Lee @ 2026-10-26  5:54 UTC (permalink / raw)
  To: Bart Van Assche
  Cc: Leon Romanovsky, Jason Gunthorpe, linux-rdma, linux-kernel,
	stable, yhlee

srp_cm_rep_handler() takes max_ti_iu_len straight from the target's
SRP_LOGIN_RSP and srp_alloc_iu_bufs() then sizes every receive IU with it,
so the target alone decides how large the initiator's receive buffers are.
Nothing enforces a lower bound.

The initiator parses a 36 byte header out of those buffers. A target that
reports a smaller max_ti_iu_len gets undersized buffers, and the header
reads in srp_process_rsp() then run past the allocation. A report of zero
is worse, because kzalloc() answers it with ZERO_SIZE_PTR, and on a
transport that maps addresses virtually ib_dma_map_single() returns that
pointer without looking at the length and ib_dma_mapping_error() reports
success, so the buffer reaches srp_recv_done() and the read of the opcode
is already out of bounds.

  BUG: KASAN: slab-out-of-bounds in srp_process_rsp+0x757/0xbe0
  Read of size 4 at addr ffff88800243f120 by task kunit_try_catch/42

  CPU: 0 UID: 0 PID: 42 Comm: kunit_try_catch Tainted: G                 N   7.3.0-13249-gcea86339412a-dirty #2 PREEMPT(lazy)
  Tainted: [N]=TEST
  Call Trace:
   <TASK>
   dump_stack_lvl+0x3f/0x50
   print_report+0xcd/0x620
   ? vprintk_emit+0x21d/0x380
   ? srp_process_rsp+0x757/0xbe0
   kasan_report+0xde/0x110
   ? srp_process_rsp+0x757/0xbe0
   srp_process_rsp+0x757/0xbe0
   srp_oob33_test+0x305/0x700
   ? __pfx_srp_oob33_test+0x10/0x10
   ? __set_cpus_allowed_ptr+0x181/0x240
   ? __pfx_read_tsc+0x10/0x10
   ? ktime_get_ts64+0x192/0x250
   kunit_try_run_case+0x1ca/0x4b0
   ? __pfx_kunit_try_run_case+0x10/0x10
   ? kthread_affine_node+0x24b/0x370
   ? __pfx_kthread_affine_node+0x10/0x10
   ? __pfx_kunit_try_run_case+0x10/0x10
   ? __pfx_kunit_generic_run_threadfn_adapter+0x10/0x10
   kunit_generic_run_threadfn_adapter+0x7b/0xe0
   kthread+0x36e/0x500
   ? __pfx_kthread+0x10/0x10
   ret_from_fork+0x34d/0x620
   ? __pfx_ret_from_fork+0x10/0x10
   ? __switch_to+0x22/0xdd0
   ? __pfx_kthread+0x10/0x10
   ret_from_fork_asm+0x19/0x30
   </TASK>

  Allocated by task 42:
   kasan_save_stack+0x33/0x60
   kasan_save_track+0x14/0x30
   __kasan_kmalloc+0x8f/0xa0
   __kmalloc_noprof+0x179/0x3b0
   srp_alloc_iu.constprop.0+0x69/0x5c0
   srp_cm_rep_handler+0xc2e/0x1bb0
   srp_test_login+0xc8/0x630
   srp_oob33_test+0xaa/0x700
   kunit_try_run_case+0x1ca/0x4b0
   kunit_generic_run_threadfn_adapter+0x7b/0xe0
   kthread+0x36e/0x500
   ret_from_fork+0x34d/0x620
   ret_from_fork_asm+0x19/0x30

  The buggy address belongs to the object at ffff88800243f100
   which belongs to the cache kmalloc-64 of size 64
  The buggy address is located 32 bytes inside of
   allocated 33-byte region [ffff88800243f100, ffff88800243f121)

The KUnit harness that forces this is not part of this patch.

Refuse the login instead. Both the largest messages the initiator parses,
SRP_RSP and SRP_AER_REQ, are 36 bytes, and a target that cannot send one
cannot speak the protocol, so nothing that works today is turned away.

Fixes: aef9ec39c47f ("IB: Add SCSI RDMA Protocol (SRP) initiator")
Cc: stable@vger.kernel.org
Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
---
 drivers/infiniband/ulp/srp/ib_srp.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 5811f02df9805..a85d28b95306a 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -2379,6 +2379,13 @@ static void srp_cm_rep_handler(struct ib_cm_id *cm_id,
 
 	if (lrsp->opcode == SRP_LOGIN_RSP) {
 		ch->max_ti_iu_len = be32_to_cpu(lrsp->max_ti_iu_len);
+		if (ch->max_ti_iu_len < sizeof(struct srp_rsp)) {
+			shost_printk(KERN_ERR, target->scsi_host, PFX
+				     "Target reported max_ti_iu_len %u, too small for a %zu byte SRP_RSP\n",
+				     ch->max_ti_iu_len, sizeof(struct srp_rsp));
+			ret = -ECONNRESET;
+			goto error;
+		}
 		ch->req_lim       = be32_to_cpu(lrsp->req_lim_delta);
 		ch->use_imm_data  = srp_use_imm_data &&
 			(lrsp->rsp_flags & SRP_LOGIN_RSP_IMMED_SUPP);

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 RESEND 2/2] RDMA/srp: do not DMA-sync a receive IU past its mapped length
  2026-10-26  5:54 [PATCH v2 RESEND 0/2] RDMA/srp: bound the receive IU the target asks for Yehyeong Lee
  2026-10-26  5:54 ` [PATCH v2 RESEND 1/2] RDMA/srp: refuse a target that cannot receive an SRP_RSP Yehyeong Lee
@ 2026-10-26  5:54 ` Yehyeong Lee
  2026-10-26  9:08   ` sashiko-bot
  2026-10-26 17:16 ` [PATCH v2 RESEND 0/2] RDMA/srp: bound the receive IU the target asks for Bart Van Assche
  2 siblings, 1 reply; 6+ messages in thread
From: Yehyeong Lee @ 2026-10-26  5:54 UTC (permalink / raw)
  To: Bart Van Assche
  Cc: Leon Romanovsky, Jason Gunthorpe, linux-rdma, linux-kernel,
	stable, yhlee

srp_recv_done() syncs the receive IU with ch->max_ti_iu_len, but the IU
was mapped with iu->size.  Those are the same value only until the first
reconnect.  srp_cm_rep_handler() takes ch->max_ti_iu_len from every
SRP_LOGIN_RSP while it allocates the receive ring only when there is none,
and srp_rport_reconnect() keeps the ring across a reconnect, so a target
that reports a larger max_ti_iu_len the second time around makes both
ib_dma_sync_single_for_cpu() and ib_dma_sync_single_for_device() run past
the end of the mapping, which breaks the DMA API rules.

The HCA itself cannot overrun the buffer, because srp_post_recv() posts
iu->size, so sync the length that was actually mapped.

Suggested-by: Bart Van Assche <bvanassche@acm.org>
Fixes: aef9ec39c47f ("IB: Add SCSI RDMA Protocol (SRP) initiator")
Cc: stable@vger.kernel.org
Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
---
 drivers/infiniband/ulp/srp/ib_srp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index a85d28b95306a..159d6b6aa93e3 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -2111,7 +2111,7 @@ static void srp_recv_done(struct ib_cq *cq, struct ib_wc *wc)
 		return;
 	}
 
-	ib_dma_sync_single_for_cpu(dev, iu->dma, ch->max_ti_iu_len,
+	ib_dma_sync_single_for_cpu(dev, iu->dma, iu->size,
 				   DMA_FROM_DEVICE);
 
 	opcode = *(u8 *) iu->buf;
@@ -2148,7 +2148,7 @@ static void srp_recv_done(struct ib_cq *cq, struct ib_wc *wc)
 		break;
 	}
 
-	ib_dma_sync_single_for_device(dev, iu->dma, ch->max_ti_iu_len,
+	ib_dma_sync_single_for_device(dev, iu->dma, iu->size,
 				      DMA_FROM_DEVICE);
 
 	res = srp_post_recv(ch, iu);

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 RESEND 1/2] RDMA/srp: refuse a target that cannot receive an SRP_RSP
  2026-10-26  5:54 ` [PATCH v2 RESEND 1/2] RDMA/srp: refuse a target that cannot receive an SRP_RSP Yehyeong Lee
@ 2026-10-26  9:00   ` sashiko-bot
  0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-10-26  9:00 UTC (permalink / raw)
  To: Yehyeong Lee; +Cc: linux-rdma

> srp_cm_rep_handler() takes max_ti_iu_len straight from the target's
> SRP_LOGIN_RSP and srp_alloc_iu_bufs() then sizes every receive IU with it,
> so the target alone decides how large the initiator's receive buffers are.
> Nothing enforces a lower bound.
> 
> The initiator parses a 36 byte header out of those buffers. A target that
> reports a smaller max_ti_iu_len gets undersized buffers, and the header
> reads in srp_process_rsp() then run past the allocation. A report of zero
> is worse, because kzalloc() answers it with ZERO_SIZE_PTR, and on a
> transport that maps addresses virtually ib_dma_map_single() returns that
> pointer without looking at the length and ib_dma_mapping_error() reports
> success, so the buffer reaches srp_recv_done() and the read of the opcode
> is already out of bounds.
> 
>   BUG: KASAN: slab-out-of-bounds in srp_process_rsp+0x757/0xbe0
> [ ... ]
> cannot speak the protocol, so nothing that works today is turned away.
> 
> Fixes: aef9ec39c47f ("IB: Add SCSI RDMA Protocol (SRP) initiator")
> Cc: stable@vger.kernel.org
> Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261026055430.406487-1-yhlee@isslab.korea.ac.kr?part=1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 RESEND 2/2] RDMA/srp: do not DMA-sync a receive IU past its mapped length
  2026-10-26  5:54 ` [PATCH v2 RESEND 2/2] RDMA/srp: do not DMA-sync a receive IU past its mapped length Yehyeong Lee
@ 2026-10-26  9:08   ` sashiko-bot
  0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-10-26  9:08 UTC (permalink / raw)
  To: Yehyeong Lee; +Cc: linux-rdma

> srp_recv_done() syncs the receive IU with ch->max_ti_iu_len, but the IU
> was mapped with iu->size.  Those are the same value only until the first
> reconnect.  srp_cm_rep_handler() takes ch->max_ti_iu_len from every
> SRP_LOGIN_RSP while it allocates the receive ring only when there is none,
> and srp_rport_reconnect() keeps the ring across a reconnect, so a target
> that reports a larger max_ti_iu_len the second time around makes both
> ib_dma_sync_single_for_cpu() and ib_dma_sync_single_for_device() run past
> the end of the mapping, which breaks the DMA API rules.
> 
> The HCA itself cannot overrun the buffer, because srp_post_recv() posts
> iu->size, so sync the length that was actually mapped.
> 
> Suggested-by: Bart Van Assche <bvanassche@acm.org>
> Fixes: aef9ec39c47f ("IB: Add SCSI RDMA Protocol (SRP) initiator")
> Cc: stable@vger.kernel.org
> Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261026055430.406487-1-yhlee@isslab.korea.ac.kr?part=2


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 RESEND 0/2] RDMA/srp: bound the receive IU the target asks for
  2026-10-26  5:54 [PATCH v2 RESEND 0/2] RDMA/srp: bound the receive IU the target asks for Yehyeong Lee
  2026-10-26  5:54 ` [PATCH v2 RESEND 1/2] RDMA/srp: refuse a target that cannot receive an SRP_RSP Yehyeong Lee
  2026-10-26  5:54 ` [PATCH v2 RESEND 2/2] RDMA/srp: do not DMA-sync a receive IU past its mapped length Yehyeong Lee
@ 2026-10-26 17:16 ` Bart Van Assche
  2 siblings, 0 replies; 6+ messages in thread
From: Bart Van Assche @ 2026-10-26 17:16 UTC (permalink / raw)
  To: Yehyeong Lee
  Cc: Leon Romanovsky, Jason Gunthorpe, linux-rdma, linux-kernel,
	stable

On 10/25/26 10:54 PM, Yehyeong Lee wrote:
> Resending as a standalone thread; the v2 I sent earlier went out
> In-Reply-To v1 by mistake. No code changes. Apologies for the noise.

We are in the middle of the merge window so this is not the best time to
post or resend patches. Please repost after the merge window has closed.

Thanks,

Bart.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-10-26 17:16 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-26  5:54 [PATCH v2 RESEND 0/2] RDMA/srp: bound the receive IU the target asks for Yehyeong Lee
2026-10-26  5:54 ` [PATCH v2 RESEND 1/2] RDMA/srp: refuse a target that cannot receive an SRP_RSP Yehyeong Lee
2026-10-26  9:00   ` sashiko-bot
2026-10-26  5:54 ` [PATCH v2 RESEND 2/2] RDMA/srp: do not DMA-sync a receive IU past its mapped length Yehyeong Lee
2026-10-26  9:08   ` sashiko-bot
2026-10-26 17:16 ` [PATCH v2 RESEND 0/2] RDMA/srp: bound the receive IU the target asks for Bart Van Assche

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox