--- sys/dev/beri/virtio/virtio.c.orig
+++ sys/dev/beri/virtio/virtio.c
@@ -107,12 +107,17 @@
 static inline void
 _vq_record(uint32_t offs, int i, volatile struct vring_desc *vd,
 	struct iovec *iov, int n_iov, uint16_t *flags) {
+	uint32_t len;
+	uint64_t addr;
+
 	if (i >= n_iov)
 		return;
 
-	iov[i].iov_base = paddr_map(offs, be64toh(vd->addr),
-				be32toh(vd->len));
-	iov[i].iov_len = be32toh(vd->len);
+	len = atomic_load_32(&vd->len);
+	addr = atomic_load_64(&vd->addr);
+	iov[i].iov_base = paddr_map(offs, be64toh(addr),
+				be32toh(len));
+	iov[i].iov_len = be32toh(len);
 	if (flags != NULL)
 		flags[i] = be16toh(vd->flags);
 }
--- usr.sbin/bhyve/hda_codec.c.orig
+++ usr.sbin/bhyve/hda_codec.c
@@ -521,7 +521,6 @@
 		payload = cmd_data & 0xffff;
 	}
 
-	assert(cad == hci->cad);
 	assert(hci);
 
 	hops = hci->hops;
@@ -530,7 +529,10 @@
 	sc = (struct hda_codec_softc *)hci->priv;
 	assert(sc);
 
