aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJinhao Gao <gaojinhao@huawei.com>2020-12-31 14:10:19 +0800
committerDr. David Alan Gilbert <dgilbert@redhat.com>2021-02-08 11:19:51 +0000
commit39f633d429f249db4f5d2eff7f56381517c7531e (patch)
treec151fbd63d84a27799447d212c0cdbf6fef125f8
parente6ddad1fd53e6e4d65726e41c7063900a69ab694 (diff)
savevm: Fix memory leak of vmstate_configuration
When VM migrate VMState of configuration, the fields(name and capabilities) of configuration having a flag of VMS_ALLOC need to allocate memory. If the src doesn't free memory of capabilities in SaveState after save VMState of configuration, or the dst doesn't free memory of name and capabilities in post load of configuration, it may result in memory leak of name and capabilities. We free memory in configuration_post_save and configuration_post_load func, which prevents memory leak. Reported-by: Euler Robot <euler.robot@huawei.com> Signed-off-by: Jinhao Gao <gaojinhao@huawei.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Message-Id: <20201231061020.828-3-gaojinhao@huawei.com> Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
-rw-r--r--migration/savevm.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/migration/savevm.c b/migration/savevm.c
index 4f3b69ecfc..d1e6aaed60 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -315,6 +315,16 @@ static int configuration_pre_save(void *opaque)
return 0;
}
+static int configuration_post_save(void *opaque)
+{
+ SaveState *state = opaque;
+
+ g_free(state->capabilities);
+ state->capabilities = NULL;
+ state->caps_count = 0;
+ return 0;
+}
+
static int configuration_pre_load(void *opaque)
{
SaveState *state = opaque;
@@ -365,24 +375,36 @@ static int configuration_post_load(void *opaque, int version_id)
{
SaveState *state = opaque;
const char *current_name = MACHINE_GET_CLASS(current_machine)->name;
+ int ret = 0;
if (strncmp(state->name, current_name, state->len) != 0) {
error_report("Machine type received is '%.*s' and local is '%s'",
(int) state->len, state->name, current_name);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
if (state->target_page_bits != qemu_target_page_bits()) {
error_report("Received TARGET_PAGE_BITS is %d but local is %d",
state->target_page_bits, qemu_target_page_bits());
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
if (!configuration_validate_capabilities(state)) {
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
- return 0;
+out:
+ g_free((void *)state->name);
+ state->name = NULL;
+ state->len = 0;
+ g_free(state->capabilities);
+ state->capabilities = NULL;
+ state->caps_count = 0;
+
+ return ret;
}
static int get_capability(QEMUFile *f, void *pv, size_t size,
@@ -516,6 +538,7 @@ static const VMStateDescription vmstate_configuration = {
.pre_load = configuration_pre_load,
.post_load = configuration_post_load,
.pre_save = configuration_pre_save,
+ .post_save = configuration_post_save,
.fields = (VMStateField[]) {
VMSTATE_UINT32(len, SaveState),
VMSTATE_VBUFFER_ALLOC_UINT32(name, SaveState, 0, NULL, len),