Skip to content

Commit 65ed715

Browse files
Snapshot use after free (#2125)
* memory snapshots fix use after free on flatview copy When restoring a snapshot with memory the flatview must be restored before the memory reagions are filtered. Because the AddressSpaceDispatcher also has pointer to the MemoryRegions and on copy they need to be cleared. The memory_filter_subregions function frees MemoryRegions which are not used at the time of the snapshot. * fix some memleaks in tests These tests has forgott to call uc_close(uc), which lead to memory leaks. Found by the LeakSanitizer. * memory snapshots correct clean up container memory regions * Fix further stackoverflow in tests --------- Co-authored-by: mio <[email protected]>
1 parent 088c066 commit 65ed715

File tree

6 files changed

+24
-6
lines changed

6 files changed

+24
-6
lines changed

qemu/softmmu/memory.c

+7
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
void memory_region_transaction_begin(void);
3030
static void memory_region_transaction_commit(MemoryRegion *mr);
31+
static void memory_region_destructor_container(MemoryRegion *mr);
3132

3233
typedef struct AddrRange AddrRange;
3334

@@ -87,6 +88,7 @@ static void make_contained(struct uc_struct *uc, MemoryRegion *current)
8788
hwaddr addr = current->addr;
8889
MemoryRegion *container = g_new(MemoryRegion, 1);
8990
memory_region_init(uc, container, int128_get64(current->size));
91+
container->destructor = memory_region_destructor_container;
9092
memory_region_del_subregion(uc->system_memory, current);
9193
memory_region_add_subregion_overlap(container, 0, current, current->priority);
9294
memory_region_add_subregion(uc->system_memory, addr, container);
@@ -1091,6 +1093,11 @@ static void memory_region_destructor_ram(MemoryRegion *mr)
10911093
qemu_ram_free(mr->uc, mr->ram_block);
10921094
}
10931095

1096+
static void memory_region_destructor_container(MemoryRegion *mr)
1097+
{
1098+
memory_region_filter_subregions(mr, 0);
1099+
}
1100+
10941101
void memory_region_init(struct uc_struct *uc,
10951102
MemoryRegion *mr,
10961103
uint64_t size)

tests/unit/test_arm.c

+2
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,7 @@ static void test_arm_tcg_opcode_cmp(void)
905905
TEST_CHECK(cmp_info.v0 == 5 && cmp_info.v1 == 3);
906906
TEST_CHECK(cmp_info.pc == 0x1008);
907907
TEST_CHECK(cmp_info.size == 32);
908+
OK(uc_close(uc));
908909
}
909910

910911
static void test_arm_thumb_tcg_opcode_cmn(void)
@@ -931,6 +932,7 @@ static void test_arm_thumb_tcg_opcode_cmn(void)
931932
TEST_CHECK(cmp_info.v0 == 5 && cmp_info.v1 == 3);
932933
TEST_CHECK(cmp_info.pc == 0x1006);
933934
TEST_CHECK(cmp_info.size == 32);
935+
OK(uc_close(uc));
934936
}
935937

936938
static void test_arm_cp15_c1_c0_2(void)

tests/unit/test_arm64.c

+1
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,7 @@ static void test_arm64_mmu(void)
481481
TEST_CHECK(x1 == 0x4444444444444444);
482482
TEST_CHECK(x2 == 0x4444444444444444);
483483
free(data);
484+
OK(uc_close(uc));
484485
}
485486

486487
static void test_arm64_pc_wrap(void)

tests/unit/test_riscv.c

+1
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,7 @@ static void test_riscv_mmu(void)
718718
OK(uc_mem_read(uc, data_address, &data_result, sizeof(data_result)));
719719

720720
TEST_CHECK(data_value == data_result);
721+
OK(uc_close(uc));
721722
}
722723

723724
static void test_riscv_priv(void)

tests/unit/test_x86.c

+9-2
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,7 @@ static void test_x86_smc_add(void)
632632
{
633633
uc_engine *uc;
634634
uint64_t stack_base = 0x20000;
635-
int r_rsp;
635+
uint64_t r_rsp;
636636
/*
637637
* mov qword ptr [rip+0x10], rax
638638
* mov word ptr [rip], 0x0548
@@ -647,6 +647,8 @@ static void test_x86_smc_add(void)
647647
r_rsp = stack_base + 0x1800;
648648
OK(uc_reg_write(uc, UC_X86_REG_RSP, &r_rsp));
649649
OK(uc_emu_start(uc, code_start, -1, 0, 0));
650+
651+
OK(uc_close(uc));
650652
}
651653

652654
static void test_x86_smc_mem_hook_callback(uc_engine *uc, uc_mem_type t,
@@ -667,7 +669,7 @@ static void test_x86_smc_mem_hook(void)
667669
uc_engine *uc;
668670
uc_hook hook;
669671
uint64_t stack_base = 0x20000;
670-
int r_rsp;
672+
uint64_t r_rsp;
671673
unsigned int i = 0;
672674
/*
673675
* mov qword ptr [rip+0x29], rax
@@ -689,6 +691,8 @@ static void test_x86_smc_mem_hook(void)
689691
r_rsp = stack_base + 0x1800;
690692
OK(uc_reg_write(uc, UC_X86_REG_RSP, &r_rsp));
691693
OK(uc_emu_start(uc, code_start, -1, 0, 0));
694+
695+
OK(uc_close(uc));
692696
}
693697

694698
static uint64_t test_x86_mmio_uc_mem_rw_read_callback(uc_engine *uc,
@@ -1589,6 +1593,8 @@ static void test_x86_mmu(void)
15891593
OK(uc_mem_read(uc, 0x2000, &child, sizeof(child)));
15901594
TEST_CHECK(parrent == 60);
15911595
TEST_CHECK(child == 42);
1596+
OK(uc_context_free(context));
1597+
OK(uc_close(uc));
15921598
}
15931599

15941600
static bool test_x86_vtlb_callback(uc_engine *uc, uint64_t addr,
@@ -1632,6 +1638,7 @@ static void test_x86_segmentation(void)
16321638
OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc));
16331639
OK(uc_reg_write(uc, UC_X86_REG_GDTR, &gdtr));
16341640
uc_assert_err(UC_ERR_EXCEPTION, uc_reg_write(uc, UC_X86_REG_FS, &fs));
1641+
OK(uc_close(uc));
16351642
}
16361643

16371644
static void test_x86_0xff_lcall_callback(uc_engine *uc, uint64_t address,

uc.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -2439,6 +2439,10 @@ uc_err uc_context_restore(uc_engine *uc, uc_context *context)
24392439

24402440
if (uc->context_content & UC_CTL_CONTEXT_MEMORY) {
24412441
uc->snapshot_level = context->snapshot_level;
2442+
if (!uc->flatview_copy(uc, uc->address_space_memory.current_map,
2443+
context->fv, true)) {
2444+
return UC_ERR_NOMEM;
2445+
}
24422446
ret = uc_restore_latest_snapshot(uc);
24432447
if (ret != UC_ERR_OK) {
24442448
restore_jit_state(uc);
@@ -2447,10 +2451,6 @@ uc_err uc_context_restore(uc_engine *uc, uc_context *context)
24472451
uc_snapshot(uc);
24482452
uc->ram_list.freed = context->ramblock_freed;
24492453
uc->ram_list.last_block = context->last_block;
2450-
if (!uc->flatview_copy(uc, uc->address_space_memory.current_map,
2451-
context->fv, true)) {
2452-
return UC_ERR_NOMEM;
2453-
}
24542454
uc->tcg_flush_tlb(uc);
24552455
}
24562456

0 commit comments

Comments
 (0)