Linux kernel -stable discussions
 help / color / mirror / Atom feed
* [PATCH v2 1/4] nvmet-fc: only send read data for successful commands
       [not found] <20261022132934.3592924-1-parri.andrea@gmail.com>
@ 2026-10-22 13:29 ` Andrea Parri
  2026-10-28 14:54   ` Christoph Hellwig
  2026-10-22 13:29 ` [PATCH v2 3/4] nvmet: pci-epf: report transport errors in command completions Andrea Parri
  2026-10-22 13:29 ` [PATCH v2 4/4] nvmet: pci-epf: require SGLs to match the command data length Andrea Parri
  2 siblings, 1 reply; 4+ messages in thread
From: Andrea Parri @ 2026-10-22 13:29 UTC (permalink / raw)
  To: Justin Tee, Naresh Gottumukkala, Paul Ely, Christoph Hellwig,
	Sagi Grimberg, Chaitanya Kulkarni
  Cc: Andrea Parri, Johannes Thumshirn, James Smart, Keith Busch,
	linux-nvme, linux-kernel, stable

When a read command completes with an error,
__nvmet_fc_fcp_nvme_cmd_done() still pushes the whole data buffer to
the host before the response. nvmet_fc_alloc_tgt_pgs() allocates that
buffer with sgl_alloc() and no __GFP_ZERO, and a command rejected by
nvmet_check_transfer_len() leaves it untouched, so the host receives
stale target memory.

The buffer is as large as the data length in the command IU, so the
amount of stale memory returned is up to the host.

The tcp and rdma targets send data only when cqe->status is zero (see
nvmet_tcp_need_data_out() and nvmet_rdma_need_data_out()), so no nvmet
command can rely on returning data with an error status. Do the same
for fc. The ERSP then reports a transferred length of fod->offset,
which is 0, matching what nvme_fc_fcpio_done() checks on the host.

Tested over nvme-fcloop: a failed read command no longer transfers
data and still completes with its error status, and successful reads
are unaffected.

Fixes: c53432030d86 ("nvme-fabrics: Add target support for FC transport")
Cc: stable@vger.kernel.org
Signed-off-by: Andrea Parri <parri.andrea@gmail.com>
---
 drivers/nvme/target/fc.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c
