diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2015-02-11 15:21:04 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2015-02-11 21:48:44 +0100 |
commit | ac95190ea92f7625bb0065c2864321607b95c26b (patch) | |
tree | 80e1901692ef514cb738a2ec048feaf914b7674d | |
parent | a464982499b2f637f6699e3d03e0a9d2e0b5288b (diff) |
memory: keep the owner of the AddressSpace alive until do_address_space_destroy
This fixes a use-after-free if do_address_space_destroy is executed
too late.
Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Tested-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | memory.c | 5 |
1 files changed, 5 insertions, 0 deletions
@@ -1943,6 +1943,7 @@ void memory_listener_unregister(MemoryListener *listener) void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name) { + memory_region_ref(root); memory_region_transaction_begin(); as->root = root; as->current_map = g_new(FlatView, 1); @@ -1969,10 +1970,13 @@ static void do_address_space_destroy(AddressSpace *as) flatview_unref(as->current_map); g_free(as->name); g_free(as->ioeventfds); + memory_region_unref(as->root); } void address_space_destroy(AddressSpace *as) { + MemoryRegion *root = as->root; + /* Flush out anything from MemoryListeners listening in on this */ memory_region_transaction_begin(); as->root = NULL; @@ -1984,6 +1988,7 @@ void address_space_destroy(AddressSpace *as) * entries that the guest should never use. Wait for the old * values to expire before freeing the data. */ + as->root = root; call_rcu(as, do_address_space_destroy, rcu); } |