diff options
author | Corvin Köhne <CorvinK@beckhoff.com> | 2022-04-01 08:18:52 +0000 |
---|---|---|
committer | Emmanuel Vadot <manu@FreeBSD.org> | 2022-04-01 09:13:16 +0000 |
commit | 45ddbf211274eb28c0ccd0042640de57015dd390 (patch) | |
tree | 9dbef63b34f8de88e9fd4cc5bc0703f149d82e3a | |
parent | 4fc5a607fdf47ce5148e01d62ea474a4b6b0b238 (diff) | |
download | src-45ddbf211274eb28c0ccd0042640de57015dd390.tar.gz src-45ddbf211274eb28c0ccd0042640de57015dd390.zip |
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
-rw-r--r-- | usr.sbin/bhyve/pci_emul.c | 24 |
1 files 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: |