-	assert(nid < sc->no_nodes);
+	if (cad != hci->cad || nid >= sc->no_nodes) {
+		DPRINTF("Invalid command data");
+		return (-1);
+	}
 
 	if (!hops->response) {
 		DPRINTF("The controller ops does not implement \
@@ -540,7 +542,8 @@
 
 	switch (verb) {
 	case HDA_CMD_VERB_GET_PARAMETER:
-		res = sc->get_parameters[nid][payload];
+		if (payload < HDA_CODEC_PARAMS_COUNT)
+			res = sc->get_parameters[nid][payload];
 		break;
 	case HDA_CMD_VERB_GET_CONN_LIST_ENTRY:
 		res = sc->conn_list[nid][0];
--- usr.sbin/bhyve/pci_hda.c.orig
+++ usr.sbin/bhyve/pci_hda.c
@@ -789,6 +789,11 @@
 	int err;
 
 	corb->wp = hda_get_reg_by_offset(sc, HDAC_CORBWP);
+	if (corb->wp >= corb->size) {
+		DPRINTF("Invalid HDAC_CORBWP %u >= size %u", corb->wp,
+		    corb->size);
+		return (-1);
+	}
 
 	while (corb->rp != corb->wp && corb->run) {
 		corb->rp++;
--- usr.sbin/bhyve/pci_nvme.c.orig
+++ usr.sbin/bhyve/pci_nvme.c
@@ -265,6 +265,17 @@
 	uint16_t	cid;	/* Command ID of the submitted AER */
 };
 
+/** Asynchronous Event Information - Error */
+typedef enum {
+	PCI_NVME_AEI_ERROR_INVALID_DB,
+	PCI_NVME_AEI_ERROR_INVALID_DB_VALUE,
+	PCI_NVME_AEI_ERROR_DIAG_FAILURE,
+	PCI_NVME_AEI_ERROR_PERSISTANT_ERR,
+	PCI_NVME_AEI_ERROR_TRANSIENT_ERR,
+	PCI_NVME_AEI_ERROR_FIRMWARE_LOAD_ERR,
+	PCI_NVME_AEI_ERROR_MAX,
+} pci_nvme_async_event_info_error;
+
 /** Asynchronous Event Information - Notice */
 typedef enum {
 	PCI_NVME_AEI_NOTICE_NS_ATTR_CHANGED = 0,
@@ -1402,7 +1413,7 @@
 	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:
@@ -1414,7 +1425,7 @@
 
 		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:
@@ -1437,7 +1448,7 @@
 
 		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:
@@ -1449,7 +1460,7 @@
 
 		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:
@@ -1461,7 +1472,7 @@
 
 		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;
@@ -2789,6 +2800,38 @@
 	pthread_mutex_unlock(&sq->mtx);
 }
 
+/*
+ * Check for invalid doorbell write values
+ * See NVM Express Base Specification, revision 2.0
+ * "Asynchronous Event Information - Error Status" for details
+ */
+static bool
+pci_nvme_sq_doorbell_valid(struct nvme_submission_queue *sq, uint64_t value)
+{
+	uint64_t	capacity;
+
+	/*
+	 * Queue empty : head == tail
+	 * Queue full  : head is one more than tail accounting for wrap
+	 * Therefore, can never have more than (size - 1) entries
+	 */
+	if (sq->head == sq->tail)
+		capacity = sq->size - 1;
+	else if (sq->head > sq->tail)
+		capacity = sq->size - (sq->head - sq->tail) - 1;
+	else
+		capacity = sq->tail - sq->head - 1;
+
+	if ((value == sq->tail) ||	/* same as previous */
+	    (value > capacity))	{	/* exceeds queue capacity */
+		EPRINTLN("%s: SQ size=%u head=%u tail=%u capacity=%lu value=%lu",
+		    __func__, sq->size, sq->head, sq->tail, capacity, value);
+		return false;
+	}
+
+	return true;
+}
+
 static void
 pci_nvme_handle_doorbell(struct pci_nvme_softc* sc,
 	uint64_t idx, int is_sq, uint64_t value)
@@ -2801,22 +2844,34 @@
 			WPRINTF("%s queue index %lu overflow from "
 			         "guest (max %u)",
 			         __func__, idx, sc->num_squeues);
+			pci_nvme_aen_post(sc, PCI_NVME_AE_TYPE_ERROR,
+			    PCI_NVME_AEI_ERROR_INVALID_DB);
+			return;
+		}
+
+		if (sc->submit_queues[idx].qbase == NULL) {
+			WPRINTF("%s write to SQ %lu before created", __func__,
+			    idx);
+			pci_nvme_aen_post(sc, PCI_NVME_AE_TYPE_ERROR,
+			    PCI_NVME_AEI_ERROR_INVALID_DB);
+			return;
+		}
+
+		if (!pci_nvme_sq_doorbell_valid(&sc->submit_queues[idx], value)) {
+			EPRINTLN("%s write to SQ %lu of %lu invalid", __func__,
+			    idx, value);
+			pci_nvme_aen_post(sc, PCI_NVME_AE_TYPE_ERROR,
+			    PCI_NVME_AEI_ERROR_INVALID_DB_VALUE);
 			return;
 		}
 
 		atomic_store_short(&sc->submit_queues[idx].tail,
 		                   (uint16_t)value);
 
-		if (idx == 0) {
+		if (idx == 0)
 			pci_nvme_handle_admin_cmd(sc, value);
-		} else {
+		else {
 			/* submission queue; handle new entries in SQ */
-			if (idx > sc->num_squeues) {
-				WPRINTF("%s SQ index %lu overflow from "
-				         "guest (max %u)",
-				         __func__, idx, sc->num_squeues);
-				return;
-			}
 			pci_nvme_handle_io_cmd(sc, (uint16_t)idx);
 		}
 	} else {
@@ -2824,6 +2879,16 @@
 			WPRINTF("%s queue index %lu overflow from "
 			         "guest (max %u)",
 			         __func__, idx, sc->num_cqueues);
+			pci_nvme_aen_post(sc, PCI_NVME_AE_TYPE_ERROR,
+			    PCI_NVME_AEI_ERROR_INVALID_DB);
+			return;
+		}
+
+		if (sc->compl_queues[idx].qbase == NULL) {
+			WPRINTF("%s write to CQ %lu before created", __func__,
+			    idx);
+			pci_nvme_aen_post(sc, PCI_NVME_AE_TYPE_ERROR,
+			    PCI_NVME_AEI_ERROR_INVALID_DB);
 			return;
 		}
 
--- usr.sbin/bhyve/virtio.c.orig
+++ usr.sbin/bhyve/virtio.c
@@ -217,10 +217,15 @@
 _vq_record(int i, struct vring_desc *vd, struct vmctx *ctx, struct iovec *iov,
     int n_iov, struct vi_req *reqp)
 {
+	uint32_t len;
+	uint64_t addr;
+
 	if (i >= n_iov)
 		return;
-	iov[i].iov_base = paddr_guest2host(ctx, vd->addr, vd->len);
-	iov[i].iov_len = vd->len;
+	len = atomic_load_32(&vd->len);
+	addr = atomic_load_64(&vd->addr);
+	iov[i].iov_len = len;
+	iov[i].iov_base = paddr_guest2host(ctx, addr, len);
 	if ((vd->flags & VRING_DESC_F_WRITE) == 0)
 		reqp->readable++;
 	else
