[PATCH v2 0/4] nvmet: fix read data, status and length checks in fc, zns and pci-epf
From: Andrea Parri
Date: Thu Oct 22 2026 - 09:37:08 EST
A connected host can currently receive stale target memory through two
nvmet transports, and ZNS answers a Zone Management Receive whose NUMD
byte count wraps.
The FC transport sends a read buffer even when the command completes with
an error. Some errors occur before the command handler initializes that
buffer, so the host receives data left in the allocation.
The PCI endpoint transport allocates each read segment at the length of
the host's SGL data descriptor and sends every segment in full, even when
the descriptors describe more than the command transfers. The excess
reaches the host uninitialized, on any successful read.
Patch 1 makes the FC transport send read data only for successful
commands, matching the TCP and RDMA transports. Patch 2 rejects NUMD
values whose byte count wraps the u32 length calculation instead of
accepting the wrapped request.
Patch 3 fixes a related PCI endpoint bug that patch 4 depends on. The
transport reports every error it detects itself as a successful
completion, because nvmet_pci_epf_complete_iod() reloads the status from
a CQE that only the nvmet core fills in, so even a write whose data
could not be fetched is reported as written. Patch 4 then makes the
transport reject SGLs whose data descriptors do not add up to the
command's data length.
Patches 1 and 2 were tested on top of nvme-7.4 over the loop, tcp, rdma
(rdma_rxe) and fc (fcloop) transports, with a zoned null_blk namespace
for patch 2. Without them, a failed Identify over fc returns data and a
wrapping NUMD is accepted; with them, neither occurs on any of the four
transports.
blktests nvme/072 and nvme/074 cover patches 1 and 2:
https://lore.kernel.org/r/20261022130927.3583166-1-parri.andrea@xxxxxxxxx
Their results in virtme-ng VMs, on v7.3-rc4-108-g551c722f4080 without
the fixes and on nvme-7.4 with this series applied:
loop tcp rdma fc
unpatched 072 pass pass pass FAIL failed Identify transferred
4096 bytes
074 FAIL FAIL FAIL FAIL NUMD 0x4000000f not rejected
patched both pass pass pass pass
Niklas Cassel tested patches 3 and 4 on PCI endpoint hardware with fio
over SGLs, with no change in performance; that exercises the normal
paths, not the new error paths. The pci-epf side of patch 2 is
build-tested only.
An LLM found the bugs fixed here and wrote the fixes. Following commit
1e035297ffda ("docs: remove Assisted-by references"), this is noted here
rather than in Assisted-by trailers.
Changes since v1:
- Dropped commit 31b8a6af19b7 ("nvmet: zns: don't leak stale memory in
zone management receive"), applied to nvme-7.4.
- Patch 2: check NUMD at the start of
nvmet_bdev_execute_zone_mgmt_recv() and in nvmet_io_cmd_transfer_len(),
before any (numd + 1) << 2 is computed, and drop the over-long comment
line (Christoph).
- Patches 3 and 4: add Niklas's Tested-by.
- Patches 1, 3 and 4: no code changes.
- All patches: drop the Assisted-by trailers; LLM use is noted above.
- Rebased on nvme-7.4.
v1: https://lore.kernel.org/r/20261012141239.156408-1-parri.andrea@xxxxxxxxx
Andrea Parri (4):
nvmet-fc: only send read data for successful commands
nvmet: zns: reject a NUMD whose byte count wraps
nvmet: pci-epf: report transport errors in command completions
nvmet: pci-epf: require SGLs to match the command data length
drivers/nvme/target/core.c | 3 +++
drivers/nvme/target/fc.c | 8 ++++----
drivers/nvme/target/pci-epf.c | 30 +++++++++++++++++++++++++++---
drivers/nvme/target/zns.c | 12 ++++++++++--
4 files changed, 44 insertions(+), 9 deletions(-)
base-commit: 2e8e30b3cf9f165e1a1d079331543cb7f2ad0e0c
--
2.53.0