[PATCH v3 4/7] hw/virtio: return NULL from qemu_get_virtqueue_element() on invalid state
Laurent Vivier <[email protected]>
| Newsgroups | gmane.comp.emulators.qemu.stable,gmane.comp.emulators.qemu,gmane.comp.emulators.qemu.block |
|---|---|
| Message-ID | <[email protected]> |
qemu_get_virtqueue_element() uses assert() to check that the in_num and out_num fields deserialized from the migration stream do not exceed VIRTQUEUE_MAX_SIZE. A crafted migration stream can set these fields to invalid values, hitting the assertion and aborting the destination QEMU process. Replace the assertions with a bounds check that returns NULL on failure. Cc: [email protected] Fixes: 6bdc21c050a2 ("virtio: fix up max size checks") Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3802 Signed-off-by: Laurent Vivier <[email protected]> --- Notes: v2: remove caller updates (now handled by patch 3 from Michael) hw/virtio/virtio.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 02f75a5e281b..c37ef01bf513 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -2190,13 +2190,10 @@ void *qemu_get_virtqueue_element(VirtIODevice *vdev, QEMUFile *f, size_t sz) qemu_get_buffer(f, (uint8_t *)&data, sizeof(VirtQueueElementOld)); - /* TODO: teach all callers that this can fail, and return failure instead - * of asserting here. - * This is just one thing (there are probably more) that must be - * fixed before we can allow NDEBUG compilation. - */ - assert(ARRAY_SIZE(data.in_addr) >= data.in_num); - assert(ARRAY_SIZE(data.out_addr) >= data.out_num); + if (data.in_num > ARRAY_SIZE(data.in_addr) || + data.out_num > ARRAY_SIZE(data.out_addr)) { + return NULL; + } elem = virtqueue_alloc_element(sz, data.out_num, data.in_num); elem->index = data.index; -- 2.54.0