summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYifei Gao <gyf161023@gmail.com>2026-08-04 21:36:25 +0000
committerKeith Busch <kbusch@kernel.org>2026-08-11 08:53:28 -0700
commit659ae9d02cb5d72c76f74fff7441eb8fb64d8f5c (patch)
treef360704ab41e4ffd4e8181df9b9b4eb416785271
parent8ce883fd068b7ba9ab493cd3ecca3a7ea868c375 (diff)
nvmet: pci-epf: put CQ ref on create_cq mapping failure
nvmet_pci_epf_create_cq() calls nvmet_cq_create(), which takes a reference on the controller and installs the completion queue. If the subsequent PCI address-space mapping fails or returns a too-small partial mapping, the function jumps to err_internal / err_unmap_queue without calling nvmet_cq_put(). The matching put in nvmet_pci_epf_delete_cq() is gated on NVMET_PCI_EPF_Q_LIVE, which is only set after the mapping succeeds, so teardown never releases these references. A remote PCI host that drives Create IO CQ commands with a failing PRP1/pci_addr therefore leaks the CQ and a controller reference on each attempt. Drop the CQ reference on the mapping-failure paths. The err_internal and err_unmap_queue labels are only reachable after nvmet_cq_create() has succeeded, so this pairs the create/put correctly. Fixes: 0faa0fe6f90e ("nvmet: New NVMe PCI endpoint function target driver") Cc: stable@vger.kernel.org Reviewed-by: Damien Le Moal <dlemoal@kernel.org> Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Yifei Gao <gyf161023@gmail.com> Signed-off-by: Keith Busch <kbusch@kernel.org>
-rw-r--r--drivers/nvme/target/pci-epf.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c
index 4e9db96ebfec..794e88d1d9a5 100644
--- a/drivers/nvme/target/pci-epf.c
+++ b/drivers/nvme/target/pci-epf.c
@@ -1339,6 +1339,7 @@ err_unmap_queue:
nvmet_pci_epf_mem_unmap(ctrl->nvme_epf, &cq->pci_map);
err_internal:
status = NVME_SC_INTERNAL | NVME_STATUS_DNR;
+ nvmet_cq_put(&cq->nvme_cq);
err:
if (test_and_clear_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags))
nvmet_pci_epf_remove_irq_vector(ctrl, cq->vector);