All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH nvme] nvmet-rdma: reject short connection requests
@ 2026-10-16 17:23 bestswngs
  2026-10-16 17:35 ` sashiko-bot
  0 siblings, 1 reply; 2+ messages in thread
From: bestswngs @ 2026-10-16 17:23 UTC (permalink / raw)
  To: hch, sagi, kch, linux-nvme
  Cc: xmei5, Weiming Shi, stable, co+e015e82956da641b

From: Weiming Shi <bestswngs@gmail.com>

nvmet_rdma_parse_cm_connect_req() treats RDMA-CM private data as a
struct nvme_rdma_cm_req but accepts any nonzero private_data_len.  The
iWARP path allocates exactly the peer-provided length, so a six-byte MPA
request reaches the parser and the hsqsize load reads two bytes past the
allocation.

Require the complete request structure before reading any of its fields.
The decoded KASAN report is:

  BUG: KASAN: slab-out-of-bounds in nvmet_rdma_cm_handler
    (drivers/nvme/target/rdma.c:1427 drivers/nvme/target/rdma.c:1475
     drivers/nvme/target/rdma.c:1614 drivers/nvme/target/rdma.c:1814)
  Read of size 2 at addr ff1100010459d366 by task kworker/u16:1/41
  Workqueue: iw_cm_wq cm_work_handler
  Call Trace:
   <TASK>
   dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
   print_report (mm/kasan/report.c:378 mm/kasan/report.c:482)
   kasan_report (mm/kasan/report.c:595)
   nvmet_rdma_cm_handler
    (drivers/nvme/target/rdma.c:1427 drivers/nvme/target/rdma.c:1475
     drivers/nvme/target/rdma.c:1614 drivers/nvme/target/rdma.c:1814)
   cma_cm_event_handler (drivers/infiniband/core/cma.c:2181)
   iw_conn_req_handler (drivers/infiniband/core/cma.c:2640)
   cm_work_handler
    (drivers/infiniband/core/cm.c:2502
     drivers/infiniband/core/cm.c:3858)
   process_one_work (kernel/workqueue.c:3396)
   worker_thread (kernel/workqueue.c:3479 kernel/workqueue.c:3560)
   kthread (kernel/kthread.c:436)
   ret_from_fork (arch/x86/kernel/process.c:158)
   ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
   </TASK>

  Allocated by task 12:
   __kasan_kmalloc (mm/kasan/common.c:398 mm/kasan/common.c:415)
   __kmalloc_node_track_caller_noprof
    (mm/slub.c:5414 mm/slub.c:5545)
   kmemdup_noprof (mm/util.c:138)
   cm_event_handler
    (drivers/infiniband/core/iwcm.c:194
     drivers/infiniband/core/iwcm.c:1076)
   siw_cm_upcall (drivers/infiniband/sw/siw/siw_cm.c:408)
   siw_proc_mpareq (drivers/infiniband/sw/siw/siw_cm.c:750)
   siw_cm_work_handler (drivers/infiniband/sw/siw/siw_cm.c:1086)

  The buggy address is located 0 bytes to the right of
  allocated 6-byte region [ff1100010459d360, ff1100010459d366)

Cc: stable@vger.kernel.org
Fixes: 8f000cac6e7a ("nvmet-rdma: add a NVMe over Fabrics RDMA target driver")
Reported-by: <co+e015e82956da641b@bugs.sh>
Assisted-by: LLM
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
---
 drivers/nvme/target/rdma.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c
index ffa1e172c..075ab58d8 100644
--- a/drivers/nvme/target/rdma.c
+++ b/drivers/nvme/target/rdma.c
@@ -1412,7 +1412,7 @@ nvmet_rdma_parse_cm_connect_req(struct rdma_conn_param *conn,
 	struct nvme_rdma_cm_req *req;
 
 	req = (struct nvme_rdma_cm_req *)conn->private_data;
-	if (!req || conn->private_data_len == 0)
+	if (!req || conn->private_data_len < sizeof(*req))
 		return NVME_RDMA_CM_INVALID_LEN;
 
 	if (le16_to_cpu(req->recfmt) != NVME_RDMA_CM_FMT_1_0)
-- 
2.55.0



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

* Re: [PATCH nvme] nvmet-rdma: reject short connection requests
  2026-10-16 17:23 [PATCH nvme] nvmet-rdma: reject short connection requests bestswngs
@ 2026-10-16 17:35 ` sashiko-bot
  0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-10-16 17:35 UTC (permalink / raw)
  To: bestswngs, linux-nvme

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] nvme-rdma: unauthenticated remote DoS via unbounded IO queue sizes
--

