From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794063734; b=mXjRI1sAsiNoLPsgpk7aXdHAwViXA4MFUWWDC3CYCBk53N+eUF6VISIwQXJyNd8DCXmy XTrup5dM9G7cmsDKZeHgYzJesZKOBCIGBbTCRakDgPJEpEfxRhC+P9dV+zgR9grrqqd64 Jc5D0KVR7TDQHFuhrh36gwdATHJfoVWMQGfOPG4nnCZTjF6xAMDe6AgogOPJfJY4YZG4I 4T6oiTYnqfeUGaHEjWzhUkmug+jxEefpZ4AdtCNRMImvR037AUklDeaP4bk8e2B/DdgiT TnJplnEoPfx+ASwSC6aK0q8Oz42wMBFEvSnxca2DLNQMxXaV90+wgd2wFjHx+/AW1vA== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794063734; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:User-Agent:X-stable:X-Patchwork-Hint: MIME-Version:Content-Transfer-Encoding; bh=AF/alENvRGis3te5F+8tiqQxL6yxmDcfKhUwvAiyEtA=; b=wdCCD2FXIzoeKEACjQkR6ch2ukaDnxn5kGlcEjVXlv2H48FYb60YYxHuFnaAof/kXE+l Q1NdBcnNMoa42VkVSsa/YgzRz3p0hOUwM+Hpkj1zt9LJfa8wSsh11npv3/uUfHaAoQGB3 kueZIExQct1M9A4twVgcrIGnInvwlITnBY5dNU6EmBxSYn9FyqcnXmH772r7UvSxDCoxC 9BsKwPxh0nOcZIG3HXUesybNDjcap7S067nSs8z2S1fy5ZpZ0tjmI9ErRZyFbtxHoFOnS tJvo1KYWtnTWDZaDVbkp0+yz+X8LV8NYYMHS1V3JnfaD17jQjRnUQU6UlbSHfJ+AnvQ== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b="Gtv/iYQp"; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 74892606D802; Sat, 7 Nov 2026 15:02:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=Gtv/iYQp Received: by smtp.kernel.org (Postfix) with ESMTPSA id 16B261F0089F; Sat, 7 Nov 2026 15:02:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1794063734; bh=AF/alENvRGis3te5F+8tiqQxL6yxmDcfKhUwvAiyEtA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Gtv/iYQpupRvA+9VXpD/5JkpYtPyFn2Ms+RdizCbfpcPqDwXC2RlDQ/lLzqdjwJeT wMtvexPxbITjKRB58lnTI8c0tTLLtftWvkKzrvbQSs3hrs6/yv06fxymyQV9VYEpZB pIXbTqwYcz/yCLyZhT+pQGJTDvGGQLT89mV8tsoE= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Niklas Cassel , Andrea Parri , Keith Busch , Sasha Levin Subject: [PATCH 6.18 831/869] nvmet: pci-epf: require SGLs to match the command data length Date: Sat, 7 Nov 2026 08:58:33 -0500 Message-ID: <20261107134921.099719391@linuxfoundation.org> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261107134852.069646174@linuxfoundation.org> References: <20261107134852.069646174@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore X-Mailing-List: stable@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.18-stable review patch. If anyone has any objections, please let me know. ------------------ From: Andrea Parri [ Upstream commit 9fb4adbc39751697b9fcf71e45bd5d5119c3f07c ] 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 Signed-off-by: Andrea Parri Signed-off-by: Keith Busch Signed-off-by: Sasha Levin --- 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 a85f21a593706..dcc6cae6f3c5e 100644 --- a/drivers/nvme/target/pci-epf.c +++ b/drivers/nvme/target/pci-epf.c @@ -1095,10 +1095,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. */ @@ -1106,10 +1118,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