index eecdffefa24fa..b95893adae36c 100644
--- a/drivers/nvme/target/fc.c
+++ b/drivers/nvme/target/fc.c
@@ -2487,11 +2487,11 @@ __nvmet_fc_fcp_nvme_cmd_done(struct nvmet_fc_tgtport *tgtport,
 	} else {
 
 		/*
-		 * try to push the data even if the SQE status is non-zero.
-		 * There may be a status where data still was intended to
-		 * be moved
+		 * A failed command may not have filled its read buffer, so
+		 * only push data for success, as the tcp and rdma targets do.
 		 */
-		if ((fod->io_dir == NVMET_FCP_READ) && (fod->data_sg_cnt)) {
+		if (fod->io_dir == NVMET_FCP_READ && fod->data_sg_cnt &&
+		    !cqe->status) {
 			/* push the data over before sending rsp */
 			nvmet_fc_transfer_fcp_data(tgtport, fod,
 						NVMET_FCOP_READDATA);
-- 
2.53.0


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

* [PATCH v2 3/4] nvmet: pci-epf: report transport errors in command completions
       [not found] <20261022132934.3592924-1-parri.andrea@gmail.com>
  2026-10-22 13:29 ` [PATCH v2 1/4] nvmet-fc: only send read data for successful commands Andrea Parri
@ 2026-10-22 13:29 ` Andrea Parri
  2026-10-22 13:29 ` [PATCH v2 4/4] nvmet: pci-epf: require SGLs to match the command data length Andrea Parri
  2 siblings, 0 replies; 4+ messages in thread
From: Andrea Parri @ 2026-10-22 13:29 UTC (permalink / raw)
  To: Christoph Hellwig, Sagi Grimberg, Chaitanya Kulkarni
  Cc: Andrea Parri, Damien Le Moal, Keith Busch, Manivannan Sadhasivam,
	Krzysztof Wilczyński, Niklas Cassel, linux-nvme,
	linux-kernel, stable

When the PCI endpoint target fails a command itself, the host receives a
successful completion. This happens for a data length above MDTS,
malformed PRPs or SGLs, a buffer allocation failure, an SQ that is not
live, and a failed DMA of the command data. A write whose data cannot be
fetched from the host is thus reported as written, though nothing was
executed.

Each of these paths sets iod->status and calls
nvmet_pci_epf_complete_iod(), which then reloads iod->status from
iod->cqe.status. The nvmet core only fills that field when it completes
the request, which these paths never do, so it is still zero and
nvmet_pci_epf_cq_work() posts a success status to the host.

Drop the reload. Every path already sets iod->status before completion:
nvmet_pci_epf_queue_response() copies it from the request's CQE, and
the transport error paths set it themselves.

Found by code inspection.

Fixes: 0faa0fe6f90e ("nvmet: New NVMe PCI endpoint function target driver")
Cc: stable@vger.kernel.org
Tested-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Andrea Parri <parri.andrea@gmail.com>
---
 drivers/nvme/target/pci-epf.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c
index 9c28367435a59..099e8766f6d40 100644
--- a/drivers/nvme/target/pci-epf.c
+++ b/drivers/nvme/target/pci-epf.c
@@ -1149,7 +1149,6 @@ static void nvmet_pci_epf_complete_iod(struct nvmet_pci_epf_iod *iod)
 	unsigned long flags;
 
 	/* Print an error message for failed commands, except AENs. */
-	iod->status = le16_to_cpu(iod->cqe.status) >> 1;
 	if (iod->status && iod->cmd.common.opcode != nvme_admin_async_event)
 		dev_err(iod->ctrl->dev,
 			"CQ[%d]: Command %s (0x%x) status 0x%0x\n",
-- 
2.53.0


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

* [PATCH v2 4/4] nvmet: pci-epf: require SGLs to match the command data length
       [not found] <20261022132934.3592924-1-parri.andrea@gmail.com>
  2026-10-22 13:29 ` [PATCH v2 1/4] nvmet-fc: only send read data for successful commands Andrea Parri
  2026-10-22 13:29 ` [PATCH v2 3/4] nvmet: pci-epf: report transport errors in command completions Andrea Parri
@ 2026-10-22 13:29 ` Andrea Parri
  2 siblings, 0 replies; 4+ messages in thread
From: Andrea Parri @ 2026-10-22 13:29 UTC (permalink / raw)
  To: Christoph Hellwig, Sagi Grimberg, Chaitanya Kulkarni
  Cc: Andrea Parri, Damien Le Moal, Keith Busch, Manivannan Sadhasivam,
	Krzysztof Wilczyński, Niklas Cassel, linux-nvme,
	linux-kernel, stable

The PCI endpoint target sends the host every byte a read command's SGL
describes, even when the SGL describes more than the command transfers.
The excess is kmalloc() memory the command never wrote, so the host
receives stale target memory. Any successful read can do this,
including Identify.

nvmet_pci_epf_alloc_iod_data_buf() allocates each segment at the length
of its SGL data descriptor, but sets req->transfer_len from
iod->data_len, the length the command implies. Once the command
completes, nvmet_pci_epf_transfer_iod_data() sends every segment in
full. Nothing compares the descriptor lengths with iod->data_len, and
the MDTS check only bounds iod->data_len.

Fail the command with Data SGL Length Invalid when the data descriptors
do not add up to iod->data_len, before any segment is allocated. The
tcp and rdma transports take the data length from the SGL itself, so
there most commands already reject a mismatch in
nvmet_check_transfer_len(). PRP lists are built from iod->data_len and
are unaffected.

Found by code inspection.

Fixes: 0faa0fe6f90e ("nvmet: New NVMe PCI endpoint function target driver")
Cc: stable@vger.kernel.org
Tested-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Andrea Parri <parri.andrea@gmail.com>
---
For stable, this depends on patch 3/4: without it, the new Data SGL
Length Invalid error is still reported to the host as a success.

 drivers/nvme/target/pci-epf.c | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c
index 099e8766f6d40..0cc198f87dec3 100644
--- a/drivers/nvme/target/pci-epf.c
+++ b/drivers/nvme/target/pci-epf.c
@@ -1070,10 +1070,22 @@ static int nvmet_pci_epf_iod_parse_sgl_segments(struct nvmet_pci_epf_ctrl *ctrl,
 	return 0;
 }
 
+static u64 nvmet_pci_epf_iod_data_segs_len(struct nvmet_pci_epf_iod *iod)
+{
+	u64 len = 0;
+	int i;
+
+	for (i = 0; i < iod->nr_data_segs; i++)
+		len += iod->data_segs[i].length;
+
+	return len;
+}
+
 static int nvmet_pci_epf_iod_parse_sgls(struct nvmet_pci_epf_iod *iod)
 {
 	struct nvmet_pci_epf_ctrl *ctrl = iod->ctrl;
 	struct nvme_sgl_desc *sgl = &iod->cmd.common.dptr.sgl;
+	int ret;
 
 	if (sgl->type == (NVME_SGL_FMT_DATA_DESC << 4)) {
 		/* Single data descriptor case. */
@@ -1081,10 +1093,23 @@ static int nvmet_pci_epf_iod_parse_sgls(struct nvmet_pci_epf_iod *iod)
 		iod->data_segs = &iod->data_seg;
 		iod->data_seg.pci_addr = le64_to_cpu(sgl->addr);
 		iod->data_seg.length = le32_to_cpu(sgl->length);
-		return 0;
+	} else {
+		ret = nvmet_pci_epf_iod_parse_sgl_segments(ctrl, iod);
+		if (ret)
+			return ret;
 	}
 
-	return nvmet_pci_epf_iod_parse_sgl_segments(ctrl, iod);
+	/*
+	 * The command executes on data_len bytes, but each segment is
+	 * allocated and transferred in full, so they must describe exactly
+	 * data_len bytes.
+	 */
+	if (nvmet_pci_epf_iod_data_segs_len(iod) != iod->data_len) {
+		iod->status = NVME_SC_SGL_INVALID_DATA | NVME_STATUS_DNR;
+		return -EINVAL;
+	}
+
+	return 0;
 }
 
 static int nvmet_pci_epf_alloc_iod_data_buf(struct nvmet_pci_epf_iod *iod)
-- 
2.53.0


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

* Re: [PATCH v2 1/4] nvmet-fc: only send read data for successful commands
  2026-10-22 13:29 ` [PATCH v2 1/4] nvmet-fc: only send read data for successful commands Andrea Parri
@ 2026-10-28 14:54   ` Christoph Hellwig
  0 siblings, 0 replies; 4+ messages in thread
From: Christoph Hellwig @ 2026-10-28 14:54 UTC (permalink / raw)
  To: Andrea Parri
  Cc: Justin Tee, Naresh Gottumukkala, Paul Ely, Christoph Hellwig,
	Sagi Grimberg, Chaitanya Kulkarni, Johannes Thumshirn,
	James Smart, Keith Busch, linux-nvme, linux-kernel, stable

Looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>


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

end of thread, other threads:[~2026-10-28 14:54 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20261022132934.3592924-1-parri.andrea@gmail.com>
2026-10-22 13:29 ` [PATCH v2 1/4] nvmet-fc: only send read data for successful commands Andrea Parri
2026-10-28 14:54   ` Christoph Hellwig
2026-10-22 13:29 ` [PATCH v2 3/4] nvmet: pci-epf: report transport errors in command completions Andrea Parri
2026-10-22 13:29 ` [PATCH v2 4/4] nvmet: pci-epf: require SGLs to match the command data length Andrea Parri

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