mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v3 0/2] RDMA/srpt: fix the indirect descriptor table bound and the context counters
@ 2026-10-22 14:38 Yehyeong Lee
  2026-10-22 14:39 ` [PATCH v3 1/2] RDMA/srpt: bound the indirect descriptor table to the IU Yehyeong Lee
  2026-10-22 14:39 ` [PATCH v3 2/2] RDMA/srpt: widen the indirect RDMA context counters Yehyeong Lee
  0 siblings, 2 replies; 7+ messages in thread
From: Yehyeong Lee @ 2026-10-22 14:38 UTC (permalink / raw)
  To: Bart Van Assche
  Cc: Leon Romanovsky, Jason Gunthorpe, linux-rdma, target-devel,
	linux-kernel, stable, yhlee

Both changes are needed, and they fix different things.

A 510 entry table fits in the default 8276 byte IU when the additional CDB
is empty, so the bound accepts it and the counters then have to hold it.
With only the bound, a conforming command carrying 256 or more descriptors
still wraps n_rw_ctx and leaks every context it allocated. With only the
wider counters, a command that sets ADDITIONAL CDB LENGTH to its maximum
still walks a descriptor table that runs past the receive buffer.

The two defects also come from different commits, which is why they are
split here.

Changes since v2, all from Bart's review. The two fixes are separate
patches now. The widening patch says that n_rdma accumulates the
rdma_rw_ctx_init() work request counts, so it can pass 255 with only a
handful of descriptors, which is more than the 256 descriptor wrap. The
separate descriptor header pre-check is gone, folded into one room test
placed after the existing count guard, because the header can never fall
outside the buffer.

Yehyeong Lee (2):
  RDMA/srpt: bound the indirect descriptor table to the IU
  RDMA/srpt: widen the indirect RDMA context counters

 drivers/infiniband/ulp/srpt/ib_srpt.c | 12 +++++++++++-
 drivers/infiniband/ulp/srpt/ib_srpt.h |  4 ++--
 2 files changed, 13 insertions(+), 3 deletions(-)


base-commit: c03c1a14507dfaf8b856c2608f9ac216021fc222
-- 
2.43.0


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

* [PATCH v3 1/2] RDMA/srpt: bound the indirect descriptor table to the IU
  2026-10-22 14:38 [PATCH v3 0/2] RDMA/srpt: fix the indirect descriptor table bound and the context counters Yehyeong Lee
@ 2026-10-22 14:39 ` Yehyeong Lee
  2026-10-22 15:56   ` Bart Van Assche
  2026-10-22 18:15   ` Yehyeong Lee
  2026-10-22 14:39 ` [PATCH v3 2/2] RDMA/srpt: widen the indirect RDMA context counters Yehyeong Lee
  1 sibling, 2 replies; 7+ messages in thread
From: Yehyeong Lee @ 2026-10-22 14:39 UTC (permalink / raw)
  To: Bart Van Assche
  Cc: Leon Romanovsky, Jason Gunthorpe, linux-rdma, target-devel,
	linux-kernel, stable, yhlee

srpt_get_desc_tbl() takes the number of INDIRECT descriptors from
idb->table_desc.len, which the initiator controls, and checks it only
against data_out_desc_cnt + data_in_desc_cnt, two more initiator fields.
Both are u8, so the pair admits up to 510 descriptors, and nothing
compares the table against the receive IU it has to live in.
srpt_alloc_rw_ctxs() then walks idb->desc_list for that many entries.

