* [PATCH v3 0/2] RDMA/srp: bound the receive IU the target asks for
@ 2026-11-02 6:19 Yehyeong Lee
2026-11-02 6:19 ` [PATCH v3 1/2] RDMA/srp: refuse a target that cannot receive an SRP_RSP Yehyeong Lee
2026-11-02 6:19 ` [PATCH v3 2/2] RDMA/srp: do not DMA-sync a receive IU past its mapped length Yehyeong Lee
0 siblings, 2 replies; 5+ messages in thread
From: Yehyeong Lee @ 2026-11-02 6:19 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.
v2 -> v3: commit message of 1/2 only. The KASAN report now comes from
a real rxe connection instead of a KUnit harness. No code changes.
This is the repost after the merge window that Bart asked for.
v2 RESEND: https://lore.kernel.org/r/20261026055430.406487-1-yhlee@isslab.korea.ac.kr
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: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v3 1/2] RDMA/srp: refuse a target that cannot receive an SRP_RSP
2026-11-02 6:19 [PATCH v3 0/2] RDMA/srp: bound the receive IU the target asks for Yehyeong Lee
@ 2026-11-02 6:19 ` Yehyeong Lee
2026-11-02 6:31 ` sashiko-bot
2026-11-02 6:19 ` [PATCH v3 2/2] RDMA/srp: do not DMA-sync a receive IU past its mapped length Yehyeong Lee
1 sibling, 1 reply; 5+ messages in thread
From: Yehyeong Lee @ 2026-11-02 6:19 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
dereferences ZERO_SIZE_PTR.
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.
Reproduced over rxe with ib_srpt modified to advertise a max_ti_iu_len of
33 and to send its first SRP_RSP as 33 bytes with SRP_RSP_FLAG_SNSVALID
set, which is what makes srp_process_rsp() read resp_data_len at offset
32. A report of zero ends in a general protection fault on the opcode read
instead. With this patch both logins are refused.
BUG: KASAN: slab-out-of-bounds in srp_recv_done+0x8e5/0x1c80
Read of size 4 at addr ffff888106046aa0 by task kworker/u8:2/42
CPU: 1 UID: 0 PID: 42 Comm: kworker/u8:2 Not tainted 7.4.0-rc1-SRPFLRA-00001-gc23c1c890846 #7 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: rxe_wq do_work
Call Trace:
<IRQ>
dump_stack_lvl+0x53/0x70
print_report+0xd0/0x630
? __pfx__raw_spin_lock_irqsave+0x10/0x10
? srp_recv_done+0x8e5/0x1c80
kasan_report+0xce/0x100
? srp_recv_done+0x8e5/0x1c80
srp_recv_done+0x8e5/0x1c80
? __pfx_srp_recv_done+0x10/0x10
? rxe_poll_cq+0x253/0x3d0
__ib_process_cq+0xe1/0x390
ib_poll_handler+0x6e/0x200
irq_poll_softirq+0x1df/0x480
? __pfx_irq_poll_softirq+0x10/0x10
handle_softirqs+0x1b3/0x600
? __pfx_handle_softirqs+0x10/0x10
do_softirq+0x3d/0x60
</IRQ>
<TASK>
__local_bh_enable_ip+0x6a/0x70
__alloc_skb+0x734/0x890
? _raw_spin_lock_irqsave+0x86/0xe0
? __pfx___alloc_skb+0x10/0x10
? _raw_read_unlock_irqrestore+0x16/0x50
rxe_init_packet+0x16b/0x5c0
prepare_ack_packet+0xc6/0x8a0
rxe_receiver+0x499/0x9a20
? __pfx_rxe_receiver+0x10/0x10
? rxe_completer+0x29e5/0x38c0
? __pfx__raw_spin_lock_irqsave+0x10/0x10
? __pfx_rxe_receiver+0x10/0x10
do_work+0x144/0x470
process_one_work+0x697/0x1060
? __pfx___schedule+0x10/0x10
? __pfx_process_one_work+0x10/0x10
? _raw_spin_lock_irq+0x81/0xe0
? __pfx_do_work+0x10/0x10
? assign_work+0x11d/0x370
worker_thread+0x45b/0xd10
? __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/0xdc0
? __pfx_kthread+0x10/0x10
ret_from_fork_asm+0x1a/0x30
</TASK>
Allocated by task 9:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
__kasan_kmalloc+0x8f/0xa0
__kmalloc_noprof+0x193/0x450
srp_alloc_iu.constprop.0+0x69/0x5c0
srp_cm_rep_handler+0xc4a/0x1bd0
srp_rdma_cm_handler+0x111/0x7f0
cma_cm_event_handler+0x3e/0x240
cma_ib_handler+0x190/0x750
cm_process_work+0x41/0x330
cm_work_handler+0x1de2/0xc160
process_one_work+0x697/0x1060
worker_thread+0x45b/0xd10
kthread+0x2c8/0x3b0
ret_from_fork+0x36e/0x5a0
ret_from_fork_asm+0x1a/0x30
The buggy address belongs to the object at ffff888106046a80
which belongs to the cache kmalloc-64 of size 64
The buggy address is located 32 bytes inside of
allocated 33-byte region [ffff888106046a80, ffff888106046aa1)
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 5811f02df98053..a85d28b95306a5 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);
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v3 2/2] RDMA/srp: do not DMA-sync a receive IU past its mapped length
2026-11-02 6:19 [PATCH v3 0/2] RDMA/srp: bound the receive IU the target asks for Yehyeong Lee
2026-11-02 6:19 ` [PATCH v3 1/2] RDMA/srp: refuse a target that cannot receive an SRP_RSP Yehyeong Lee
@ 2026-11-02 6:19 ` Yehyeong Lee
2026-11-02 6:30 ` sashiko-bot
1 sibling, 1 reply; 5+ messages in thread
From: Yehyeong Lee @ 2026-11-02 6:19 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 a85d28b95306a5..159d6b6aa93e3a 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);
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v3 2/2] RDMA/srp: do not DMA-sync a receive IU past its mapped length
2026-11-02 6:19 ` [PATCH v3 2/2] RDMA/srp: do not DMA-sync a receive IU past its mapped length Yehyeong Lee
@ 2026-11-02 6:30 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-11-02 6:30 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/20261102061938.617371-1-yhlee@isslab.korea.ac.kr?part=2
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v3 1/2] RDMA/srp: refuse a target that cannot receive an SRP_RSP
2026-11-02 6:19 ` [PATCH v3 1/2] RDMA/srp: refuse a target that cannot receive an SRP_RSP Yehyeong Lee
@ 2026-11-02 6:31 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-11-02 6:31 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
> dereferences ZERO_SIZE_PTR.
>
> Refuse the login instead. Both the largest messages the initiator parses,
> [ ... ]
> allocated 33-byte region [ffff888106046a80, ffff888106046aa1)
>
> 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/20261102061938.617371-1-yhlee@isslab.korea.ac.kr?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-11-02 6:31 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-02 6:19 [PATCH v3 0/2] RDMA/srp: bound the receive IU the target asks for Yehyeong Lee
2026-11-02 6:19 ` [PATCH v3 1/2] RDMA/srp: refuse a target that cannot receive an SRP_RSP Yehyeong Lee
2026-11-02 6:31 ` sashiko-bot
2026-11-02 6:19 ` [PATCH v3 2/2] RDMA/srp: do not DMA-sync a receive IU past its mapped length Yehyeong Lee
2026-11-02 6:30 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox