From 41606c9357700373b7d4f3e3c22e58322d1a5a79 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Wed, 29 Mar 2023 04:27:31 +0000 Subject: [PATCH 1/2] virtio(4): Fix sizing of virtqueue allocation. vq->vq_avail[0].ring is a zero-length array, and thus sizeof is zero; likewise vq->vq_used[0].ring. Use vq->vq_avail[0].ring[0] and vq->vq_used[0].ring[0] to fix this and restore the previous allocation sizing logic. XXX We shouldn't use zero-length arrays here -- they are asking for trouble like this, and C99 has a standard way to express what we're actually trying to get at it, flexible array members. PR kern/57304 Reported-by: syzbot+7fb1047f5dfa33b26331@syzkaller.appspotmail.com --- sys/dev/pci/virtio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/dev/pci/virtio.c b/sys/dev/pci/virtio.c index 70209f164a86..1ffd6c62fe35 100644 --- a/sys/dev/pci/virtio.c +++ b/sys/dev/pci/virtio.c @@ -784,9 +784,9 @@ virtio_alloc_vq(struct virtio_softc *sc, struct virtqueue *vq, size_desc = sizeof(vq->vq_desc[0]) * vq_num; size_avail = sizeof(uint16_t) * hdrlen - + sizeof(vq->vq_avail[0].ring) * vq_num; + + sizeof(vq->vq_avail[0].ring[0]) * vq_num; size_used = sizeof(uint16_t) *hdrlen - + sizeof(vq->vq_used[0].ring) * vq_num; + + sizeof(vq->vq_used[0].ring[0]) * vq_num; size_indirect = (sc->sc_indirect && maxnsegs >= MINSEG_INDIRECT) ? sizeof(struct vring_desc) * maxnsegs * vq_num : 0; From c9afd79685a4e76fafd7719af8fb5a64dfa7c33d Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Wed, 29 Mar 2023 04:31:38 +0000 Subject: [PATCH 2/2] virtio(4): Use flexible array members, not zero-length arrays. This detects mistakes in sizeof like PR kern/57304. --- sys/dev/pci/virtioreg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/dev/pci/virtioreg.h b/sys/dev/pci/virtioreg.h index ea4435701ffa..27e97eaf3955 100644 --- a/sys/dev/pci/virtioreg.h +++ b/sys/dev/pci/virtioreg.h @@ -153,7 +153,7 @@ struct vring_desc { struct vring_avail { uint16_t flags; uint16_t idx; - uint16_t ring[0]; + uint16_t ring[]; /* trailed by uint16_t used_event when VIRTIO_F_RING_EVENT_IDX */ } __packed; @@ -168,7 +168,7 @@ struct vring_used_elem { struct vring_used { uint16_t flags; uint16_t idx; - struct vring_used_elem ring[0]; + struct vring_used_elem ring[]; /* trailed by uint16_t avail_event when VIRTIO_F_RING_EVENT_IDX */ } __packed;