git: 9d8cd04694d4 - main - bhyve nvme: Fix LBA out-of-range calculation

From: Chuck Tuffli <chuck_at_FreeBSD.org>
Date: Sat, 29 Jan 2022 23:15:47 UTC
The branch main has been updated by chuck:

URL: https://cgit.FreeBSD.org/src/commit/?id=9d8cd04694d47d48cc4003f8322739ba10fa8108

commit 9d8cd04694d47d48cc4003f8322739ba10fa8108
Author:     Chuck Tuffli <chuck@FreeBSD.org>
AuthorDate: 2022-01-30 07:09:57 +0000
Commit:     Chuck Tuffli <chuck@FreeBSD.org>
CommitDate: 2022-01-30 07:09:57 +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.
    
    Reviewed by:    imp, allanjude, jhb
    Tested by:      jason@tubnor.net
    MFC after:      1 month
    Differential Revision:  https://reviews.freebsd.org/D33575
---
 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 ea3503bdbfc0..5ad7a0a59d65 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;
 	}