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>
Fabiano Rosas committed
Aug 18, 2026 at 15:24 UTC
c3b99f3091d0c840c33fc204c8dacdb599abc83d
1 file changed
+22
-8
migration/vmstate.c
+22
-8
@@ -148,16 +148,28 @@ static uint64_t vmstate_size(void *opaque, const VMStateField *field)
148
return size;
149
}
150
151
-static void vmstate_handle_alloc(void *ptr, const VMStateField *field,
152
- void *opaque)
151
+static bool vmstate_handle_alloc(void *ptr, const VMStateField *field,
152
+ uint64_t n, uint64_t size, Error **errp)
153
{
154
+ void *p;
155
+
156
if (field->flags & VMS_POINTER && field->flags & VMS_ALLOC) {
155
- uint64_t size = vmstate_size(opaque, field);
156
- size *= vmstate_n_elems(opaque, field);
157
- if (size) {
158
- *(void **)ptr = g_malloc(size);
159
- }
157
+ if (size && n) {
158
+ if (umul64_overflow(size, n, &size)) {
159
+ error_setg(errp, "%s: field '%s' multiply overflow",
160
+ __func__, field->name);
161
+ return false;
162
+ }
163
+ p = g_try_malloc(size);
164
+ if (!p) {
165
+ error_setg(errp, "%s: Could not allocate memory for field '%s'",
166
+ __func__, field->name);
167
+ return false;
168
+ }
169
+ *(void **)ptr = p;
170
+ }
171
}
172
+ return true;
173
}
174
175
static bool vmstate_ptr_marker_load(QEMUFile *f, bool *load_field,
@@ -367,7 +379,9 @@ bool vmstate_load_vmsd(QEMUFile *f, const VMStateDescription *vmsd,
379
uint64_t n_elems = vmstate_n_elems(opaque, field);
380
uint64_t size = vmstate_size(opaque, field);
381
370
- vmstate_handle_alloc(first_elem, field, opaque);
382
+ if (!vmstate_handle_alloc(first_elem, field, n_elems, size, errp)) {
383
+ return false;
384
+ }
385
if (field->flags & VMS_POINTER) {
386
first_elem = *(void **)first_elem;
387
assert(first_elem || !n_elems || !size);