migration/multifd: Fix leaks of TLS error objects
The code currently ignores errors from multifd threads that happen after a first error has already been propagated. Make sure the subsequent errors are freed appopriately. This fixes a leak of the TLS session->werr when the certificate validation fails after multifd threads are already running. The first writes on the threads will fail deep into the gnutls stack. No need to check if(err) because the callers are all under a similar check. Reviewed-by: Peter Xu <peterx@redhat.com> Reviewed-by: Prasad Pandit <pjp@fedoraproject.org> Link: https://lore.kernel.org/qemu-devel/20260311213418.16951-5-farosas@suse.de Signed-off-by: Fabiano Rosas <farosas@suse.de>
Fabiano Rosas committed
Mar 11, 2026 at 18:34 UTC
56b9cfd5da14555ae6874c19195dff4cf8cad87a
1 file changed
+12
-15
migration/multifd.c
+12
-15
@@ -412,28 +412,25 @@ bool multifd_send(MultiFDSendData **send_data)
412
/* Multifd send side hit an error; remember it and prepare to quit */
413
static void multifd_send_error_propagate(Error *err)
414
{
415
+ MigrationState *s = migrate_get_current();
416
+
417
/*
416
- * We don't want to exit each threads twice. Depending on where
417
- * we get the error, or if there are two independent errors in two
418
- * threads at the same time, we can end calling this function
419
- * twice.
418
+ * There may be independent errors in each thread. Propagate the
419
+ * first and free the subsequent ones.
420
*/
421
if (qatomic_xchg(&multifd_send_state->exiting, 1)) {
422
+ error_free(err);
423
return;
424
}
425
425
- if (err) {
426
- MigrationState *s = migrate_get_current();
427
-
428
- migrate_error_propagate(s, err);
426
+ migrate_error_propagate(s, err);
427
430
- if (s->state == MIGRATION_STATUS_SETUP ||
431
- s->state == MIGRATION_STATUS_PRE_SWITCHOVER ||
432
- s->state == MIGRATION_STATUS_DEVICE ||
433
- s->state == MIGRATION_STATUS_ACTIVE) {
434
- migrate_set_state(&s->state, s->state,
435
- MIGRATION_STATUS_FAILING);
436
- }
428
+ if (s->state == MIGRATION_STATUS_SETUP ||
429
+ s->state == MIGRATION_STATUS_PRE_SWITCHOVER ||
430
+ s->state == MIGRATION_STATUS_DEVICE ||
431
+ s->state == MIGRATION_STATUS_ACTIVE) {
432
+ migrate_set_state(&s->state, s->state,
433
+ MIGRATION_STATUS_FAILING);
434
}
435
}
436