From d7eb3bd2347f3bd1e262a700513ab91c0124216a Mon Sep 17 00:00:00 2001 From: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com> Date: Tue, 20 May 2025 16:30:26 +0100 Subject: [PATCH] LibAFL_QEMU: Fix snapshots for large mappings (#3252) --- libafl_qemu/src/modules/usermode/snapshot.rs | 21 ++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/libafl_qemu/src/modules/usermode/snapshot.rs b/libafl_qemu/src/modules/usermode/snapshot.rs index d8d925abe1..8eacba63e6 100644 --- a/libafl_qemu/src/modules/usermode/snapshot.rs +++ b/libafl_qemu/src/modules/usermode/snapshot.rs @@ -302,13 +302,12 @@ impl SnapshotModule { } pub fn access(&mut self, addr: GuestAddr, size: usize) { - // ASSUMPTION: the access can only cross 2 pages - debug_assert!(size <= SNAPSHOT_PAGE_SIZE); - let page = addr & SNAPSHOT_PAGE_MASK; - self.page_access(page); - let second_page = (addr + size as GuestAddr - 1) & SNAPSHOT_PAGE_MASK; - if page != second_page { - self.page_access(second_page); + let start = addr & SNAPSHOT_PAGE_MASK; + let end = (addr + size as GuestAddr - 1) & SNAPSHOT_PAGE_MASK; + /* Apparently there is a performance hit to using an inclusive range */ + #[allow(clippy::range_plus_one)] + for page in (start..end + 1).step_by(SNAPSHOT_PAGE_SIZE) { + self.page_access(page); } } @@ -920,7 +919,13 @@ where match i64::from(sys_num) { SYS_read | SYS_pread64 => { let h = emulator_modules.get_mut::().unwrap(); - h.access(a1, a2 as usize); + /* + * Only note the access if the call is successful. And only mark the + * portion of the buffer which has actually been modified. + */ + if result != GuestAddr::MAX { + h.access(a1, result as usize); + } } SYS_readlinkat => { let h = emulator_modules.get_mut::().unwrap();