9ae3a8
From 0726ca63bf611741889fb77f68afd9e7e18d4e47 Mon Sep 17 00:00:00 2001
9ae3a8
From: Orit Wasserman <owasserm@redhat.com>
9ae3a8
Date: Tue, 11 Feb 2014 14:56:37 +0100
9ae3a8
Subject: [PATCH 18/28] migration:fix free XBZRLE decoded_buf wrong
9ae3a8
9ae3a8
RH-Author: Orit Wasserman <owasserm@redhat.com>
9ae3a8
Message-id: <1392130597-23600-3-git-send-email-owasserm@redhat.com>
9ae3a8
Patchwork-id: 57213
9ae3a8
O-Subject: [RHEL7 qemu-kvm PATCH 2/2] migration:fix free XBZRLE decoded_buf wrong
9ae3a8
Bugzilla: 1038540
9ae3a8
RH-Acked-by: Marcel Apfelbaum <marcel.a@redhat.com>
9ae3a8
RH-Acked-by: Dr. David Alan Gilbert (git) <dgilbert@redhat.com>
9ae3a8
RH-Acked-by: Juan Quintela <quintela@redhat.com>
9ae3a8
9ae3a8
From: "Gonglei (Arei)" <arei.gonglei@huawei.com>
9ae3a8
9ae3a8
When qemu do live migration with xbzrle, qemu malloc decoded_buf
9ae3a8
at destination end but free it at source end. It will crash qemu
9ae3a8
by double free error in some scenarios. Splitting the XBZRLE structure
9ae3a8
for clear logic distinguishing src/dst side.
9ae3a8
9ae3a8
Signed-off-by: ChenLiang <chenliang88@huawei.com>
9ae3a8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9ae3a8
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
9ae3a8
Signed-off-by: GongLei <arei.gonglei@huawei.com>
9ae3a8
Signed-off-by: Juan Quintela <quintela@redhat.com>
9ae3a8
(cherry picked from commit 905f26f2221e139ac0e7317ddac158c50f5cf876)
9ae3a8
---
9ae3a8
 arch_init.c                   | 22 ++++++++++++----------
9ae3a8
 include/migration/migration.h |  1 +
9ae3a8
 migration.c                   |  1 +
9ae3a8
 3 files changed, 14 insertions(+), 10 deletions(-)
9ae3a8
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
---
9ae3a8
 arch_init.c                   |   22 ++++++++++++----------
9ae3a8
 include/migration/migration.h |    1 +
9ae3a8
 migration.c                   |    1 +
9ae3a8
 3 files changed, 14 insertions(+), 10 deletions(-)
9ae3a8
9ae3a8
diff --git a/arch_init.c b/arch_init.c
9ae3a8
index 65148d6..31bf690 100644
9ae3a8
--- a/arch_init.c
9ae3a8
+++ b/arch_init.c
9ae3a8
@@ -164,17 +164,15 @@ static struct {
9ae3a8
     uint8_t *encoded_buf;
9ae3a8
     /* buffer for storing page content */
9ae3a8
     uint8_t *current_buf;
9ae3a8
-    /* buffer used for XBZRLE decoding */
9ae3a8
-    uint8_t *decoded_buf;
9ae3a8
     /* Cache for XBZRLE */
9ae3a8
     PageCache *cache;
9ae3a8
 } XBZRLE = {
9ae3a8
     .encoded_buf = NULL,
9ae3a8
     .current_buf = NULL,
9ae3a8
-    .decoded_buf = NULL,
9ae3a8
     .cache = NULL,
9ae3a8
 };
9ae3a8
-
9ae3a8
+/* buffer used for XBZRLE decoding */
9ae3a8
+static uint8_t *xbzrle_decoded_buf;
9ae3a8
 
9ae3a8
 int64_t xbzrle_cache_resize(int64_t new_size)
9ae3a8
 {
9ae3a8
@@ -608,6 +606,12 @@ uint64_t ram_bytes_total(void)
9ae3a8
     return total;
9ae3a8
 }
9ae3a8
 
