Commit c3b99f3091 for qemu.org
commit c3b99f3091d0c840c33fc204c8dacdb599abc83d
Author: Fabiano Rosas <farosas@suse.de>
Date: Tue Aug 18 15:24:40 2026 -0300
migration: Harden vmstate_handle_alloc
Harden the vmstate_handle_alloc function against overflow of the 64bit
integers it consumes and failure to allocate due to an exceedingly
large request.
Acked-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Fabiano Rosas <farosas@suse.de>
diff --git a/migration/vmstate.c b/migration/vmstate.c
index 1f9cb45923..cbcd86e5b6 100644
--- a/migration/vmstate.c
+++ b/migration/vmstate.c
@@ -148,16 +148,28 @@ static uint64_t vmstate_size(void *opaque, const VMStateField *field)
return size;
}
-static void vmstate_handle_alloc(void *ptr, const VMStateField *field,
- void *opaque)
+static bool vmstate_handle_alloc(void *ptr, const VMStateField *field,
+ uint64_t n, uint64_t size, Error **errp)
{
+ void *p;
+
if (field->flags & VMS_POINTER && field->flags & VMS_ALLOC) {
- uint64_t size = vmstate_size(opaque, field);
- size *= vmstate_n_elems(opaque, field);
- if (size) {
- *(void **)ptr = g_malloc(size);
- }
+ if (size && n) {
+ if (umul64_overflow(size, n, &size)) {
+ error_setg(errp, "%s: field '%s' multiply overflow",
+ __func__, field->name);
+ return false;
+ }
+ p = g_try_malloc(size);
+ if (!p) {
+ error_setg(errp, "%s: Could not allocate memory for field '%s'",
+ __func__, field->name);
+ return false;
+ }
+ *(void **)ptr = p;
+ }
}
+ return true;
}
static bool vmstate_ptr_marker_load(QEMUFile *f, bool *load_field,
@@ -367,7 +379,9 @@ bool vmstate_load_vmsd(QEMUFile *f, const VMStateDescription *vmsd,
uint64_t n_elems = vmstate_n_elems(opaque, field);
uint64_t size = vmstate_size(opaque, field);
- vmstate_handle_alloc(first_elem, field, opaque);
+ if (!vmstate_handle_alloc(first_elem, field, n_elems, size, errp)) {
+ return false;
+ }
if (field->flags & VMS_POINTER) {
first_elem = *(void **)first_elem;
assert(first_elem || !n_elems || !size);