With the default srp_max_req_size of 8276 the table fits as long as the
additional CDB is short, but ADDITIONAL CDB LENGTH is an initiator field
too, and at its maximum of 252 bytes 510 descriptors end at
48 + 252 + 20 + 510 * 16 = 8480, which is past the end of the object:

  BUG: KASAN: slab-out-of-bounds in srpt_alloc_rw_ctxs+0x64c/0x820
  Read of size 4 at addr ffff888002d3a05c by task kunit_try_catch/44

  CPU: 0 UID: 0 PID: 44 Comm: kunit_try_catch Tainted: G                 N  7.3.0-dirty #1 PREEMPT(lazy)
  Tainted: [N]=TEST
  Call Trace:
   <TASK>
   dump_stack_lvl+0x3f/0x50
   print_report+0xcd/0x620
   ? alloc_pages_node_noprof+0xa2/0x140
   ? srpt_alloc_rw_ctxs+0x64c/0x820
   kasan_report+0xde/0x110
   ? srpt_alloc_rw_ctxs+0x64c/0x820
   srpt_alloc_rw_ctxs+0x64c/0x820
   srpt_test_run.constprop.0+0x13b/0xc50
   ? __pfx_srpt_test_run.constprop.0+0x10/0x10
   ? pick_task_fair+0x126/0x1950
   ? update_curr.constprop.0+0x4a/0x390
   ? __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+0x247/0x360
   ? __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+0x36a/0x4f0
   ? __pfx_kthread+0x10/0x10
   ret_from_fork+0x34d/0x620
   ? __pfx_ret_from_fork+0x10/0x10
   ? __switch_to+0x22/0xde0
   ? __pfx_kthread+0x10/0x10
   ret_from_fork_asm+0x19/0x30
   </TASK>

  Allocated by task 44:
   kasan_save_stack+0x33/0x60
   kasan_save_track+0x14/0x30
   __kasan_slab_alloc+0x6e/0x70
   kmem_cache_alloc_noprof+0x11d/0x2f0
   srpt_test_ctx_init.constprop.0+0x481/0xfa0
   srpt_test_run.constprop.0+0xf4/0xc50
   kunit_try_run_case+0x1ca/0x4b0
   kunit_generic_run_threadfn_adapter+0x7b/0xe0
   kthread+0x36a/0x4f0
   ret_from_fork+0x34d/0x620
   ret_from_fork_asm+0x19/0x30

  The buggy address belongs to the object at ffff888002d38000
   which belongs to the cache srpt-kunit-iu of size 8276
  The buggy address is located 8 bytes to the right of
   allocated 8276-byte region [ffff888002d38000, ffff888002d3a054)

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

Compare the count against the room the IU actually leaves for the table.
recv_ioctx->byte_len is signed, so a byte_len too small to cover even the
descriptor header yields a negative room and the same test refuses it.

The header itself is always inside the buffer. The largest offset
srpt_get_desc_buf() can return is 48 + 252 and the header is 20 bytes, so
it ends at 320, while srp_max_req_size is at least MIN_MAX_REQ_SIZE,
which is 996. Only the table needs bounding, so one test placed after the
existing count check is enough.

