untrusted comment: verify with openbsd-78-base.pub RWS3/nvFmk4SWf/vvHn+K/dnvOwg2YOUDfE08yD7tMGip1QHrWQYQ1FJGUAoXQQcaEKyCFtv9Huyut3nlJJb+irL9E4W623WkQo= OpenBSD 7.8 errata 039, June 2, 2026: In vmd(8), fix a variety of crashing bugs. Apply by doing: signify -Vep /etc/signify/openbsd-78-base.pub -x 039_vmd.patch.sig \ -m - | (cd /usr/src && patch -p0) And then rebuild and install vmd: cd /usr/src/usr.sbin/vmd make obj make make install Index: usr.sbin/vmd/vioblk.c =================================================================== RCS file: /cvs/src/usr.sbin/vmd/vioblk.c,v diff -u -p -r1.24 vioblk.c --- usr.sbin/vmd/vioblk.c 2 Aug 2025 15:16:18 -0000 1.24 +++ usr.sbin/vmd/vioblk.c 29 May 2026 17:11:11 -0000 @@ -266,7 +266,7 @@ vioblk_notifyq(struct virtio_dev *dev, u struct vioblk_dev *vioblk = &dev->vioblk; /* Invalid queue? */ - if (vq_idx > dev->num_queues) + if (vq_idx >= dev->num_queues) return (0); vq_info = &dev->vq[vq_idx]; @@ -283,6 +283,11 @@ vioblk_notifyq(struct virtio_dev *dev, u while (idx != avail->idx) { /* Retrieve Command descriptor. */ cmd_desc_idx = avail->ring[idx & vq_info->mask]; + if (cmd_desc_idx >= vq_info->qs) { + log_warnx("%s: invalid head descriptor index", + __func__); + goto reset; + } desc = &table[cmd_desc_idx]; cmd_len = desc->len; Index: usr.sbin/vmd/vioscsi.c =================================================================== RCS file: /cvs/src/usr.sbin/vmd/vioscsi.c,v diff -u -p -r1.26 vioscsi.c --- usr.sbin/vmd/vioscsi.c 2 Aug 2025 15:16:18 -0000 1.26 +++ usr.sbin/vmd/vioscsi.c 29 May 2026 17:11:12 -0000 @@ -1149,6 +1149,11 @@ vioscsi_handle_read_10(struct virtio_dev __func__, acct->resp_desc->addr, acct->resp_desc->len, acct->resp_idx, acct->req_idx, acct->idx); + if (acct->resp_desc->len == 0) { + log_warnx("%s: zero-length read_buf descriptor", __func__); + goto free_read_10; + } + /* Check we don't read beyond read_buf boundaries. */ if (acct->resp_desc->len > info->len - chunk_offset) { log_warnx("%s: descriptor length beyond read_buf len", @@ -1164,7 +1169,7 @@ vioscsi_handle_read_10(struct virtio_dev acct->resp_desc->addr); goto free_read_10; } - chunk_offset += acct->resp_desc->len; + chunk_offset += chunk_len; } while (chunk_offset < info->len); ret = 1; @@ -1840,7 +1845,17 @@ vioscsi_notifyq(struct virtio_dev *dev, struct virtio_vq_acct acct; struct virtio_vq_info *vq_info; + if (vq_idx >= dev->num_queues) { + log_warnx("%s: invalid virtqueue index %u", __func__, vq_idx); + return (0); + } + vq_info = &dev->vq[vq_idx]; + if (!vq_info->vq_enabled) { + log_warnx("%s: virtqueue not enabled", __func__); + return (0); + } + vr = vq_info->q_hva; if (vr == NULL) fatalx("%s: null vring", __func__); Index: usr.sbin/vmd/virtio.c =================================================================== RCS file: /cvs/src/usr.sbin/vmd/virtio.c,v diff -u -p -r1.127 virtio.c --- usr.sbin/vmd/virtio.c 8 Aug 2025 13:36:04 -0000 1.127 +++ usr.sbin/vmd/virtio.c 29 May 2026 17:11:12 -0000 @@ -197,6 +197,7 @@ virtio_update_qa(struct virtio_dev *dev) { struct virtio_vq_info *vq_info = NULL; void *hva = NULL; + uint64_t availoff, usedoff, availsz, usedsz; if (dev->driver_feature & VIRTIO_F_VERSION_1) { if (dev->pci_cfg.queue_select >= dev->num_queues) { @@ -213,11 +214,41 @@ virtio_update_qa(struct virtio_dev *dev) vq_info->qs = dev->pci_cfg.queue_size; vq_info->mask = vq_info->qs - 1; + /* + * Require the available (driver) and used (device) area to be + * similar to Virtio 0.9 but support Virtio 1.x alignment. + */ + if (dev->pci_cfg.queue_avail < dev->pci_cfg.queue_desc || + dev->pci_cfg.queue_used < dev->pci_cfg.queue_desc) { + vq_info->vq_enabled = 0; + return; + } + + availoff = dev->pci_cfg.queue_avail - dev->pci_cfg.queue_desc; + usedoff = dev->pci_cfg.queue_used - dev->pci_cfg.queue_desc; + if (availoff > UINT32_MAX || usedoff > UINT32_MAX || + (usedoff & 3) != 0) { + vq_info->vq_enabled = 0; + return; + } + + availsz = sizeof(uint16_t) * (2 + vq_info->qs); + usedsz = (sizeof(uint16_t) * 2) + + (sizeof(struct vring_used_elem) * vq_info->qs); + hva = hvaddr_mem(dev->pci_cfg.queue_desc + availoff, availsz); + if (hva == NULL) { + vq_info->vq_enabled = 0; + return; + } + hva = hvaddr_mem(dev->pci_cfg.queue_desc + usedoff, usedsz); + if (hva == NULL) { + vq_info->vq_enabled = 0; + return; + } + if (vq_info->qs > 0 && vq_info->qs % 2 == 0) { - vq_info->vq_availoffset = dev->pci_cfg.queue_avail - - dev->pci_cfg.queue_desc; - vq_info->vq_usedoffset = dev->pci_cfg.queue_used - - dev->pci_cfg.queue_desc; + vq_info->vq_availoffset = availoff; + vq_info->vq_usedoffset = usedoff; vq_info->vq_enabled = (dev->pci_cfg.queue_enable == 1); } else { vq_info->vq_availoffset = 0; @@ -295,8 +326,10 @@ viornd_notifyq(struct virtio_dev *dev, u dxx = avail->ring[aidx] & vq_info->mask; sz = desc[dxx].len; - if (sz > MAXPHYS) - fatalx("viornd descriptor size too large (%zu)", sz); + if (sz > MAXPHYS) { + log_warnx("viornd descriptor size too large (%zu)", sz); + return (0); + } rnd_data = malloc(sz); if (rnd_data == NULL)