commit 73a9fa992c7d8c72321b7f00558b5cb1451f8574
Author: Weiming Shi <bestswngs@gmail.com>

nvmet-rdma: reject short connection requests

nvmet_rdma_parse_cm_connect_req() treats rdma cm private data as a
struct nvme_rdma_cm_req but accepts any nonzero private_data_len. The
iWARP path allocates exactly the peer-provided length, so a six-byte MPA
request reaches the parser and the hsqsize load reads two bytes past the
allocation. This requires the complete request structure before reading
any of its fields.

> diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c
> index ffa1e172c259b..075ab58d8c884 100644
> --- a/drivers/nvme/target/rdma.c
> +++ b/drivers/nvme/target/rdma.c
> @@ -1412,7 +1412,7 @@ nvmet_rdma_parse_cm_connect_req(struct rdma_conn_param *conn,
>  	struct nvme_rdma_cm_req *req;
>  
>  	req = (struct nvme_rdma_cm_req *)conn->private_data;
> -	if (!req || conn->private_data_len == 0)
> +	if (!req || conn->private_data_len < sizeof(*req))
>  		return NVME_RDMA_CM_INVALID_LEN;
>  
>  	if (le16_to_cpu(req->recfmt) != NVME_RDMA_CM_FMT_1_0)

[Severity: High]
Does this code adequately validate the remote request fields for io queues?

In nvmet_rdma_parse_cm_connect_req(), the unvalidated hsqsize and hrqsize
fields from the untrusted remote request are directly assigned to the queue
sizes. While there is a check for the admin queue (host_qid == 0), the lack
of bounds checking for io queues allows an unauthenticated initiator to set
arbitrary queue bounds up to the 16-bit integer limit:

	queue->recv_queue_size = le16_to_cpu(req->hsqsize) + 1;
	queue->send_queue_size = le16_to_cpu(req->hrqsize);

	if (!queue->host_qid && queue->recv_queue_size > NVME_AQ_DEPTH)
		return NVME_RDMA_CM_INVALID_HSQSIZE;

During rdma connection establishment, these unvalidated sizes are passed to
nvmet_rdma_alloc_queue() within the unauthenticated rdma cm handler. This
introduces a regression where massive heap allocations are based on remote
input.

For instance, nvmet_rdma_alloc_rsps() uses the unvalidated size to loop up
to 131,072 times allocating cqe slabs and establishing dma mappings:

	int nr_rsps = queue->recv_queue_size * 2;
	...
	for (i = 0; i < nr_rsps; i++) {
		struct nvmet_rdma_rsp *rsp = &queue->rsps[i];
		ret = nvmet_rdma_alloc_rsp(ndev, rsp, i);

Similarly, nvmet_rdma_alloc_cmds() loops nr_cmds (up to 65,536) times,
allocating full memory pages via alloc_page(GFP_KERNEL) for inline data
and mapping them via dma:

	for (i = 0; i < nr_cmds; i++) {
		ret = nvmet_rdma_alloc_cmd(ndev, cmds + i, admin);

Could this allow an unauthenticated attacker to open a few concurrent
connections with large hsqsize values to trivially trigger severe memory
exhaustion and cause a denial of service?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261016172336.286341-3-bestswngs@gmail.com?part=1


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

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

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-16 17:23 [PATCH nvme] nvmet-rdma: reject short connection requests bestswngs
2026-10-16 17:35 ` sashiko-bot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.