Linux-NVME Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] nvmet-fc: bound the FCP command data length before allocating buffers
@ 2026-10-13 10:40 Yehyeong Lee
  2026-10-13 14:19 ` Christoph Hellwig
  0 siblings, 1 reply; 3+ messages in thread
From: Yehyeong Lee @ 2026-10-13 10:40 UTC (permalink / raw)
  To: Justin Tee, Christoph Hellwig, Sagi Grimberg, Keith Busch,
	linux-nvme
  Cc: Naresh Gottumukkala, Paul Ely, Chaitanya Kulkarni, James Smart,
	linux-kernel, stable, yhlee

nvmet_fc_handle_fcp_rqst() takes the data length straight from the FCP
command IU (cmdiu->data_len, a 32-bit value from the wire) into
fod->req.transfer_len and calls nvmet_fc_alloc_tgt_pgs(), which hands it to
sgl_alloc() with no upper bound.  nvmet_req_init() only parses the command
and clears transfer_len; nvmet_check_transfer_len(), the only other place
the length is checked, runs later from req->execute(), after the allocation
has already happened.

A remote, effectively unauthenticated host can therefore declare a huge
transfer length and make the target allocate that much kernel memory for a
command that never delivers the data.  nvmet-tcp bounds the equivalent
length and the rdma transport is limited by its 24-bit SGL length field;
the fc transport had no such limit.

Reject a command whose data length exceeds NVMET_FC_MAX_XFR_LENGTH before
allocating anything.  The ceiling is 16 MiB, the largest transfer any
in-tree fc LLDD can describe (lpfc maps up to LPFC_MAX_SG_SEG_CNT 4096
segments, qla2xxx 1024), so no in-tree configuration is rejected.

A command declaring 4 GiB reaches sgl_alloc() unbounded before this change;
afterwards a length above 16 MiB is failed with SGL_INVALID_DATA before any
allocation is attempted.

Fixes: c53432030d86 ("nvme-fabrics: Add target support for FC transport")
Cc: stable@vger.kernel.org
Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
---
 drivers/nvme/target/fc.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c
index 1b557775e033a..5ec581780454e 100644
--- a/drivers/nvme/target/fc.c
+++ b/drivers/nvme/target/fc.c
@@ -62,6 +62,16 @@ struct nvmet_fc_ls_req_op {		/* for an LS RQST XMT */
 /* desired maximum for a single sequence - if sg list allows it */
 #define NVMET_FC_MAX_SEQ_LENGTH		(256 * 1024)
 
+/*
+ * Upper bound on the data length a host may declare in an FCP CMD IU.
+ * This is the largest transfer any in-tree LLDD can describe: lpfc maps
+ * at most LPFC_MAX_SG_SEG_CNT (4096) segments and qla2xxx 1024, so 4096
+ * pages covers both.  The length arrives from the wire as a full 32-bit
+ * value and sizes the command's buffer allocation, so it has to be
+ * bounded before anything is allocated for it.
+ */
+#define NVMET_FC_MAX_XFR_LENGTH		(16 * 1024 * 1024)
+
 enum nvmet_fcp_datadir {
 	NVMET_FCP_NODATA,
 	NVMET_FCP_WRITE,
@@ -2577,6 +2587,14 @@ nvmet_fc_handle_fcp_rqst(struct nvmet_fc_tgtport *tgtport,
 	atomic_inc(&fod->queue->sqtail);
 
 	if (fod->req.transfer_len) {
+		/* bound the host-declared length before allocating for it */
+		if (fod->req.transfer_len > NVMET_FC_MAX_XFR_LENGTH) {
+			nvmet_req_complete(&fod->req,
+					   NVME_SC_SGL_INVALID_DATA |
+					   NVME_STATUS_DNR);
+			return;
+		}
+
 		ret = nvmet_fc_alloc_tgt_pgs(fod);
 		if (ret) {
 			nvmet_req_complete(&fod->req, ret);

base-commit: 2c3418fffa9d037b2038a6db48be63f9e2291806
-- 
2.43.0



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

* Re: [PATCH] nvmet-fc: bound the FCP command data length before allocating buffers
  2026-10-13 10:40 [PATCH] nvmet-fc: bound the FCP command data length before allocating buffers Yehyeong Lee
@ 2026-10-13 14:19 ` Christoph Hellwig
  2026-10-13 15:53   ` Yehyeong Lee
  0 siblings, 1 reply; 3+ messages in thread
From: Christoph Hellwig @ 2026-10-13 14:19 UTC (permalink / raw)
  To: Yehyeong Lee
  Cc: Justin Tee, Christoph Hellwig, Sagi Grimberg, Keith Busch,
	linux-nvme, Naresh Gottumukkala, Paul Ely, Chaitanya Kulkarni,
	James Smart, linux-kernel, stable

On Tue, Oct 13, 2026 at 07:40:38PM +0900, Yehyeong Lee wrote:
> nvmet_fc_handle_fcp_rqst() takes the data length straight from the FCP
> command IU (cmdiu->data_len, a 32-bit value from the wire) into
> fod->req.transfer_len and calls nvmet_fc_alloc_tgt_pgs(), which hands it to
> sgl_alloc() with no upper bound.  nvmet_req_init() only parses the command
> and clears transfer_len; nvmet_check_transfer_len(), the only other place
> the length is checked, runs later from req->execute(), after the allocation
> has already happened.
> 
> A remote, effectively unauthenticated host can therefore declare a huge
> transfer length and make the target allocate that much kernel memory for a
> command that never delivers the data.  nvmet-tcp bounds the equivalent
> length and the rdma transport is limited by its 24-bit SGL length field;
> the fc transport had no such limit.
> 
> Reject a command whose data length exceeds NVMET_FC_MAX_XFR_LENGTH before
> allocating anything.  The ceiling is 16 MiB, the largest transfer any
> in-tree fc LLDD can describe (lpfc maps up to LPFC_MAX_SG_SEG_CNT 4096
> segments, qla2xxx 1024), so no in-tree configuration is rejected.
> 
> A command declaring 4 GiB reaches sgl_alloc() unbounded before this change;
> afterwards a length above 16 MiB is failed with SGL_INVALID_DATA before any
> allocation is attempted.

The bounds check is obviously a good idea, but we really need to tell
the host about it using MDTS, don't we?



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

* Re: [PATCH] nvmet-fc: bound the FCP command data length before allocating buffers
  2026-10-13 14:19 ` Christoph Hellwig
@ 2026-10-13 15:53   ` Yehyeong Lee
  0 siblings, 0 replies; 3+ messages in thread
From: Yehyeong Lee @ 2026-10-13 15:53 UTC (permalink / raw)
  To: Justin Tee, Christoph Hellwig, Sagi Grimberg, Keith Busch,
	linux-nvme
  Cc: Naresh Gottumukkala, Paul Ely, Chaitanya Kulkarni, James Smart,
	linux-kernel, stable, yhlee

Agreed.  v2 adds a ->get_mdts callback that advertises the 16 MiB ceiling
so a compliant host keeps its transfers under it, and keeps the
allocation-time bound as enforcement for one that does not:
https://lore.kernel.org/linux-nvme/20261013153316.3178656-1-yhlee@isslab.korea.ac.kr/


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

end of thread, other threads:[~2026-10-13 15:53 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-13 10:40 [PATCH] nvmet-fc: bound the FCP command data length before allocating buffers Yehyeong Lee
2026-10-13 14:19 ` Christoph Hellwig
2026-10-13 15:53   ` Yehyeong Lee

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