git: b6ecef28bfd7 - main - bhyve: Address uses of uninitialized variables in pci_nvme.c

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Sun, 14 Aug 2022 16:07:26 UTC
The branch main has been updated by markj:

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

commit b6ecef28bfd7c1c267442fae1c8f2fe0f699f617
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2022-08-14 15:57:24 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2022-08-14 15:59:01 +0000

    bhyve: Address uses of uninitialized variables in pci_nvme.c
    
    The debug print in nvme_opc_get_log_page() would print an uninitialized
    local variable.
    
    In nvme_opc_write_read(), a failed LBA bounds check would cause
    pci_nvme_stats_write_read_update() to be called with an uninitialized
    variable as a parameter.  Although the parameter is unused when the
    check fails (and so status != 0), LLVM 14 emits some bogus machine code
    in this path, which happens to result in a segfault when it gets
    executed.
    
    PR:             265749
    Reviewed by:    chuck, emaste
    MFC after:      2 weeks
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D36119
---
 usr.sbin/bhyve/pci_nvme.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/usr.sbin/bhyve/pci_nvme.c b/usr.sbin/bhyve/pci_nvme.c
index b832caa6f05d..38102beb0152 100644
--- a/usr.sbin/bhyve/pci_nvme.c
+++ b/usr.sbin/bhyve/pci_nvme.c
@@ -1418,9 +1418,7 @@ nvme_opc_get_log_page(struct pci_nvme_softc* sc, struct nvme_command* command,
 {
 	uint64_t logoff;
 	uint32_t logsize;
-	uint8_t logpage = command->cdw10 & 0xFF;
-
-	DPRINTF("%s log page %u len %u", __func__, logpage, logsize);
+	uint8_t logpage;
 
 	pci_nvme_status_genc(&compl->status, NVME_SC_SUCCESS);
 
@@ -1428,10 +1426,13 @@ nvme_opc_get_log_page(struct pci_nvme_softc* sc, struct nvme_command* command,
 	 * Command specifies the number of dwords to return in fields NUMDU
 	 * and NUMDL. This is a zero-based value.
 	 */
+	logpage = command->cdw10 & 0xFF;
 	logsize = ((command->cdw11 << 16) | (command->cdw10 >> 16)) + 1;
 	logsize *= sizeof(uint32_t);
 	logoff  = ((uint64_t)(command->cdw13) << 32) | command->cdw12;
 
+	DPRINTF("%s log page %u len %u", __func__, logpage, logsize);
+
 	switch (logpage) {
 	case NVME_LOG_ERROR:
 		if (logoff >= sizeof(sc->err_log)) {
@@ -2507,6 +2508,12 @@ nvme_opc_write_read(struct pci_nvme_softc *sc,
 
 	lba = ((uint64_t)cmd->cdw11 << 32) | cmd->cdw10;
 	nblocks = (cmd->cdw12 & 0xFFFF) + 1;
+	bytes = nblocks << nvstore->sectsz_bits;
+	if (bytes > NVME_MAX_DATA_SIZE) {
+		WPRINTF("%s command would exceed MDTS", __func__);
+		pci_nvme_status_genc(status, NVME_SC_INVALID_FIELD);
+		goto out;
+	}
 
 	if (pci_nvme_out_of_range(nvstore, lba, nblocks)) {
 		WPRINTF("%s command would exceed LBA range(slba=%#lx nblocks=%#lx)",
@@ -2515,13 +2522,6 @@ nvme_opc_write_read(struct pci_nvme_softc *sc,
 		goto out;
 	}
 
-	bytes  = nblocks << nvstore->sectsz_bits;
-	if (bytes > NVME_MAX_DATA_SIZE) {
-		WPRINTF("%s command would exceed MDTS", __func__);
-		pci_nvme_status_genc(status, NVME_SC_INVALID_FIELD);
-		goto out;
-	}
-
 	offset = lba << nvstore->sectsz_bits;
 
 	req->bytes = bytes;