CVE-2019-18844 (C, published 2019-11-13T20:15Z)
Description: value: The Device Model in ACRN before 2019w25.5-140000p relies on assert calls in devicemodel/hw/pci/core.c and devicemodel/include/pci_core.h (instead of other mechanisms for propagating error information or diagnostic information), which might allow attackers to cause a denial of service (assertion failure) within pci core. This is fixed in 1.2. 6199e653418e is a mitigation for pre-1.1 versions, whereas 2b3dedfb9ba1 is a mitigation for 1.1.
Severity: MEDIUM (CVSS v3 base score: 7.5)
Weakness: CWE-617 \u2014 Reachable Assertion
The product contains an assert() or similar statement that can be triggered by an attacker, which leads to an application exit or other behavior that is more severe than necessary.
Repository: https://github.com/projectacrn/acrn-hypervisor
Files changed:
devicemodel/hw/pci/core.c
devicemodel/include/pci_core.h
devicemodel/include/types.h
Commit message: dm: pci: clean up assert() in pci core

Tracked-On: #3252
Signed-off-by: Shuo A Liu <shuo.a.liu@intel.com>
Reviewed-by: Yonghua Huang <yonghua.huang@intel.com>


Vulnerable code:
	assert(bidx <= PCI_BARMAX);
	assert(pdi->bar[bidx].type == PCIBAR_MEM32 ||
	       pdi->bar[bidx].type == PCIBAR_MEM64);
	assert(addr >= pdi->bar[bidx].addr &&
	       addr + size <= pdi->bar[bidx].addr + pdi->bar[bidx].size);
	assert((size & (size - 1)) == 0);	/* must be a power of 2 */
static void
		return;
	assert(error == 0);
		assert(0);
	assert(idx >= 0 && idx <= PCI_BARMAX);

		printf("%s: invalid bar type %d\n", __func__, type);
		assert(0);
		assert(idx + 1 <= PCI_BARMAX);
	assert(caplen > 0);

void
	assert((msgnum & (msgnum - 1)) == 0 && msgnum >= 1 && msgnum <= 32);
	pci_populate_msicap(&msicap, msgnum, 0);

	return pci_emul_add_capability(dev, (u_char *)&msicap, sizeof(msicap));
	assert(msix_tab_size % 4096 == 0);

static void
	assert(table_entries > 0);
	assert(table_entries <= MAX_MSIX_TABLE_ENTRIES);


	assert(dev->msix.table != NULL);
	assert(msgnum >= 1 && msgnum <= MAX_MSIX_TABLE_ENTRIES);
	assert(barnum >= 0 && barnum <= PCIR_MAX_BAR_0);
	pci_msix_table_init(dev, msgnum);
	assert(offset >= capoff);
				assert(ops != NULL);

	assert(error == 0);
	assert(error == 0);
	assert(error == 0);
				assert(ops != NULL);
				assert(ops != NULL);

	assert(bi != NULL);
	assert(bus >= 0 && bus < MAXBUSES);
	assert(bi != NULL);
	assert(bi != NULL);
	assert(bi != NULL);
	assert(ii->ii_ioapic_irq > 0);
	assert(ii->ii_pirq_pin > 0);
	assert(dev->lintr.pin > 0);
	assert(dev->lintr.pin > 0);
			assert(0);
				assert(idx >= 1);
				assert(0);
	int error;
	error = pci_emul_add_msicap(dev, PCI_EMUL_MSI_MSGS);
	assert(error == 0);

	error = pci_emul_alloc_bar(dev, 0, PCIBAR_IO, DIOSZ);
	assert(error == 0);

	error = pci_emul_alloc_bar(dev, 1, PCIBAR_MEM32, DMEMSZ);
	assert(error == 0);

	error = pci_emul_alloc_bar(dev, 2, PCIBAR_MEM32, DMEMSZ);
	assert(error == 0);

	return 0;
	assert(bi != NULL);
void	pci_populate_msicap(struct msicap *cap, int msgs, int nextptr);
	assert(offset <= PCI_REGMAX);
	assert(offset <= (PCI_REGMAX - 1) && (offset & 1) == 0);
	assert(offset <= (PCI_REGMAX - 3) && (offset & 3) == 0);
	assert(offset <= PCI_REGMAX);
	assert(offset <= (PCI_REGMAX - 1) && (offset & 1) == 0);
	assert(offset <= (PCI_REGMAX - 3) && (offset & 3) == 0);

