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