From: Marc-André Lureau <marcandre.lureau@redhat.com>
An unbounded iov_cnt from the migration stream drives two g_new()
allocations whose combined size can exceed available memory, causing
GLib to abort the process.
Switch to g_try_new() and propagate the failure as a migration error.
Fixes: 0c244e50ee12 ("virtio-gpu: add live migration support")
Fixes: f66767f75c9c ("virtio-gpu: add virtio-gpu/blob vmstate subsection")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3753
Reported-by: Feifan Qian <bea1e@proton.me>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
hw/display/virtio-gpu.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index e00fb6effa5..048b151872e 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1365,8 +1365,15 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
return -EINVAL;
}
- res->addrs = g_new(uint64_t, res->iov_cnt);
- res->iov = g_new(struct iovec, res->iov_cnt);
+ res->addrs = g_try_new(uint64_t, res->iov_cnt);
+ res->iov = g_try_new(struct iovec, res->iov_cnt);
+ if (res->iov_cnt && (!res->addrs || !res->iov)) {
+ pixman_image_unref(res->image);
+ g_free(res->addrs);
+ g_free(res->iov);
+ g_free(res);
+ return -EINVAL;
+ }
/* read data */
for (i = 0; i < res->iov_cnt; i++) {
@@ -1440,8 +1447,15 @@ static int virtio_gpu_blob_load(QEMUFile *f, void *opaque, size_t size,
res->resource_id = resource_id;
res->blob_size = qemu_get_be32(f);
res->iov_cnt = qemu_get_be32(f);
- res->addrs = g_new(uint64_t, res->iov_cnt);
- res->iov = g_new(struct iovec, res->iov_cnt);
+
+ res->addrs = g_try_new(uint64_t, res->iov_cnt);
+ res->iov = g_try_new(struct iovec, res->iov_cnt);
+ if (res->iov_cnt && (!res->addrs || !res->iov)) {
+ g_free(res->addrs);
+ g_free(res->iov);
+ g_free(res);
+ return -EINVAL;
+ }
/* read data */
for (i = 0; i < res->iov_cnt; i++) {
--
2.55.0