Fix qemu snapshot module unmap (#3084)
* fix qemu usermode snapshot unmap * fix phys addr computation for qemu. some cleanup.
This commit is contained in:
parent
a613676675
commit
d5ddc1359e
@ -169,6 +169,7 @@ pub fn generate(
|
|||||||
.allowlist_function("qemu_plugin_hwaddr_phys_addr")
|
.allowlist_function("qemu_plugin_hwaddr_phys_addr")
|
||||||
.allowlist_function("qemu_plugin_get_hwaddr")
|
.allowlist_function("qemu_plugin_get_hwaddr")
|
||||||
.allowlist_function("qemu_target_page_size")
|
.allowlist_function("qemu_target_page_size")
|
||||||
|
.allowlist_function("qemu_target_page_mask")
|
||||||
.allowlist_function("syx_.*")
|
.allowlist_function("syx_.*")
|
||||||
.allowlist_function("device_list_all")
|
.allowlist_function("device_list_all")
|
||||||
.allowlist_function("libafl_.*")
|
.allowlist_function("libafl_.*")
|
||||||
|
@ -154,7 +154,6 @@ pub struct SnapshotModule {
|
|||||||
pub mmap_limit: usize,
|
pub mmap_limit: usize,
|
||||||
pub stop_execution: Option<StopExecutionCallback>,
|
pub stop_execution: Option<StopExecutionCallback>,
|
||||||
pub empty: bool,
|
pub empty: bool,
|
||||||
pub accurate_unmap: bool,
|
|
||||||
pub interval_filter: IntervalSnapshotFilters,
|
pub interval_filter: IntervalSnapshotFilters,
|
||||||
auto_reset: bool,
|
auto_reset: bool,
|
||||||
}
|
}
|
||||||
@ -187,7 +186,6 @@ impl SnapshotModule {
|
|||||||
mmap_limit: 0,
|
mmap_limit: 0,
|
||||||
stop_execution: None,
|
stop_execution: None,
|
||||||
empty: true,
|
empty: true,
|
||||||
accurate_unmap: false,
|
|
||||||
interval_filter: IntervalSnapshotFilters::new(),
|
interval_filter: IntervalSnapshotFilters::new(),
|
||||||
auto_reset: true,
|
auto_reset: true,
|
||||||
}
|
}
|
||||||
@ -206,7 +204,6 @@ impl SnapshotModule {
|
|||||||
mmap_limit: 0,
|
mmap_limit: 0,
|
||||||
stop_execution: None,
|
stop_execution: None,
|
||||||
empty: true,
|
empty: true,
|
||||||
accurate_unmap: false,
|
|
||||||
interval_filter,
|
interval_filter,
|
||||||
auto_reset: true,
|
auto_reset: true,
|
||||||
}
|
}
|
||||||
@ -225,16 +222,11 @@ impl SnapshotModule {
|
|||||||
mmap_limit,
|
mmap_limit,
|
||||||
stop_execution: Some(stop_execution),
|
stop_execution: Some(stop_execution),
|
||||||
empty: true,
|
empty: true,
|
||||||
accurate_unmap: false,
|
|
||||||
interval_filter: IntervalSnapshotFilters::new(),
|
interval_filter: IntervalSnapshotFilters::new(),
|
||||||
auto_reset: true,
|
auto_reset: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn use_accurate_unmapping(&mut self) {
|
|
||||||
self.accurate_unmap = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn use_manual_reset(&mut self) {
|
pub fn use_manual_reset(&mut self) {
|
||||||
self.auto_reset = false;
|
self.auto_reset = false;
|
||||||
}
|
}
|
||||||
@ -583,10 +575,13 @@ impl SnapshotModule {
|
|||||||
found
|
found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Unmap is allowed if it is not part of the pre-snapshot region. maybe check if it's part
|
||||||
|
/// of qemu's guest memory or not?
|
||||||
pub fn is_unmap_allowed(&mut self, start: GuestAddr, mut size: usize) -> bool {
|
pub fn is_unmap_allowed(&mut self, start: GuestAddr, mut size: usize) -> bool {
|
||||||
if size % SNAPSHOT_PAGE_SIZE != 0 {
|
if size % SNAPSHOT_PAGE_SIZE != 0 {
|
||||||
size = size + (SNAPSHOT_PAGE_SIZE - size % SNAPSHOT_PAGE_SIZE);
|
size = size + (SNAPSHOT_PAGE_SIZE - size % SNAPSHOT_PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.maps
|
self.maps
|
||||||
.tree
|
.tree
|
||||||
.query(start..(start + (size as GuestAddr)))
|
.query(start..(start + (size as GuestAddr)))
|
||||||
@ -803,9 +798,8 @@ where
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.accurate_unmap {
|
|
||||||
emulator_modules.pre_syscalls(Hook::Function(filter_mmap_snapshot::<ET, I, S>));
|
emulator_modules.pre_syscalls(Hook::Function(filter_mmap_snapshot::<ET, I, S>));
|
||||||
}
|
|
||||||
emulator_modules.post_syscalls(Hook::Function(trace_mmap_snapshot::<ET, I, S>));
|
emulator_modules.post_syscalls(Hook::Function(trace_mmap_snapshot::<ET, I, S>));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -870,6 +864,7 @@ pub fn trace_write_n_snapshot<ET, I, S>(
|
|||||||
h.access(addr, size);
|
h.access(addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Do not consider munmap syscalls that are not allowed
|
||||||
#[expect(clippy::too_many_arguments)]
|
#[expect(clippy::too_many_arguments)]
|
||||||
pub fn filter_mmap_snapshot<ET, I, S>(
|
pub fn filter_mmap_snapshot<ET, I, S>(
|
||||||
_qemu: Qemu,
|
_qemu: Qemu,
|
||||||
@ -896,6 +891,7 @@ where
|
|||||||
return SyscallHookResult::new(Some(0));
|
return SyscallHookResult::new(Some(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SyscallHookResult::new(None)
|
SyscallHookResult::new(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1007,7 +1003,7 @@ where
|
|||||||
}
|
}
|
||||||
} else if sys_const == SYS_munmap {
|
} else if sys_const == SYS_munmap {
|
||||||
let h = emulator_modules.get_mut::<SnapshotModule>().unwrap();
|
let h = emulator_modules.get_mut::<SnapshotModule>().unwrap();
|
||||||
if !h.accurate_unmap && !h.is_unmap_allowed(a0, a1 as usize) {
|
if h.is_unmap_allowed(a0, a1 as usize) {
|
||||||
h.remove_mapped(a0, a1 as usize);
|
h.remove_mapped(a0, a1 as usize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,11 +96,13 @@ impl CPU {
|
|||||||
page as GuestVirtAddr,
|
page as GuestVirtAddr,
|
||||||
attrs.as_mut_ptr(),
|
attrs.as_mut_ptr(),
|
||||||
);
|
);
|
||||||
|
let mask = Qemu::get_unchecked().target_page_mask();
|
||||||
|
let offset = vaddr & (mask as GuestVirtAddr);
|
||||||
#[expect(clippy::cast_sign_loss)]
|
#[expect(clippy::cast_sign_loss)]
|
||||||
if paddr == (-1i64 as GuestPhysAddr) {
|
if paddr == (-1i64 as GuestPhysAddr) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(paddr)
|
Some(paddr + offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -180,11 +182,6 @@ impl CPU {
|
|||||||
|
|
||||||
#[expect(clippy::unused_self)]
|
#[expect(clippy::unused_self)]
|
||||||
impl Qemu {
|
impl Qemu {
|
||||||
#[must_use]
|
|
||||||
pub fn guest_page_size(&self) -> usize {
|
|
||||||
4096
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write a value to a physical guest address, including ROM areas.
|
/// Write a value to a physical guest address, including ROM areas.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
@ -313,6 +310,11 @@ impl Qemu {
|
|||||||
pub fn target_page_size(&self) -> usize {
|
pub fn target_page_size(&self) -> usize {
|
||||||
unsafe { libafl_qemu_sys::qemu_target_page_size() }
|
unsafe { libafl_qemu_sys::qemu_target_page_size() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn target_page_mask(&self) -> usize {
|
||||||
|
unsafe { libafl_qemu_sys::qemu_target_page_mask() as usize }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QemuMemoryChunk {
|
impl QemuMemoryChunk {
|
||||||
@ -426,7 +428,7 @@ impl Iterator for PhysMemoryIter {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let start_phys_addr: GuestPhysAddr = self.cpu.get_phys_addr(*vaddr)?;
|
let start_phys_addr: GuestPhysAddr = self.cpu.get_phys_addr(*vaddr)?;
|
||||||
let phys_page_size = self.qemu.guest_page_size();
|
let phys_page_size = self.qemu.target_page_size();
|
||||||
|
|
||||||
// TODO: Turn this into a generic function
|
// TODO: Turn this into a generic function
|
||||||
let mut size_taken: usize = std::cmp::min(
|
let mut size_taken: usize = std::cmp::min(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user