From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:43213) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1W8lp6-00007r-J4 for qemu-devel@nongnu.org; Thu, 30 Jan 2014 02:14:08 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1W8lp2-0003fn-3w for qemu-devel@nongnu.org; Thu, 30 Jan 2014 02:14:04 -0500 Received: from mx1.redhat.com ([209.132.183.28]:20878) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1W8lp1-0003fh-S9 for qemu-devel@nongnu.org; Thu, 30 Jan 2014 02:14:00 -0500 From: Orit Wasserman Date: Thu, 30 Jan 2014 09:14:12 +0200 Message-Id: <1391066055-17024-4-git-send-email-owasserm@redhat.com> In-Reply-To: <1391066055-17024-1-git-send-email-owasserm@redhat.com> References: <1391066055-17024-1-git-send-email-owasserm@redhat.com> Subject: [Qemu-devel] [PATCH 3/6] migration:fix free XBZRLE decoded_buf wrong List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: ChenLiang , peter.maydell@linaro.org, "Gonglei (Arei)" , anthony@codemonkey.ws, quintela@redhat.com From: "Gonglei (Arei)" When qemu do live migration with xbzrle, qemu malloc decoded_buf at destination end but free it at source end. It will crash qemu by double free error in some scenarios. Splitting the XBZRLE structure for clear logic distinguishing src/dst side. Signed-off-by: ChenLiang Reviewed-by: Peter Maydell Reviewed-by: Orit Wasserman Signed-off-by: GongLei --- arch_init.c | 22 ++++++++++++---------- include/migration/migration.h | 1 + migration.c | 1 + 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/arch_init.c b/arch_init.c index 8edeabe..5eff80b 100644 --- a/arch_init.c +++ b/arch_init.c @@ -164,17 +164,15 @@ static struct { uint8_t *encoded_buf; /* buffer for storing page content */ uint8_t *current_buf; - /* buffer used for XBZRLE decoding */ - uint8_t *decoded_buf; /* Cache for XBZRLE */ PageCache *cache; } XBZRLE = { .encoded_buf = NULL, .current_buf = NULL, - .decoded_buf = NULL, .cache = NULL, }; - +/* buffer used for XBZRLE decoding */ +static uint8_t *xbzrle_decoded_buf; int64_t xbzrle_cache_resize(int64_t new_size) { @@ -606,6 +604,12 @@ uint64_t ram_bytes_total(void) return total; } +void free_xbzrle_decoded_buf(void) +{ + g_free(xbzrle_decoded_buf); + xbzrle_decoded_buf = NULL; +} + static void migration_end(void) { if (migration_bitmap) { @@ -619,11 +623,9 @@ static void migration_end(void) g_free(XBZRLE.cache); g_free(XBZRLE.encoded_buf); g_free(XBZRLE.current_buf); - g_free(XBZRLE.decoded_buf); XBZRLE.cache = NULL; XBZRLE.encoded_buf = NULL; XBZRLE.current_buf = NULL; - XBZRLE.decoded_buf = NULL; } } @@ -814,8 +816,8 @@ static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host) unsigned int xh_len; int xh_flags; - if (!XBZRLE.decoded_buf) { - XBZRLE.decoded_buf = g_malloc(TARGET_PAGE_SIZE); + if (!xbzrle_decoded_buf) { + xbzrle_decoded_buf = g_malloc(TARGET_PAGE_SIZE); } /* extract RLE header */ @@ -832,10 +834,10 @@ static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host) return -1; } /* load data and decode */ - qemu_get_buffer(f, XBZRLE.decoded_buf, xh_len); + qemu_get_buffer(f, xbzrle_decoded_buf, xh_len); /* decode RLE */ - ret = xbzrle_decode_buffer(XBZRLE.decoded_buf, xh_len, host, + ret = xbzrle_decode_buffer(xbzrle_decoded_buf, xh_len, host, TARGET_PAGE_SIZE); if (ret == -1) { fprintf(stderr, "Failed to load XBZRLE page - decode error!\n"); diff --git a/include/migration/migration.h b/include/migration/migration.h index bfa3951..3e1e6c7 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -109,6 +109,7 @@ MigrationState *migrate_get_current(void); uint64_t ram_bytes_remaining(void); uint64_t ram_bytes_transferred(void); uint64_t ram_bytes_total(void); +void free_xbzrle_decoded_buf(void); void acct_update_position(QEMUFile *f, size_t size, bool zero); diff --git a/migration.c b/migration.c index 84587e9..46a7305 100644 --- a/migration.c +++ b/migration.c @@ -105,6 +105,7 @@ static void process_incoming_migration_co(void *opaque) ret = qemu_loadvm_state(f); qemu_fclose(f); + free_xbzrle_decoded_buf(); if (ret < 0) { fprintf(stderr, "load of migration failed\n"); exit(EXIT_FAILURE); -- 1.8.3.1