[PATCH v3 4/5] nvme: clamp FDP placement handle count to the buffer size

Guixin Liu <[email protected]> Tue, 4 Aug 2026 10:19:00 +0800
Newsgroups org.infradead.lists.linux-nvme
Message-ID <[email protected]>
nvme_query_fdp_info() allocates the RUH status buffer for at most
S8_MAX - 1 descriptors and caps the io-mgmt-receive transfer to that
size. head->nr_plids, however, is taken verbatim from the device-supplied
nruhsd field, which can be up to 65535. If a non-conformant or malicious
device reports more descriptors than the buffer holds, the copy loop
reads past the end of the ruhs buffer (heap out-of-bounds read).

Clamp nr_plids to the number of descriptors the buffer can actually hold.

Fixes: 30b5f20bb2dd ("nvme: register fdp parameters with the block layer")
Signed-off-by: Guixin Liu <[email protected]>
Reviewed-by: Hannes Reinecke <[email protected]>
Reviewed-by: Kanchan Joshi <[email protected]>
Reviewed-by: Christoph Hellwig <[email protected]>
Reviewed-by: Nilay Shroff <[email protected]>
---
 drivers/nvme/host/core.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 453c1f0b2dd0..b1f444cd3daf 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -2358,6 +2358,7 @@ static int nvme_query_fdp_info(struct nvme_ns *ns, struct nvme_ns_info *info)
 	}
 
 	head->nr_plids = le16_to_cpu(ruhs->nruhsd);
+	head->nr_plids = min_t(u16, head->nr_plids, S8_MAX - 1);
 	if (!head->nr_plids)
 		goto free;
 
-- 
2.43.7