git: 541ff74584e1 - stable/13 - bhyve nvme: Fix LBA out-of-range calculation

From: Chuck Tuffli <chuck_at_FreeBSD.org>
Date: Mon, 21 Feb 2022 21:58:02 UTC
The branch stable/13 has been updated by chuck:

URL: https://cgit.FreeBSD.org/src/commit/?id=541ff74584e13c4543bb096915a3a39b57834b24

commit 541ff74584e13c4543bb096915a3a39b57834b24
Author:     Chuck Tuffli <chuck@FreeBSD.org>
AuthorDate: 2022-01-30 07:09:57 +0000
Commit:     Chuck Tuffli <chuck@FreeBSD.org>
CommitDate: 2022-02-22 03:27:47 +0000

    bhyve nvme: Fix LBA out-of-range calculation
    
    The function which checks for a valid LBA range mistakenly named an
    input value as NLB ("Number of Logical Blocks") instead of "number of
    blocks". The NVMe specification defines NLB as a zero-based value (i.e.
    NLB=0x0 represents 1 block, 0x1 is 2 blocks, etc.), but the passed
    parameter is a 1's-based value.
    
    Fix is to rename the variable to avoid future confusion.
    
    While in the neighborhood, also check that the starting LBA is less than
    the size of the backing storage to avoid an integer overflow.
    
    (cherry picked from commit 9d8cd04694d47d48cc4003f8322739ba10fa8108)
---
 usr.sbin/bhyve/pci_nvme.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/usr.sbin/bhyve/pci_nvme.c b/usr.sbin/bhyve/pci_nvme.c
index aff881bd5056..66ca3dcdf38e 100644
--- a/usr.sbin/bhyve/pci_nvme.c
+++ b/usr.sbin/bhyve/pci_nvme.c
@@ -2103,8 +2103,8 @@ pci_nvme_stats_write_read_update(struct pci_nvme_softc *sc, uint8_t opc,
 }
 
 /*
- * Check if the combination of Starting LBA (slba) and Number of Logical
- * Blocks (nlb) exceeds the range of the underlying storage.
+ * Check if the combination of Starting LBA (slba) and number of blocks
+ * exceeds the range of the underlying storage.
  *
  * Because NVMe specifies the SLBA in blocks as a uint64_t and blockif stores
  * the capacity in bytes as a uint64_t, care must be taken to avoid integer
@@ -2112,7 +2112,7 @@ pci_nvme_stats_write_read_update(struct pci_nvme_softc *sc, uint8_t opc,
  */
 static bool
 pci_nvme_out_of_range(struct pci_nvme_blockstore *nvstore, uint64_t slba,
-    uint32_t nlb)
+    uint32_t nblocks)
 {
 	size_t	offset, bytes;
 
@@ -2121,10 +2121,10 @@ pci_nvme_out_of_range(struct pci_nvme_blockstore *nvstore, uint64_t slba,
 		return (true);
 
 	offset = slba << nvstore->sectsz_bits;
-	bytes = nlb << nvstore->sectsz_bits;
+	bytes = nblocks << nvstore->sectsz_bits;
 
 	/* Overflow check of Number of Logical Blocks */
-	if ((nvstore->size - offset) < bytes)
+	if ((nvstore->size <= offset) || ((nvstore->size - offset) < bytes))
 		return (true);
 
 	return (false);
@@ -2433,7 +2433,8 @@ nvme_opc_write_read(struct pci_nvme_softc *sc,
 	nblocks = (cmd->cdw12 & 0xFFFF) + 1;
 
 	if (pci_nvme_out_of_range(nvstore, lba, nblocks)) {
-		WPRINTF("%s command would exceed LBA range", __func__);
+		WPRINTF("%s command would exceed LBA range(slba=%#lx nblocks=%#lx)",
+		    __func__, lba, nblocks);
 		pci_nvme_status_genc(status, NVME_SC_LBA_OUT_OF_RANGE);
 		goto out;
 	}