git: 45ddbf211274 - main - bhyve: avoid overflow of BAR index

From: Emmanuel Vadot <manu_at_FreeBSD.org>
Date: Fri, 01 Apr 2022 09:19:40 UTC
The branch main has been updated by manu:

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

commit 45ddbf211274eb28c0ccd0042640de57015dd390
Author:     Corvin Köhne <CorvinK@beckhoff.com>
AuthorDate: 2022-04-01 08:18:52 +0000
Commit:     Emmanuel Vadot <manu@FreeBSD.org>
CommitDate: 2022-04-01 09:13:16 +0000

    bhyve: avoid overflow of BAR index
    
    At the moment, writes to BAR registers that aren't 4 byte aligned are
    ignored. So, there's no overflow yet. Nevertheless, if this behaviour
    changes in the future, it could unintentionally, introduce a buffer
    overflow. Additionally, some compiler or tools will detect this
    potential overflow and complain about it.
    
    Reviewed by:    markj
    Signed-off-by: Corvin Köhne <c.koehne@beckhoff.com>
    Reported-by: Andy Fiddaman <andy@omniosce.org>
    Differential Revision:  https://reviews.freebsd.org/D34689
---
 usr.sbin/bhyve/pci_emul.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c
index 6005513eafe4..ab90c01c2394 100644
--- a/usr.sbin/bhyve/pci_emul.c
+++ b/usr.sbin/bhyve/pci_emul.c
@@ -166,6 +166,18 @@ CFGREAD(struct pci_devinst *pi, int coff, int bytes)
 		return (pci_get_cfgdata32(pi, coff));
 }
 
+static int
+is_pcir_bar(int coff)
+{
+	return (coff >= PCIR_BAR(0) && coff < PCIR_BAR(PCI_BARMAX + 1));
+}
+
+static int
+is_pcir_bios(int coff)
+{
+	return (coff >= PCIR_BIOS && coff < PCIR_BIOS + 4);
+}
+
 /*
  * I/O access
  */
@@ -2107,19 +2119,23 @@ pci_cfgrw(struct vmctx *ctx, int vcpu, int in, int bus, int slot, int func,
 		/*
 		 * Special handling for write to BAR and ROM registers
 		 */
-		if ((coff >= PCIR_BAR(0) && coff < PCIR_BAR(PCI_BARMAX + 1)) ||
-		    (coff >= PCIR_BIOS && coff < PCIR_BIOS + 4)) {
+		if (is_pcir_bar(coff) || is_pcir_bios(coff)) {
 			/*
 			 * Ignore writes to BAR registers that are not
 			 * 4-byte aligned.
 			 */
 			if (bytes != 4 || (coff & 0x3) != 0)
 				return;
-			if (coff != PCIR_BIOS) {
+
+			if (is_pcir_bar(coff)) {
 				idx = (coff - PCIR_BAR(0)) / 4;
-			} else {
+			} else if (is_pcir_bios(coff)) {
 				idx = PCI_ROM_IDX;
+			} else {
+				errx(4, "%s: invalid BAR offset %d", __func__,
+				    coff);
 			}
+
 			mask = ~(pi->pi_bar[idx].size - 1);
 			switch (pi->pi_bar[idx].type) {
 			case PCIBAR_NONE: