Browse Source

migration/savevm: Add a compatibility check for capabilities

It has always been possible to enable arbitrary migration capabilities
and attempt to take a snapshot of the VM with the savevm/loadvm
commands as well as their QMP counterparts
snapshot-save/snapshot-load.

Most migration capabilities are not meant to be used with snapshots
and there's a risk of crashing QEMU or producing incorrect
behavior. Ideally, every migration capability would either be
implemented for savevm or explicitly rejected.

Add a compatibility check routine and reject the snapshot command if
an incompatible capability is enabled. For now only act on the the two
that actually cause a crash: multifd and mapped-ram.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2881
Signed-off-by: Fabiano Rosas <farosas@suse.de>
Link: https://lore.kernel.org/r/20251007184213.5990-1-farosas@suse.de
Signed-off-by: Peter Xu <peterx@redhat.com>
pull/307/head
Fabiano Rosas 6 months ago
committed by Peter Xu
parent
commit
112b55f0b0
  1. 27
      migration/options.c
  2. 1
      migration/options.h
  3. 8
      migration/savevm.c

27
migration/options.c

@ -445,11 +445,38 @@ INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot,
MIGRATION_CAPABILITY_VALIDATE_UUID,
MIGRATION_CAPABILITY_ZERO_COPY_SEND);
/* Snapshot compatibility check list */
static const
INITIALIZE_MIGRATE_CAPS_SET(check_caps_savevm,
MIGRATION_CAPABILITY_MULTIFD,
MIGRATION_CAPABILITY_MAPPED_RAM,
);
static bool migrate_incoming_started(void)
{
return !!migration_incoming_get_current()->transport_data;
}
bool migrate_can_snapshot(Error **errp)
{
MigrationState *s = migrate_get_current();
int i;
for (i = 0; i < check_caps_savevm.size; i++) {
int incomp_cap = check_caps_savevm.caps[i];
if (s->capabilities[incomp_cap]) {
error_setg(errp,
"Snapshots are not compatible with %s",
MigrationCapability_str(incomp_cap));
return false;
}
}
return true;
}
bool migrate_rdma_caps_check(bool *caps, Error **errp)
{
if (caps[MIGRATION_CAPABILITY_XBZRLE]) {

1
migration/options.h

@ -59,6 +59,7 @@ bool migrate_tls(void);
bool migrate_rdma_caps_check(bool *caps, Error **errp);
bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp);
bool migrate_can_snapshot(Error **errp);
/* parameters */

8
migration/savevm.c

@ -3322,6 +3322,10 @@ bool save_snapshot(const char *name, bool overwrite, const char *vmstate,
GLOBAL_STATE_CODE();
if (!migrate_can_snapshot(errp)) {
return false;
}
if (migration_is_blocked(errp)) {
return false;
}
@ -3507,6 +3511,10 @@ bool load_snapshot(const char *name, const char *vmstate,
int ret;
MigrationIncomingState *mis = migration_incoming_get_current();
if (!migrate_can_snapshot(errp)) {
return false;
}
if (!bdrv_all_can_snapshot(has_devices, devices, errp)) {
return false;
}

Loading…
Cancel
Save