Skip to content

Commit

Permalink
bhyve/nvme: Fix out-of-bounds read in NVMe log page
Browse files Browse the repository at this point in the history
The function nvme_opc_get_log_page in the file usr.sbin/bhyve/pci_nvme.c
is vulnerable to buffer over-read. The value logoff is user controlled
but never checked against the value of logsize. Thus the difference:
	logsize - logoff
can underflow.

Due to the sc structure layout, an attacker can dump internals fields of
sc and the content of next heap allocation.

Reported by: Synacktiv
Reviewed by:	emaste, jhb
Security: HYP-07
Sponsored by: Alpha-Omega Project, The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D46021

(cherry picked from commit b0a24be)
(cherry picked from commit a5be19e)
  • Loading branch information
Chuck Tuffli authored and emaste committed Oct 11, 2024
1 parent 72e277f commit c8f7568
Showing 1 changed file with 5 additions and 5 deletions.
10 changes: 5 additions & 5 deletions usr.sbin/bhyve/pci_nvme.c
Original file line number Diff line number Diff line change
Expand Up @@ -1454,7 +1454,7 @@ nvme_opc_get_log_page(struct pci_nvme_softc* sc, struct nvme_command* command,
logsize *= sizeof(uint32_t);
logoff = ((uint64_t)(command->cdw13) << 32) | command->cdw12;

DPRINTF("%s log page %u len %u", __func__, logpage, logsize);
DPRINTF("%s log page %u offset %lu len %u", __func__, logpage, logoff, logsize);

switch (logpage) {
case NVME_LOG_ERROR:
Expand All @@ -1466,7 +1466,7 @@ nvme_opc_get_log_page(struct pci_nvme_softc* sc, struct nvme_command* command,

nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, command->prp1,
command->prp2, (uint8_t *)&sc->err_log + logoff,
MIN(logsize - logoff, sizeof(sc->err_log)),
MIN(logsize, sizeof(sc->err_log) - logoff),
NVME_COPY_TO_PRP);
break;
case NVME_LOG_HEALTH_INFORMATION:
Expand All @@ -1489,7 +1489,7 @@ nvme_opc_get_log_page(struct pci_nvme_softc* sc, struct nvme_command* command,

nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, command->prp1,
command->prp2, (uint8_t *)&sc->health_log + logoff,
MIN(logsize - logoff, sizeof(sc->health_log)),
MIN(logsize, sizeof(sc->health_log) - logoff),
NVME_COPY_TO_PRP);
break;
case NVME_LOG_FIRMWARE_SLOT:
Expand All @@ -1501,7 +1501,7 @@ nvme_opc_get_log_page(struct pci_nvme_softc* sc, struct nvme_command* command,

nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, command->prp1,
command->prp2, (uint8_t *)&sc->fw_log + logoff,
MIN(logsize - logoff, sizeof(sc->fw_log)),
MIN(logsize, sizeof(sc->fw_log) - logoff),
NVME_COPY_TO_PRP);
break;
case NVME_LOG_CHANGED_NAMESPACE:
Expand All @@ -1513,7 +1513,7 @@ nvme_opc_get_log_page(struct pci_nvme_softc* sc, struct nvme_command* command,

nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, command->prp1,
command->prp2, (uint8_t *)&sc->ns_log + logoff,
MIN(logsize - logoff, sizeof(sc->ns_log)),
MIN(logsize, sizeof(sc->ns_log) - logoff),
NVME_COPY_TO_PRP);
memset(&sc->ns_log, 0, sizeof(sc->ns_log));
break;
Expand Down

0 comments on commit c8f7568

Please sign in to comment.