mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-23 19:49:43 +00:00
migration:fix free XBZRLE decoded_buf wrong
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 <chenliang88@huawei.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Orit Wasserman <owasserm@redhat.com> Signed-off-by: GongLei <arei.gonglei@huawei.com> Signed-off-by: Juan Quintela <quintela@redhat.com>
This commit is contained in:
parent
c91e681a55
commit
905f26f222
22
arch_init.c
22
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");
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user