9ae3a8
+void free_xbzrle_decoded_buf(void)
9ae3a8
+{
9ae3a8
+    g_free(xbzrle_decoded_buf);
9ae3a8
+    xbzrle_decoded_buf = NULL;
9ae3a8
+}
9ae3a8
+
9ae3a8
 static void migration_end(void)
9ae3a8
 {
9ae3a8
     if (migration_bitmap) {
9ae3a8
@@ -621,11 +625,9 @@ static void migration_end(void)
9ae3a8
         g_free(XBZRLE.cache);
9ae3a8
         g_free(XBZRLE.encoded_buf);
9ae3a8
         g_free(XBZRLE.current_buf);
9ae3a8
-        g_free(XBZRLE.decoded_buf);
9ae3a8
         XBZRLE.cache = NULL;
9ae3a8
         XBZRLE.encoded_buf = NULL;
9ae3a8
         XBZRLE.current_buf = NULL;
9ae3a8
-        XBZRLE.decoded_buf = NULL;
9ae3a8
     }
9ae3a8
 }
9ae3a8
 
9ae3a8
@@ -830,8 +832,8 @@ static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host)
9ae3a8
     unsigned int xh_len;
9ae3a8
     int xh_flags;
9ae3a8
 
9ae3a8
-    if (!XBZRLE.decoded_buf) {
9ae3a8
-        XBZRLE.decoded_buf = g_malloc(TARGET_PAGE_SIZE);
9ae3a8
+    if (!xbzrle_decoded_buf) {
9ae3a8
+        xbzrle_decoded_buf = g_malloc(TARGET_PAGE_SIZE);
9ae3a8
     }
9ae3a8
 
9ae3a8
     /* extract RLE header */
9ae3a8
@@ -848,10 +850,10 @@ static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host)
9ae3a8
         return -1;
9ae3a8
     }
9ae3a8
     /* load data and decode */
9ae3a8
-    qemu_get_buffer(f, XBZRLE.decoded_buf, xh_len);
9ae3a8
+    qemu_get_buffer(f, xbzrle_decoded_buf, xh_len);
9ae3a8
 
9ae3a8
     /* decode RLE */
9ae3a8
-    ret = xbzrle_decode_buffer(XBZRLE.decoded_buf, xh_len, host,
9ae3a8
+    ret = xbzrle_decode_buffer(xbzrle_decoded_buf, xh_len, host,
9ae3a8
                                TARGET_PAGE_SIZE);
9ae3a8
     if (ret == -1) {
9ae3a8
         fprintf(stderr, "Failed to load XBZRLE page - decode error!\n");
9ae3a8
diff --git a/include/migration/migration.h b/include/migration/migration.h
9ae3a8
index 140e6b4..9314511 100644
9ae3a8
--- a/include/migration/migration.h
9ae3a8
+++ b/include/migration/migration.h
9ae3a8
@@ -98,6 +98,7 @@ MigrationState *migrate_get_current(void);
9ae3a8
 uint64_t ram_bytes_remaining(void);
9ae3a8
 uint64_t ram_bytes_transferred(void);
9ae3a8
 uint64_t ram_bytes_total(void);
9ae3a8
+void free_xbzrle_decoded_buf(void);
9ae3a8
 
9ae3a8
 void acct_update_position(QEMUFile *f, size_t size, bool zero);
9ae3a8
 
9ae3a8
diff --git a/migration.c b/migration.c
9ae3a8
index b6de990..93de654 100644
9ae3a8
--- a/migration.c
9ae3a8
+++ b/migration.c
9ae3a8
@@ -104,6 +104,7 @@ static void process_incoming_migration_co(void *opaque)
9ae3a8
 
9ae3a8
     ret = qemu_loadvm_state(f);
9ae3a8
     qemu_fclose(f);
9ae3a8
+    free_xbzrle_decoded_buf();
9ae3a8
     if (ret < 0) {
9ae3a8
         fprintf(stderr, "load of migration failed\n");
9ae3a8
         exit(EXIT_FAILURE);
9ae3a8
-- 
9ae3a8
1.7.1
9ae3a8