* [PATCH 0/2] nvmet: pci-epf: fix a configfs overflow and a failed-read hang
@ 2026-11-03 19:07 shao.mingyin
2026-11-03 19:07 ` [PATCH 1/2] nvmet: pci-epf: fix subsysnqn configfs buffer overflow shao.mingyin
2026-11-03 19:07 ` [PATCH 2/2] nvmet: pci-epf: complete failed read commands instead of waiting forever shao.mingyin
0 siblings, 2 replies; 3+ messages in thread
From: shao.mingyin @ 2026-11-03 19:07 UTC (permalink / raw)
To: kbusch, axboe, hch, sagi, linux-nvme; +Cc: linux-kernel, stable
This series fixes two independent bugs in the NVMe PCI endpoint function
target driver.
Patch 1 fixes a heap overflow in the subsysnqn configfs attribute. The
store callback passed the length of the configfs write buffer to
strscpy() as the destination size; an NQN longer than NVMF_NQN_SIZE
therefore wrote past subsysnqn into the following fields of the
nvmet_pci_epf object.
Patch 2 fixes a hang on failed read commands. queue_response() completed
a command with a non-zero status directly, without waking
exec_iod_work(), which is waiting for the transfer of a DMA_TO_DEVICE
command. The completion queue work could then free the iod while the
work item was still waiting on iod->done. The work item now waits based
only on the data direction and length, and completes the command after
the wait even when it failed. This is a follow-up to the recent fix for
the use-after-free in the same function (c9e9bb757971), which moved the
wait decision earlier but left the failed-command case from
746d0ac5a07d in place.
The two patches are independent, have no inter-patch dependencies and can
be applied in any order or as a subset. Both carry Fixes: and
Cc: stable.
Testing: both apply to next-20261030, pass checkpatch.pl --strict with
0 errors/0 warnings/0 checks, and drivers/nvme/target/pci-epf.c builds
with CONFIG_NVME_TARGET_PCI_EPF=m and W=1 without new warnings.
Patch 1 was also reproduced and re-tested in QEMU (7.3.0-next-20261030,
configfs pci_ep framework, no endpoint controller needed): writing a
230-byte value through the subsysnqn attribute stored it and clobbered
mdts_kb (512 -> 4276545) before the fix, and is rejected with -EINVAL
after it. Patch 2 was not runtime-tested: this setup has no PCI
endpoint controller.
Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn>
---
base-commit: 7649ba73f9e7e1e04d0b46213e39c79ae09dd55c
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 1/2] nvmet: pci-epf: fix subsysnqn configfs buffer overflow
2026-11-03 19:07 [PATCH 0/2] nvmet: pci-epf: fix a configfs overflow and a failed-read hang shao.mingyin
@ 2026-11-03 19:07 ` shao.mingyin
2026-11-03 19:07 ` [PATCH 2/2] nvmet: pci-epf: complete failed read commands instead of waiting forever shao.mingyin
1 sibling, 0 replies; 3+ messages in thread
From: shao.mingyin @ 2026-11-03 19:07 UTC (permalink / raw)
To: kbusch, axboe, hch, sagi, linux-nvme; +Cc: linux-kernel, stable
nvmet_pci_epf_subsysnqn_store() passes the length of the configfs write
to strscpy() as the destination size:
strscpy(nvme_epf->subsysnqn, page, len);
The third argument of strscpy() is the size of the destination buffer,
not the length of the source string. The destination is
subsysnqn[NVMF_NQN_SIZE], i.e. 223 bytes, while a configfs attribute
store can carry up to 4095 bytes. A longer NQN therefore overflows
subsysnqn into the following mdts_kb field and past the nvmet_pci_epf
object, corrupting the heap.
Using the write length also silently dropped the last byte of the value:
configfs terminates the buffer after the trailing newline that echo(1)
writes, so a normal write stored the right NQN while a write without a
newline lost its last character.
Take the length of the value up to the newline, reject a value that does
not fit and copy the NQN explicitly.
Fixes: 0faa0fe6f90e ("nvmet: New NVMe PCI endpoint function target driver")
Cc: stable@vger.kernel.org
Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn>
---
Tested on 7.3.0-next-20261030 (QEMU/TCG guest) with configfs and
nvmet-pci-epf; the attribute store does not need a PCI endpoint
controller.
Writing 230 bytes to the subsysnqn attribute of an nvmet_pci_epf
instance runs past subsysnqn[NVMF_NQN_SIZE] (223) and overwrites the
following mdts_kb field:
unpatched patched
write accepted write rejected (-EINVAL)
mdts_kb 512 -> 4276545 (0x414141) mdts_kb stays 512
diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c
index a8df176c1a57..38c210cac961 100644
--- a/drivers/nvme/target/pci-epf.c
+++ b/drivers/nvme/target/pci-epf.c
@@ -2531,15 +2531,18 @@ static ssize_t nvmet_pci_epf_subsysnqn_store(struct config_item *item,
{
struct config_group *group = to_config_group(item);
struct nvmet_pci_epf *nvme_epf = to_nvme_epf(group);
+ size_t nqn_len;
/* Do not allow setting this when the function is already started. */
if (nvme_epf->ctrl.tctrl)
return -EBUSY;
- if (!len)
+ nqn_len = strcspn(page, "\n");
+ if (!nqn_len || nqn_len >= sizeof(nvme_epf->subsysnqn))
return -EINVAL;
- strscpy(nvme_epf->subsysnqn, page, len);
+ memcpy(nvme_epf->subsysnqn, page, nqn_len);
+ nvme_epf->subsysnqn[nqn_len] = '\0';
return len;
}
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 2/2] nvmet: pci-epf: complete failed read commands instead of waiting forever
2026-11-03 19:07 [PATCH 0/2] nvmet: pci-epf: fix a configfs overflow and a failed-read hang shao.mingyin
2026-11-03 19:07 ` [PATCH 1/2] nvmet: pci-epf: fix subsysnqn configfs buffer overflow shao.mingyin
@ 2026-11-03 19:07 ` shao.mingyin
1 sibling, 0 replies; 3+ messages in thread
From: shao.mingyin @ 2026-11-03 19:07 UTC (permalink / raw)
To: kbusch, axboe, hch, sagi, linux-nvme; +Cc: linux-kernel, stable
nvmet_pci_epf_queue_response() completes a command directly when its
status is non-zero, without calling complete(&iod->done). For commands
that transfer data from the device to the host (DMA_TO_DEVICE),
nvmet_pci_epf_exec_iod_work() clears no_wait and waits for iod->done
after req->execute() has returned. If such a command fails
synchronously, for example because the request length or SGL is invalid
or because the backend rejects the command, the work item waits forever
on iod->done while the completion path has already queued the iod for
the completion queue work, which eventually frees it: the waiter is left
on a freed completion and the SQ worker is stuck.
Only decide whether the work item has to wait from the data direction
and length, and let it complete the command after the wait even when the
command failed. This preserves exactly one
nvmet_pci_epf_complete_iod() per command and also wakes the waiter for
failed read commands.
Fixes: 746d0ac5a07d ("nvmet: pci-epf: Do not complete commands twice if nvmet_req_init() fails")
Cc: stable@vger.kernel.org
Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn>
---
diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c
index a8df176c1a57..b12855b57b59 100644
--- a/drivers/nvme/target/pci-epf.c
+++ b/drivers/nvme/target/pci-epf.c
@@ -1248,10 +1248,11 @@ static void nvmet_pci_epf_queue_response(struct nvmet_req *req)
iod->status = le16_to_cpu(req->cqe->status) >> 1;
/*
- * If the command failed or we have no data to transfer, complete the
- * command immediately.
+ * If we have no data to transfer back to the host, complete the
+ * command immediately. Otherwise wake up the work item, which
+ * transfers the data and completes the command even if it failed.
*/
- if (iod->status || !iod->data_len || iod->dma_dir != DMA_TO_DEVICE) {
+ if (!iod->data_len || iod->dma_dir != DMA_TO_DEVICE) {
nvmet_pci_epf_complete_iod(iod);
return;
}
@@ -1659,7 +1660,7 @@ static void nvmet_pci_epf_exec_iod_work(struct work_struct *work)
wait_for_completion(&iod->done);
if (iod->status != NVME_SC_SUCCESS)
- return;
+ goto complete;
WARN_ON_ONCE(!iod->data_len || iod->dma_dir != DMA_TO_DEVICE);
nvmet_pci_epf_transfer_iod_data(iod);
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-11-03 19:07 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-03 19:07 [PATCH 0/2] nvmet: pci-epf: fix a configfs overflow and a failed-read hang shao.mingyin
2026-11-03 19:07 ` [PATCH 1/2] nvmet: pci-epf: fix subsysnqn configfs buffer overflow shao.mingyin
2026-11-03 19:07 ` [PATCH 2/2] nvmet: pci-epf: complete failed read commands instead of waiting forever shao.mingyin
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®