Skip to content

Commit d5ddc13

Browse files
authored
Fix qemu snapshot module unmap (#3084)
* fix qemu usermode snapshot unmap * fix phys addr computation for qemu. some cleanup.
1 parent a613676 commit d5ddc13

File tree

4 files changed

+19
-20
lines changed

4 files changed

+19
-20
lines changed

fuzzers/binary_only/qemu_cmin/Justfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,4 @@ test:
4242

4343
[unix]
4444
clean:
45-
cargo clean
45+
cargo clean

libafl_qemu/libafl_qemu_build/src/bindings.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ pub fn generate(
169169
.allowlist_function("qemu_plugin_hwaddr_phys_addr")
170170
.allowlist_function("qemu_plugin_get_hwaddr")
171171
.allowlist_function("qemu_target_page_size")
172+
.allowlist_function("qemu_target_page_mask")
172173
.allowlist_function("syx_.*")
173174
.allowlist_function("device_list_all")
174175
.allowlist_function("libafl_.*")

libafl_qemu/src/modules/usermode/snapshot.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,6 @@ pub struct SnapshotModule {
154154
pub mmap_limit: usize,
155155
pub stop_execution: Option<StopExecutionCallback>,
156156
pub empty: bool,
157-
pub accurate_unmap: bool,
158157
pub interval_filter: IntervalSnapshotFilters,
159158
auto_reset: bool,
160159
}
@@ -187,7 +186,6 @@ impl SnapshotModule {
187186
mmap_limit: 0,
188187
stop_execution: None,
189188
empty: true,
190-
accurate_unmap: false,
191189
interval_filter: IntervalSnapshotFilters::new(),
192190
auto_reset: true,
193191
}
@@ -206,7 +204,6 @@ impl SnapshotModule {
206204
mmap_limit: 0,
207205
stop_execution: None,
208206
empty: true,
209-
accurate_unmap: false,
210207
interval_filter,
211208
auto_reset: true,
212209
}
@@ -225,16 +222,11 @@ impl SnapshotModule {
225222
mmap_limit,
226223
stop_execution: Some(stop_execution),
227224
empty: true,
228-
accurate_unmap: false,
229225
interval_filter: IntervalSnapshotFilters::new(),
230226
auto_reset: true,
231227
}
232228
}
233229

234-
pub fn use_accurate_unmapping(&mut self) {
235-
self.accurate_unmap = true;
236-
}
237-
238230
pub fn use_manual_reset(&mut self) {
239231
self.auto_reset = false;
240232
}
@@ -583,10 +575,13 @@ impl SnapshotModule {
583575
found
584576
}
585577

578+
/// Unmap is allowed if it is not part of the pre-snapshot region. maybe check if it's part
579+
/// of qemu's guest memory or not?
586580
pub fn is_unmap_allowed(&mut self, start: GuestAddr, mut size: usize) -> bool {
587581
if size % SNAPSHOT_PAGE_SIZE != 0 {
588582
size = size + (SNAPSHOT_PAGE_SIZE - size % SNAPSHOT_PAGE_SIZE);
589583
}
584+
590585
self.maps
591586
.tree
592587
.query(start..(start + (size as GuestAddr)))
@@ -803,9 +798,8 @@ where
803798
);
804799
}
805800

806-
if !self.accurate_unmap {
807-
emulator_modules.pre_syscalls(Hook::Function(filter_mmap_snapshot::<ET, I, S>));
808-
}
801+
emulator_modules.pre_syscalls(Hook::Function(filter_mmap_snapshot::<ET, I, S>));
802+
809803
emulator_modules.post_syscalls(Hook::Function(trace_mmap_snapshot::<ET, I, S>));
810804
}
811805

@@ -870,6 +864,7 @@ pub fn trace_write_n_snapshot<ET, I, S>(
870864
h.access(addr, size);
871865
}
872866

867+
/// Do not consider munmap syscalls that are not allowed
873868
#[expect(clippy::too_many_arguments)]
874869
pub fn filter_mmap_snapshot<ET, I, S>(
875870
_qemu: Qemu,
@@ -896,6 +891,7 @@ where
896891
return SyscallHookResult::new(Some(0));
897892
}
898893
}
894+
899895
SyscallHookResult::new(None)
900896
}
901897

@@ -1007,7 +1003,7 @@ where
10071003
}
10081004
} else if sys_const == SYS_munmap {
10091005
let h = emulator_modules.get_mut::<SnapshotModule>().unwrap();
1010-
if !h.accurate_unmap && !h.is_unmap_allowed(a0, a1 as usize) {
1006+
if h.is_unmap_allowed(a0, a1 as usize) {
10111007
h.remove_mapped(a0, a1 as usize);
10121008
}
10131009
}

libafl_qemu/src/qemu/systemmode.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,13 @@ impl CPU {
9696
page as GuestVirtAddr,
9797
attrs.as_mut_ptr(),
9898
);
99+
let mask = Qemu::get_unchecked().target_page_mask();
100+
let offset = vaddr & (mask as GuestVirtAddr);
99101
#[expect(clippy::cast_sign_loss)]
100102
if paddr == (-1i64 as GuestPhysAddr) {
101103
None
102104
} else {
103-
Some(paddr)
105+
Some(paddr + offset)
104106
}
105107
}
106108
}
@@ -180,11 +182,6 @@ impl CPU {
180182

181183
#[expect(clippy::unused_self)]
182184
impl Qemu {
183-
#[must_use]
184-
pub fn guest_page_size(&self) -> usize {
185-
4096
186-
}
187-
188185
/// Write a value to a physical guest address, including ROM areas.
189186
///
190187
/// # Safety
@@ -313,6 +310,11 @@ impl Qemu {
313310
pub fn target_page_size(&self) -> usize {
314311
unsafe { libafl_qemu_sys::qemu_target_page_size() }
315312
}
313+
314+
#[must_use]
315+
pub fn target_page_mask(&self) -> usize {
316+
unsafe { libafl_qemu_sys::qemu_target_page_mask() as usize }
317+
}
316318
}
317319

318320
impl QemuMemoryChunk {
@@ -426,7 +428,7 @@ impl Iterator for PhysMemoryIter {
426428
}
427429
};
428430
let start_phys_addr: GuestPhysAddr = self.cpu.get_phys_addr(*vaddr)?;
429-
let phys_page_size = self.qemu.guest_page_size();
431+
let phys_page_size = self.qemu.target_page_size();
430432

431433
// TODO: Turn this into a generic function
432434
let mut size_taken: usize = std::cmp::min(

0 commit comments

Comments
 (0)