Fixed code:
	if (addr + size > pdi->bar[bidx].addr + pdi->bar[bidx].size) {
		pr_err("%s, Out of emulated memory range\n", __func__);
		return -ESRCH;
	}
	if ((size & (size - 1)) != 0) {	/* must be a power of 2 */
		pr_err("%s: Cannot alloc invalid size %lld resource\n", __func__, size);
		return -1;
	}
static int
		return 0;

	return error;
		pr_err("%s: invalid bar type %d\n", __func__, type);
		return;
		if (idx + 1 > PCI_BARMAX) {
			pr_err("%s: invalid bar number %d for MEM64 type\n", __func__, idx);
			return -1;
		}
		pr_err("%s: invalid bar type %d\n", __func__, type);
		return -1;
int
	if (((msgnum & (msgnum - 1)) != 0) || msgnum < 1 || msgnum > 32) {
		pr_err("%s: invalid number of msi messages!\n", __func__);
		return -1;
	}

	return 0;
	return pci_populate_msicap(&msicap, msgnum, 0) ||
		pci_emul_add_capability(dev, (u_char *)&msicap, sizeof(msicap));
static int
	if (!dev->msix.table) {
		pr_err("%s: Cannot alloc memory!\n", __func__);
		return -1;
	}

	return 0;
	if (msgnum > MAX_MSIX_TABLE_ENTRIES) {
		pr_err("%s: Too many entries!\n", __func__);
		return -1;
	}
	if (pci_msix_table_init(dev, msgnum) != 0)
		return -1;
				if (!ops) {
					pr_warn("No driver for device [%s]\n", fi->fi_name);
					continue;
				}
	if (error != 0)
		goto pci_emul_init_fail;
	if (error != 0)
		goto pci_emul_init_fail;
	if (error != 0)
		goto pci_emul_init_fail;
				if (!ops) {
					pr_warn("No driver for device [%s]\n", fi->fi_name);
					continue;
				}
				if (!ops) {
					pr_warn("No driver for device [%s]\n", fi->fi_name);
					continue;
				}
	if (bi == NULL) {
		pr_err("%s: pci [%s] has wrong bus %d info!\n", __func__, dev->name, dev->bus);
		return;
	}
	if (bi == NULL) {
		pr_err("%s: pci [%s] has wrong bus %d info!\n", __func__, dev->name, dev->bus);
		return;
	}
	if (bi == NULL) {
		pr_err("%s: pci [%s] has wrong bus %d info!\n", __func__, dev->name, dev->bus);
		return;
	}
	if (dev->lintr.pin <= 0) {
		pr_warn("%s: Invalid intr pin on dev [%s]\n", __func__, dev->name);
		return;
	}
	if (dev->lintr.pin <= 0) {
		pr_warn("%s: Invalid intr pin on dev [%s]\n", __func__, dev->name);
		return;
	}
			pr_err("%s: invalid bar type %d\n", __func__, dev->bar[i].type);
			return;
				pr_err("%s: invalid bar type %d\n", __func__, dev->bar[idx].type);
				return;
	return pci_emul_add_msicap(dev, PCI_EMUL_MSI_MSGS) ||
		pci_emul_alloc_bar(dev, 0, PCIBAR_IO, DIOSZ) ||
		pci_emul_alloc_bar(dev, 1, PCIBAR_MEM32, DMEMSZ) ||
		pci_emul_alloc_bar(dev, 2, PCIBAR_MEM32, DMEMSZ);
	if (bi == NULL)
		return NULL;
#include "log.h"
int	pci_populate_msicap(struct msicap *cap, int msgs, int nextptr);
	if (offset > PCI_REGMAX) {
		pr_err("%s: out of range of PCI config space!\n", __func__);
		return;
	}
	if ((offset > PCI_REGMAX - 1) || (offset & 1) != 0) {
		pr_err("%s: out of range of PCI config space!\n", __func__);
		return;
	}
	if ((offset > PCI_REGMAX - 3) || (offset & 3) != 0) {
		pr_err("%s: out of range of PCI config space!\n", __func__);
		return;
	}
	if (offset > PCI_REGMAX) {
		pr_err("%s: out of range of PCI config space!\n", __func__);
		return 0xff;
	}
	if ((offset > PCI_REGMAX - 1) || (offset & 1) != 0) {
		pr_err("%s: out of range of PCI config space!\n", __func__);
		return 0xffff;
	}
	if ((offset > PCI_REGMAX - 3) || (offset & 3) != 0) {
		pr_err("%s: out of range of PCI config space!\n", __func__);
		return 0xffffffff;
	}
#include <stdarg.h>