CVE-2019-18844: Reachable Assertion (CWE-617)
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.
CWE description: 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.
CVSS v3 base score: 7.5
Published: 2019-11-13T20:15Z
Repository: https://github.com/projectacrn/acrn-hypervisor
Language: C
Files changed: devicemodel/hw/pci/core.c, devicemodel/include/pci_core.h, devicemodel/include/types.h
Commit date: 2019-06-20 11:21:51 +0800
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>

Diff: diff --git a/devicemodel/hw/pci/core.c b/devicemodel/hw/pci/core.c
index a29b60c2..81d7b16e 100644
--- a/devicemodel/hw/pci/core.c
+++ b/devicemodel/hw/pci/core.c
@@ -424,15 +424,14 @@ pci_emul_mem_handler(struct vmctx *ctx, int vcpu, int dir, uint64_t addr,
 	struct pci_vdev *pdi = arg1;
 	struct pci_vdev_ops *ops = pdi->dev_ops;
 	uint64_t offset;
 	int bidx = (int) arg2;
 
-	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);
+	if (addr + size > pdi->bar[bidx].addr + pdi->bar[bidx].size) {
+		pr_err("%s, Out of emulated memory range\n", __func__);
+		return -ESRCH;
+	}
 
 	offset = addr - pdi->bar[bidx].addr;
 
 	if (dir == MEM_F_WRITE) {
 		if (size == 8) {
@@ -471,11 +470,14 @@ static int
 pci_emul_alloc_resource(uint64_t *baseptr, uint64_t limit, uint64_t size,
 			uint64_t *addr)
 {
 	uint64_t base;
 
-	assert((size & (size - 1)) == 0);	/* must be a power of 2 */
+	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;
+	}
 
 	base = roundup2(*baseptr, size);
 
 	if (base + size <= limit) {
 		*addr = base;
@@ -494,11 +496,11 @@ pci_emul_alloc_bar(struct pci_vdev *pdi, int idx, enum pcibar_type type,
 
 /*
  * Register (or unregister) the MMIO or I/O region associated with the BAR
  * register 'idx' of an emulated pci device.
  */
-static void
+static int
 modify_bar_registration(struct pci_vdev *dev, int idx, int registration)
 {
 	int error;
 	struct inout_port iop;
 	struct mem_range mr;
@@ -513,11 +515,11 @@ modify_bar_registration(struct pci_vdev *dev, int idx, int registration)
 		 * obsoleted with the migration of using OVMF to do bar
 		 * addressing and generate ACPI PCI resource from using
 		 * acrn-dm.
 		 */
 		printf("modify_bar_registration: bypass for pci-gvt\n");
-		return;
+		return 0;
 	}
 	switch (dev->bar[idx].type) {
 	case PCIBAR_IO:
 		bzero(&iop, sizeof(struct inout_port));
 		iop.name = dev->name;
@@ -548,11 +550,12 @@ modify_bar_registration(struct pci_vdev *dev, int idx, int registration)
 		break;
 	default:
 		error = EINVAL;
 		break;
 	}
-	assert(error == 0);
+
+	return error;
 }
 
 static void
 unregister_bar(struct pci_vdev *dev, int idx)
 {
@@ -622,11 +625,12 @@ update_bar_address(struct vmctx *ctx, struct pci_vdev *dev, uint64_t addr,
 	case PCIBAR_MEMHI64:
 		dev->bar[idx].addr &= 0xffffffff;
 		dev->bar[idx].addr |= addr;
 		break;
 	default:
-		assert(0);
+		pr_err("%s: invalid bar type %d\n", __func__, type);
+		return;
 	}
 
 	if (decode)
 		register_bar(dev, idx);
 
@@ -640,12 +644,10 @@ pci_emul_alloc_pbar(struct pci_vdev *pdi, int idx, uint64_t hostbase,
 		    enum pcibar_type type, uint64_t size)
 {
 	int error;
 	uint64_t *baseptr, limit, addr, mask, lobits, bar;
 
-	assert(idx >= 0 && idx <= PCI_BARMAX);
-
 	if ((size & (size - 1)) != 0)
 		size = 1UL << flsl(size);	/* round up to a power of 2 */
 
 	/* Enforce minimum BAR sizes required by the PCI standard */
 	if (type == PCIBAR_IO) {
@@ -666,10 +668,14 @@ pci_emul_alloc_pbar(struct pci_vdev *pdi, int idx, uint64_t hostbase,
 		limit = PCI_EMUL_IOLIMIT;
 		mask = PCIM_BAR_IO_BASE;
 		lobits = PCIM_BAR_IO_SPACE;
 		break;
 	case PCIBAR_MEM64:
+		if (idx + 1 > PCI_BARMAX) {
+			pr_err("%s: invalid bar number %d for MEM64 type\n", __func__, idx);
+			return -1;
+		}
 		/*
 		 * FIXME
 		 * Some drivers do not work well if the 64-bit BAR is allocated
 		 * above 4GB. Allow for this by allocating small requests under
 		 * 4GB unless then allocation size is larger than some arbitrary
@@ -701,12 +707,12 @@ pci_emul_alloc_pbar(struct pci_vdev *pdi, int idx, uint64_t hostbase,
 		limit = PCI_EMUL_MEMLIMIT32;
 		mask = PCIM_BAR_MEM_BASE;
 		lobits = PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_32;
 		break;
 	default:
-		printf("%s: invalid bar type %d\n", __func__, type);
-		assert(0);
+		pr_err("%s: invalid bar type %d\n", __func__, type);
+		return -1;
 	}
 
 	if (baseptr != NULL) {
 		error = pci_emul_alloc_resource(baseptr, limit, size, &addr);
 		if (error != 0)
@@ -720,11 +726,10 @@ pci_emul_alloc_pbar(struct pci_vdev *pdi, int idx, uint64_t hostbase,
 	/* Initialize the BAR register in config space */
 	bar = (addr & mask) | lobits;
 	pci_set_cfgdata32(pdi, PCIR_BAR(idx), bar);
 
 	if (type == PCIBAR_MEM64) {
-		assert(idx + 1 <= PCI_BARMAX);
 		pdi->bar[idx + 1].type = PCIBAR_MEMHI64;
 		pci_set_cfgdata32(pdi, PCIR_BAR(idx + 1), bar >> 32);
 	}
 
 	register_bar(pdi, idx);
@@ -763,12 +768,10 @@ int
 pci_emul_add_capability(struct pci_vdev *dev, u_char *capdata, int caplen)
 {
 	int i, capoff, reallen;
 	uint16_t sts;
 
-	assert(caplen > 0);
-
 	reallen = roundup2(caplen, 4);		/* dword aligned */
 
 	sts = pci_get_cfgdata16(dev, PCIR_STATUS);
 	if ((sts & PCIM_STATUS_CAPPRESENT) == 0)
 		capoff = CAP_START_OFFSET;
@@ -911,42 +914,44 @@ pci_emul_deinit(struct vmctx *ctx, struct pci_vdev_ops *ops, int bus, int slot,
 		pci_emul_free_msixcap(fi->fi_devi);
 		free(fi->fi_devi);
 	}
 }
 
-void
+int
 pci_populate_msicap(struct msicap *msicap, int msgnum, int nextptr)
 {
 	int mmc;
 
 	/* Number of msi messages must be a power of 2 between 1 and 32 */
-	assert((msgnum & (msgnum - 1)) == 0 && msgnum >= 1 && msgnum <= 32);
+	if (((msgnum & (msgnum - 1)) != 0) || msgnum < 1 || msgnum > 32) {
+		pr_err("%s: invalid number of msi messages!\n", __func__);
+		return -1;
+	}
 	mmc = ffs(msgnum) - 1;
 
 	bzero(msicap, sizeof(struct msicap));
 	msicap->capid = PCIY_MSI;
 	msicap->nextptr = nextptr;
 	msicap->msgctrl = PCIM_MSICTRL_64BIT | (mmc << 1);
+
+	return 0;
 }
 
 int
 pci_emul_add_msicap(struct pci_vdev *dev, int msgnum)
 {
 	struct msicap msicap;
 
-	pci_populate_msicap(&msicap, msgnum, 0);
-
-	return pci_emul_add_capability(dev, (u_char *)&msicap, sizeof(msicap));
+	return pci_populate_msicap(&msicap, msgnum, 0) ||
+		pci_emul_add_capability(dev, (u_char *)&msicap, sizeof(msicap));
 }
 
 static void
 pci_populate_msixcap(struct msixcap *msixcap, int msgnum, int barnum,
 		     uint32_t msix_tab_size)
 {
 
-	assert(msix_tab_size % 4096 == 0);
-
 	bzero(msixcap, sizeof(struct msixcap));
 	msixcap->capid = PCIY_MSIX;
 
 	/*
 	 * Message Control Register, all fields set to
@@ -962,36 +967,39 @@ pci_populate_msixcap(struct msixcap *msixcap, int msgnum, int barnum,
 	 */
 	msixcap->table_info = barnum & PCIM_MSIX_BIR_MASK;
 	msixcap->pba_info = msix_tab_size | (barnum & PCIM_MSIX_BIR_MASK);
 }
 
-static void
+static int
 pci_msix_table_init(struct pci_vdev *dev, int table_entries)
 {
 	int i, table_size;
 
-	assert(table_entries > 0);
-	assert(table_entries <= MAX_MSIX_TABLE_ENTRIES);
-
 	table_size = table_entries * MSIX_TABLE_ENTRY_SIZE;
 	dev->msix.table = calloc(1, table_size);
-
-	assert(dev->msix.table != NULL);
+	if (!dev->msix.table) {
+		pr_err("%s: Cannot alloc memory!\n", __func__);
+		return -1;
+	}
 
 	/* set mask bit of vector control register */
 	for (i = 0; i < table_entries; i++)
 		dev->msix.table[i].vector_control |= PCIM_MSIX_VCTRL_MASK;
+
+	return 0;
 }
 
 int
 pci_emul_add_msixcap(struct pci_vdev *dev, int msgnum, int barnum)
 {
 	uint32_t tab_size;
 	struct msixcap msixcap;
 
-	assert(msgnum >= 1 && msgnum <= MAX_MSIX_TABLE_ENTRIES);
-	assert(barnum >= 0 && barnum <= PCIR_MAX_BAR_0);
+	if (msgnum > MAX_MSIX_TABLE_ENTRIES) {
+		pr_err("%s: Too many entries!\n", __func__);
+		return -1;
+	}
 
 	tab_size = msgnum * MSIX_TABLE_ENTRY_SIZE;
 
 	/* Align table size to nearest 4K */
 	tab_size = roundup2(tab_size, 4096);
@@ -1001,11 +1009,12 @@ pci_emul_add_msixcap(struct pci_vdev *dev, int msgnum, int barnum)
 	dev->msix.table_offset = 0;
 	dev->msix.table_count = msgnum;
 	dev->msix.pba_offset = tab_size;
 	dev->msix.pba_size = PBA_SIZE(msgnum);
 
-	pci_msix_table_init(dev, msgnum);
+	if (pci_msix_table_init(dev, msgnum) != 0)
+		return -1;
 
 	pci_populate_msixcap(&msixcap, msgnum, barnum, tab_size);
 
 	/* allocate memory for MSI-X Table and PBA */
 	pci_emul_alloc_bar(dev, barnum, PCIBAR_MEM32,
@@ -1141,11 +1150,10 @@ pci_emul_capwrite(struct pci_vdev *dev, int offset, int bytes, uint32_t val)
 		if (offset >= capoff && offset < nextoff)
 			break;
 
 		capoff = nextoff;
 	}
-	assert(offset >= capoff);
 
 	/*
 	 * Capability ID and Next Capability Pointer are readonly.
 	 * However, some o/s's do 4-byte writes that include these.
 	 * For this case, trim the write back to 2 bytes and adjust
@@ -1260,12 +1268,14 @@ init_pci(struct vmctx *ctx)
 			for (func = 0; func < MAXFUNCS; func++) {
 				fi = &si->si_funcs[func];
 				if (fi->fi_name == NULL)
 					continue;
 				ops = pci_emul_finddev(fi->fi_name);
-				assert(ops != NULL);
-
+				if (!ops) {
+					pr_warn("No driver for device [%s]\n", fi->fi_name);
+					continue;
+				}
 				pr_notice("pci init %s\r\n", fi->fi_name);
 				error = pci_emul_init(ctx, ops, bus, slot,
 				    func, fi);
 				if (error) {
 					pr_err("pci %s init failed\n", fi->fi_name);
@@ -1346,31 +1356,34 @@ init_pci(struct vmctx *ctx)
 	mr.flags = MEM_F_RW;
 	mr.base = lowmem;
 	mr.size = (4ULL * 1024 * 1024 * 1024) - lowmem;
 	mr.handler = pci_emul_fallback_handler;
 	error = register_mem_fallback(&mr);
-	assert(error == 0);
+	if (error != 0)
+		goto pci_emul_init_fail;
 
 	/* ditto for the 64-bit PCI host aperture */
 	bzero(&mr, sizeof(struct mem_range));
 	mr.name = "PCI hole (64-bit)";
 	mr.flags = MEM_F_RW;
 	mr.base = PCI_EMUL_MEMBASE64;
 	mr.size = PCI_EMUL_MEMLIMIT64 - PCI_EMUL_MEMBASE64;
 	mr.handler = pci_emul_fallback_handler;
 	error = register_mem_fallback(&mr);
-	assert(error == 0);
+	if (error != 0)
+		goto pci_emul_init_fail;
 
 	/* PCI extended config space */
 	bzero(&mr, sizeof(struct mem_range));
 	mr.name = "PCI ECFG";
 	mr.flags = MEM_F_RW;
 	mr.base = PCI_EMUL_ECFG_BASE;
 	mr.size = PCI_EMUL_ECFG_SIZE;
 	mr.handler = pci_emul_ecfg_handler;
 	error = register_mem(&mr);
-	assert(error == 0);
+	if (error != 0)
+		goto pci_emul_init_fail;
 
 	return 0;
 
 pci_emul_init_fail:
 	for (bus = 0; bus < MAXBUSES && success_cnt > 0; bus++) {
@@ -1384,11 +1397,14 @@ pci_emul_init_fail:
 				if (fi->fi_name == NULL)
 					continue;
 				if (success_cnt-- <= 0)
 					break;
 				ops = pci_emul_finddev(fi->fi_name);
-				assert(ops != NULL);
+				if (!ops) {
+					pr_warn("No driver for device [%s]\n", fi->fi_name);
+					continue;
+				}
 				pci_emul_deinit(ctx, ops, bus, slot,
 				    func, fi);
 			}
 		}
 	}
@@ -1439,12 +1455,14 @@ deinit_pci(struct vmctx *ctx)
 			for (func = 0; func < MAXFUNCS; func++) {
 				fi = &si->si_funcs[func];
 				if (fi->fi_name == NULL)
 					continue;
 				ops = pci_emul_finddev(fi->fi_name);
-				assert(ops != NULL);
-
+				if (!ops) {
+					pr_warn("No driver for device [%s]\n", fi->fi_name);
+					continue;
+				}
 				pr_notice("pci deinit %s\n", fi->fi_name);
 				pci_emul_deinit(ctx, ops, bus, slot,
 				    func, fi);
 			}
 		}
@@ -1557,11 +1575,10 @@ pci_bus_write_dsdt(int bus)
 		if (bi == NULL) {
 			dsdt_line("    })");
 			goto done;
 		}
 	}
-	assert(bi != NULL);
 
 	/* i/o window */
 	dsdt_line("      WordIO (ResourceProducer, MinFixed, MaxFixed, "
 	    "PosDecode, EntireRange,");
 	dsdt_line("        0x0000,             // Granularity");
@@ -1661,11 +1678,10 @@ pci_write_dsdt(void)
 }
 
 int
 pci_bus_configured(int bus)
 {
-	assert(bus >= 0 && bus < MAXBUSES);
 	return (pci_businfo[bus] != NULL);
 }
 
 int
 pci_msi_enabled(struct pci_vdev *dev)
@@ -1750,11 +1766,14 @@ pci_lintr_request(struct pci_vdev *dev)
 	struct businfo *bi;
 	struct slotinfo *si;
 	int bestpin, bestcount, pin;
 
 	bi = pci_businfo[dev->bus];
-	assert(bi != NULL);
+	if (bi == NULL) {
+		pr_err("%s: pci [%s] has wrong bus %d info!\n", __func__, dev->name, dev->bus);
+		return;
+	}
 
 	/*
 	 * Just allocate a pin from our slot.  The pin will be
 	 * assigned IRQs later when interrupts are routed.
 	 */
@@ -1779,11 +1798,14 @@ pci_lintr_release(struct pci_vdev *dev)
 	struct businfo *bi;
 	struct slotinfo *si;
 	int pin;
 
 	bi = pci_businfo[dev->bus];
-	assert(bi != NULL);
+	if (bi == NULL) {
+		pr_err("%s: pci [%s] has wrong bus %d info!\n", __func__, dev->name, dev->bus);
+		return;
+	}
 
 	si = &bi->slotinfo[dev->slot];
 
 	for (pin = 1; pin < 4; pin++) {
 		si->si_intpins[pin].ii_count = 0;
@@ -1800,28 +1822,29 @@ pci_lintr_route(struct pci_vdev *dev)
 
 	if (dev->lintr.pin == 0)
 		return;
 
 	bi = pci_businfo[dev->bus];
-	assert(bi != NULL);
+	if (bi == NULL) {
+		pr_err("%s: pci [%s] has wrong bus %d info!\n", __func__, dev->name, dev->bus);
+		return;
+	}
 	ii = &bi->slotinfo[dev->slot].si_intpins[dev->lintr.pin - 1];
 
 	/*
 	 * Attempt to allocate an I/O APIC pin for this intpin if one
 	 * is not yet assigned.
 	 */
 	if (ii->ii_ioapic_irq == 0)
 		ii->ii_ioapic_irq = ioapic_pci_alloc_irq(dev);
-	assert(ii->ii_ioapic_irq > 0);
 
 	/*
 	 * Attempt to allocate a PIRQ pin for this intpin if one is
 	 * not yet assigned.
 	 */
 	if (ii->ii_pirq_pin == 0)
 		ii->ii_pirq_pin = pirq_alloc_pin(dev);
-	assert(ii->ii_pirq_pin > 0);
 
 	dev->lintr.ioapic_irq = ii->ii_ioapic_irq;
 	dev->lintr.pirq_pin = ii->ii_pirq_pin;
 	pci_set_cfgdata8(dev, PCIR_INTLINE, pirq_irq(ii->ii_pirq_pin));
 }
@@ -1834,11 +1857,14 @@ pci_lintr_route(struct pci_vdev *dev)
  * @return None
  */
 void
 pci_lintr_assert(struct pci_vdev *dev)
 {
-	assert(dev->lintr.pin > 0);
+	if (dev->lintr.pin <= 0) {
+		pr_warn("%s: Invalid intr pin on dev [%s]\n", __func__, dev->name);
+		return;
+	}
 
 	pthread_mutex_lock(&dev->lintr.lock);
 	if (dev->lintr.state == IDLE) {
 		if (pci_lintr_permitted(dev)) {
 			dev->lintr.state = ASSERTED;
@@ -1857,11 +1883,14 @@ pci_lintr_assert(struct pci_vdev *dev)
  * @return None
  */
 void
 pci_lintr_deassert(struct pci_vdev *dev)
 {
-	assert(dev->lintr.pin > 0);
+	if (dev->lintr.pin <= 0) {
+		pr_warn("%s: Invalid intr pin on dev [%s]\n", __func__, dev->name);
+		return;
+	}
 
 	pthread_mutex_lock(&dev->lintr.lock);
 	if (dev->lintr.state == ASSERTED) {
 		dev->lintr.state = IDLE;
 		pci_irq_deassert(dev);
@@ -2029,11 +2058,12 @@ pci_emul_cmdsts_write(struct pci_vdev *dev, int coff, uint32_t new, int bytes)
 				else
 					unregister_bar(dev, i);
 			}
 			break;
 		default:
-			assert(0);
+			pr_err("%s: invalid bar type %d\n", __func__, dev->bar[i].type);
+			return;
 		}
 	}
 
 	/*
 	 * If INTx has been unmasked and is pending, assert the
@@ -2194,22 +2224,22 @@ pci_cfgrw(struct vmctx *ctx, int vcpu, int in, int bus, int slot, int func,
 							   PCIBAR_MEM64,
 							   ignore_reg_unreg);
 				}
 				break;
 			case PCIBAR_MEMHI64:
-				assert(idx >= 1);
 				mask = ~(dev->bar[idx - 1].size - 1);
 				addr = ((uint64_t)*eax << 32) & mask;
 				bar = addr >> 32;
 				if (bar != dev->bar[idx - 1].addr >> 32) {
 					update_bar_address(ctx, dev, addr, idx - 1,
 							   PCIBAR_MEMHI64,
 							   ignore_reg_unreg);
 				}
 				break;
 			default:
-				assert(0);
+				pr_err("%s: invalid bar type %d\n", __func__, dev->bar[idx].type);
+				return;
 			}
 			pci_set_cfgdata32(dev, coff, bar);
 
 		} else if (coff == PCIR_BIOS) {
 			/* ignore ROM BAR length request */
@@ -2305,34 +2335,24 @@ struct pci_emul_dummy {
 #define	PCI_EMUL_MSIX_MSGS	16
 
 static int
 pci_emul_dinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
 {
-	int error;
 	struct pci_emul_dummy *dummy;
 
 	dummy = calloc(1, sizeof(struct pci_emul_dummy));
 
 	dev->arg = dummy;
 
 	pci_set_cfgdata16(dev, PCIR_DEVICE, 0x0001);
 	pci_set_cfgdata16(dev, PCIR_VENDOR, 0x10DD);
 	pci_set_cfgdata8(dev, PCIR_CLASS, 0x02);
 
-	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;
+	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);
 }
 
 static void
 pci_emul_diow(struct vmctx *ctx, int vcpu, struct pci_vdev *dev, int baridx,
 	      uint64_t offset, int size, uint64_t value)
@@ -2465,11 +2485,12 @@ pci_get_vdev_info(int slot)
 	struct businfo *bi;
 	struct slotinfo *si;
 	struct pci_vdev *dev = NULL;
 
 	bi = pci_businfo[0];
-	assert(bi != NULL);
+	if (bi == NULL)
+		return NULL;
 
 	si = &bi->slotinfo[slot];
 	if (si != NULL)
 		dev = si->si_funcs[0].fi_devi;
 	else
diff --git a/devicemodel/include/pci_core.h b/devicemodel/include/pci_core.h
index b8ab5c32..ab066e17 100644
--- a/devicemodel/include/pci_core.h
+++ b/devicemodel/include/pci_core.h
@@ -33,10 +33,11 @@
 
 #include <assert.h>
 #include <stdbool.h>
 #include "types.h"
 #include "pcireg.h"
+#include "log.h"
 
 #define	PCI_BARMAX	PCIR_MAX_BAR_0	/* BAR registers in a Type 0 header */
 #define	PCI_BDF(b, d, f) (((b & 0xFF) << 8) | ((d & 0x1F) << 3) | ((f & 0x7)))
 
 #define	PCI_EMUL_ECFG_BASE	0xE0000000UL	/* 3.5GB */
@@ -309,11 +310,11 @@ int	pci_msi_enabled(struct pci_vdev *pi);
 int	pci_msix_enabled(struct pci_vdev *pi);
 int	pci_msix_table_bar(struct pci_vdev *pi);
 int	pci_msix_pba_bar(struct pci_vdev *pi);
 int	pci_msi_maxmsgnum(struct pci_vdev *pi);
 int	pci_parse_slot(char *opt);
-void	pci_populate_msicap(struct msicap *cap, int msgs, int nextptr);
+int	pci_populate_msicap(struct msicap *cap, int msgs, int nextptr);
 int	pci_emul_add_msixcap(struct pci_vdev *pi, int msgnum, int barnum);
 int	pci_emul_msix_twrite(struct pci_vdev *pi, uint64_t offset, int size,
 			     uint64_t value);
 uint64_t pci_emul_msix_tread(struct pci_vdev *pi, uint64_t offset, int size);
 int	pci_count_lintr(int bus);
@@ -341,11 +342,14 @@ struct pci_vdev *pci_get_vdev_info(int slot);
  * @return None
  */
 static inline void
 pci_set_cfgdata8(struct pci_vdev *dev, int offset, uint8_t val)
 {
-	assert(offset <= PCI_REGMAX);
+	if (offset > PCI_REGMAX) {
+		pr_err("%s: out of range of PCI config space!\n", __func__);
+		return;
+	}
 	*(uint8_t *)(dev->cfgdata + offset) = val;
 }
 
 /**
  * @brief Set virtual PCI device's configuration space in 2 bytes width
@@ -357,11 +361,14 @@ pci_set_cfgdata8(struct pci_vdev *dev, int offset, uint8_t val)
  * @return None
  */
 static inline void
 pci_set_cfgdata16(struct pci_vdev *dev, int offset, uint16_t val)
 {
-	assert(offset <= (PCI_REGMAX - 1) && (offset & 1) == 0);
+	if ((offset > PCI_REGMAX - 1) || (offset & 1) != 0) {
+		pr_err("%s: out of range of PCI config space!\n", __func__);
+		return;
+	}
 	*(uint16_t *)(dev->cfgdata + offset) = val;
 }
 
 /**
  * @brief Set virtual PCI device's configuration space in 4 bytes width
@@ -373,11 +380,14 @@ pci_set_cfgdata16(struct pci_vdev *dev, int offset, uint16_t val)
  * @return None
  */
 static inline void
 pci_set_cfgdata32(struct pci_vdev *dev, int offset, uint32_t val)
 {
-	assert(offset <= (PCI_REGMAX - 3) && (offset & 3) == 0);
+	if ((offset > PCI_REGMAX - 3) || (offset & 3) != 0) {
+		pr_err("%s: out of range of PCI config space!\n", __func__);
+		return;
+	}
 	*(uint32_t *)(dev->cfgdata + offset) = val;
 }
 
 /**
  * @brief Get virtual PCI device's configuration space in 1 byte width
@@ -388,11 +398,14 @@ pci_set_cfgdata32(struct pci_vdev *dev, int offset, uint32_t val)
  * @return The configuration value in 1 byte.
  */
 static inline uint8_t
 pci_get_cfgdata8(struct pci_vdev *dev, int offset)
 {
-	assert(offset <= PCI_REGMAX);
+	if (offset > PCI_REGMAX) {
+		pr_err("%s: out of range of PCI config space!\n", __func__);
+		return 0xff;
+	}
 	return (*(uint8_t *)(dev->cfgdata + offset));
 }
 
 /**
  * @brief Get virtual PCI device's configuration space in 2 byte width
@@ -403,11 +416,14 @@ pci_get_cfgdata8(struct pci_vdev *dev, int offset)
  * @return The configuration value in 2 bytes.
  */
 static inline uint16_t
 pci_get_cfgdata16(struct pci_vdev *dev, int offset)
 {
-	assert(offset <= (PCI_REGMAX - 1) && (offset & 1) == 0);
+	if ((offset > PCI_REGMAX - 1) || (offset & 1) != 0) {
+		pr_err("%s: out of range of PCI config space!\n", __func__);
+		return 0xffff;
+	}
 	return (*(uint16_t *)(dev->cfgdata + offset));
 }
 
 /**
  * @brief Get virtual PCI device's configuration space in 4 byte width
@@ -418,10 +434,13 @@ pci_get_cfgdata16(struct pci_vdev *dev, int offset)
  * @return The configuration value in 4 bytes.
  */
 static inline uint32_t
 pci_get_cfgdata32(struct pci_vdev *dev, int offset)
 {
-	assert(offset <= (PCI_REGMAX - 3) && (offset & 3) == 0);
+	if ((offset > PCI_REGMAX - 3) || (offset & 3) != 0) {
+		pr_err("%s: out of range of PCI config space!\n", __func__);
+		return 0xffffffff;
+	}
 	return (*(uint32_t *)(dev->cfgdata + offset));
 }
 
 #endif /* _PCI_CORE_H_ */
diff --git a/devicemodel/include/types.h b/devicemodel/include/types.h
index d4850e16..dce9e2b7 100644
--- a/devicemodel/include/types.h
+++ b/devicemodel/include/types.h
@@ -1,10 +1,11 @@
 #ifndef _TYPES_H_
 #define _TYPES_H_
 
 #include "macros.h"
 #include <stdint.h>
+#include <stdarg.h>
 #include <sched.h>
 #include <sys/types.h>
 
 #define MAXCOMLEN   19      /* max command name remembered */
 #define MAXINTERP   PATH_MAX    /* max interpreter file name length */

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>