Fixes: a42d985bd5b2 ("ib_srpt: Initial SRP Target merge for v3.3-rc1")
Cc: stable@vger.kernel.org
Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
---
 drivers/infiniband/ulp/srpt/ib_srpt.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index 7197d95f2216b..97758082f71d2 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -1117,6 +1117,8 @@ static int srpt_get_desc_tbl(struct srpt_recv_ioctx *recv_ioctx,
 		struct srp_indirect_buf *idb = srpt_get_desc_buf(srp_cmd);
 		int nbufs = be32_to_cpu(idb->table_desc.len) /
 				sizeof(struct srp_direct_buf);
+		int desc_off = (u8 *)idb - (u8 *)srp_cmd;
+		int room;
 
 		if (nbufs >
 		    (srp_cmd->data_out_desc_cnt + srp_cmd->data_in_desc_cnt)) {
@@ -1128,6 +1130,14 @@ static int srpt_get_desc_tbl(struct srpt_recv_ioctx *recv_ioctx,
 			return -EINVAL;
 		}
 
+		room = (recv_ioctx->byte_len - desc_off - (int)sizeof(*idb)) /
+			(int)sizeof(struct srp_direct_buf);
+		if (nbufs > room) {
+			pr_err("received SRP_CMD with %d descriptors but room for %d in the IU\n",
+			       nbufs, room);
+			return -EINVAL;
+		}
+
 		*data_len = be32_to_cpu(idb->len);
 		return srpt_alloc_rw_ctxs(ioctx, idb->desc_list, nbufs,
 				sg, sg_cnt);
-- 
2.43.0


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

* [PATCH v3 2/2] RDMA/srpt: widen the indirect RDMA context counters
  2026-10-22 14:38 [PATCH v3 0/2] RDMA/srpt: fix the indirect descriptor table bound and the context counters Yehyeong Lee
  2026-10-22 14:39 ` [PATCH v3 1/2] RDMA/srpt: bound the indirect descriptor table to the IU Yehyeong Lee
@ 2026-10-22 14:39 ` Yehyeong Lee
  2026-10-22 15:57   ` Bart Van Assche
  2026-10-22 18:15   ` Yehyeong Lee
  1 sibling, 2 replies; 7+ messages in thread
From: Yehyeong Lee @ 2026-10-22 14:39 UTC (permalink / raw)
  To: Bart Van Assche
  Cc: Leon Romanovsky, Jason Gunthorpe, linux-rdma, target-devel,
	linux-kernel, stable, yhlee

srpt_send_ioctx::n_rdma and ::n_rw_ctx are u8, and neither of the values
stored in them is bounded by 255.

n_rw_ctx counts the INDIRECT descriptors a command carries, and the count
guard in srpt_get_desc_tbl() admits data_out_desc_cnt plus
data_in_desc_cnt, so up to 510. At 256 descriptors n_rw_ctx wraps to
zero, and srpt_release_cmd() frees the contexts only when it is non-zero,
so every scatterlist and RDMA context the command allocated leaks.

n_rdma is not a descriptor count at all. It is the sum of the
rdma_rw_ctx_init() return values, which is the number of work requests
each context needs, accumulated by ioctx->n_rdma += ret. A handful of
descriptors for large transfers can pass 255 on their own, with no
unusual descriptor count involved. A wrapped n_rdma is then handed to
atomic_sub_return(ioctx->n_rdma, &ch->sq_wr_avail) and tested by
WARN_ON(ioctx->n_rdma <= 0), so the send queue work request accounting
drifts too.

Make both counters int, the type the values they accumulate already have.

Fixes: b99f8e4d7bcd ("IB/srpt: convert to the generic RDMA READ/WRITE API")
Cc: stable@vger.kernel.org
Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
---
 drivers/infiniband/ulp/srpt/ib_srpt.c | 2 +-
 drivers/infiniband/ulp/srpt/ib_srpt.h | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index 97758082f71d2..bdea47316539f 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -959,7 +959,7 @@ static int srpt_alloc_rw_ctxs(struct srpt_send_ioctx *ioctx,
 	struct srpt_rdma_ch *ch = ioctx->ch;
 	struct scatterlist *prev = NULL;
 	unsigned prev_nents;
-	u8 n_rdma, n_rw_ctx;
+	int n_rdma, n_rw_ctx;
 	int ret, i;
 
 	if (nbufs == 1) {
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.h b/drivers/infiniband/ulp/srpt/ib_srpt.h
index 4c46b301eea18..1dce9bcb490f0 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.h
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.h
@@ -223,8 +223,8 @@ struct srpt_send_ioctx {
 	struct ib_cqe		rdma_cqe;
 	enum srpt_command_state	state;
 	struct se_cmd		cmd;
-	u8			n_rdma;
-	u8			n_rw_ctx;
+	int			n_rdma;
+	int			n_rw_ctx;
 	bool			queue_status_only;
 	u8			sense_data[TRANSPORT_SENSE_BUFFER];
 };
-- 
2.43.0


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

* Re: [PATCH v3 1/2] RDMA/srpt: bound the indirect descriptor table to the IU
  2026-10-22 14:39 ` [PATCH v3 1/2] RDMA/srpt: bound the indirect descriptor table to the IU Yehyeong Lee
@ 2026-10-22 15:56   ` Bart Van Assche
  2026-10-22 18:15   ` Yehyeong Lee
  1 sibling, 0 replies; 7+ messages in thread
From: Bart Van Assche @ 2026-10-22 15:56 UTC (permalink / raw)
  To: Yehyeong Lee
  Cc: Leon Romanovsky, Jason Gunthorpe, linux-rdma, target-devel,
	linux-kernel, stable

On 10/22/26 7:39 AM, Yehyeong Lee wrote:
> diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
> index 7197d95f2216b..97758082f71d2 100644
> --- a/drivers/infiniband/ulp/srpt/ib_srpt.c
> +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
> @@ -1117,6 +1117,8 @@ static int srpt_get_desc_tbl(struct srpt_recv_ioctx *recv_ioctx,
>   		struct srp_indirect_buf *idb = srpt_get_desc_buf(srp_cmd);
>   		int nbufs = be32_to_cpu(idb->table_desc.len) /
>   				sizeof(struct srp_direct_buf);
> +		int desc_off = (u8 *)idb - (u8 *)srp_cmd;

The idiomatic way in the kernel for subtracting pointers is to convert
these to uintptr_t instead of u8 * before subtracting.

Thanks,

Bart.

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

* Re: [PATCH v3 2/2] RDMA/srpt: widen the indirect RDMA context counters
  2026-10-22 14:39 ` [PATCH v3 2/2] RDMA/srpt: widen the indirect RDMA context counters Yehyeong Lee
@ 2026-10-22 15:57   ` Bart Van Assche
  2026-10-22 18:15   ` Yehyeong Lee
  1 sibling, 0 replies; 7+ messages in thread
From: Bart Van Assche @ 2026-10-22 15:57 UTC (permalink / raw)
  To: Yehyeong Lee
  Cc: Leon Romanovsky, Jason Gunthorpe, linux-rdma, target-devel,
	linux-kernel, stable

On 10/22/26 7:39 AM, Yehyeong Lee wrote:
> Make both counters int, the type the values they accumulate already have.

Why int, which is signed, instead of an unsigned type?

Thanks,

Bart.

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

* Re: [PATCH v3 1/2] RDMA/srpt: bound the indirect descriptor table to the IU
  2026-10-22 14:39 ` [PATCH v3 1/2] RDMA/srpt: bound the indirect descriptor table to the IU Yehyeong Lee
  2026-10-22 15:56   ` Bart Van Assche
@ 2026-10-22 18:15   ` Yehyeong Lee
  1 sibling, 0 replies; 7+ messages in thread
From: Yehyeong Lee @ 2026-10-22 18:15 UTC (permalink / raw)
  To: Bart Van Assche
  Cc: Leon Romanovsky, Jason Gunthorpe, linux-rdma, target-devel,
	linux-kernel, yhlee

Thanks, I will switch desc_off to a uintptr_t subtraction.

The room check is also wrong for a short IU, as Sashiko noted and as the
commit message wrongly denies. The division truncates toward zero, so a
byte_len one to fifteen bytes short of the header gives room zero rather
than negative, and a table_desc.len below one descriptor gives nbufs
zero, so nbufs > room is false and the truncated request is not refused.

v4 drops the division and compares the span the table needs,
desc_off + sizeof(*idb) + nbufs * sizeof(struct srp_direct_buf), against
recv_ioctx->byte_len, which refuses a short IU with no reliance on sign
or truncation.

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

* Re: [PATCH v3 2/2] RDMA/srpt: widen the indirect RDMA context counters
  2026-10-22 14:39 ` [PATCH v3 2/2] RDMA/srpt: widen the indirect RDMA context counters Yehyeong Lee
  2026-10-22 15:57   ` Bart Van Assche
@ 2026-10-22 18:15   ` Yehyeong Lee
  1 sibling, 0 replies; 7+ messages in thread
From: Yehyeong Lee @ 2026-10-22 18:15 UTC (permalink / raw)
  To: Bart Van Assche
  Cc: Leon Romanovsky, Jason Gunthorpe, linux-rdma, target-devel,
	linux-kernel, yhlee

The values are counts and never negative, so an unsigned type fits. I
used int because rdma_rw_ctx_init() returns int and the sum is guarded by
WARN_ON(ioctx->n_rdma <= 0) in srpt_rdma_read_done(), a signed test, so
int kept the surrounding code unchanged. I am happy to make both unsigned
int and turn that test into == 0 if you prefer.

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

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

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-22 14:38 [PATCH v3 0/2] RDMA/srpt: fix the indirect descriptor table bound and the context counters Yehyeong Lee
2026-10-22 14:39 ` [PATCH v3 1/2] RDMA/srpt: bound the indirect descriptor table to the IU Yehyeong Lee
2026-10-22 15:56   ` Bart Van Assche
2026-10-22 18:15   ` Yehyeong Lee
2026-10-22 14:39 ` [PATCH v3 2/2] RDMA/srpt: widen the indirect RDMA context counters Yehyeong Lee
2026-10-22 15:57   ` Bart Van Assche
2026-10-22 18:15   ` Yehyeong Lee

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®