Fix snapshot reset function when brk shrunk below the snapshotted value (#2812)
* added change_brk function for correctly handling SYS_brk * we need to update h.brk with the new brk_val * map back pages if brk shrunk below the snapshotted value * fmt and clippy * use GuestAddr instead of u64 --------- Co-authored-by: Romain Malmain <romain.malmain@pm.me>
This commit is contained in:
parent
f7745155c9
commit
1a9e25145d
@ -393,6 +393,20 @@ impl SnapshotModule {
|
|||||||
|
|
||||||
log::debug!("Start restore");
|
log::debug!("Start restore");
|
||||||
|
|
||||||
|
let new_brk = qemu.get_brk();
|
||||||
|
if new_brk < self.brk {
|
||||||
|
// The heap has shrunk below the snapshotted brk value. We need to remap those pages in the target.
|
||||||
|
// The next for loop will restore their content if needed.
|
||||||
|
let aligned_new_brk = (new_brk + ((SNAPSHOT_PAGE_SIZE - 1) as GuestAddr))
|
||||||
|
& (!(SNAPSHOT_PAGE_SIZE - 1) as GuestAddr);
|
||||||
|
log::debug!("New brk ({:#x?}) < snapshotted brk ({:#x?})! Mapping back in the target {:#x?} - {:#x?}", new_brk, self.brk, aligned_new_brk, aligned_new_brk + (self.brk - aligned_new_brk));
|
||||||
|
drop(qemu.map_fixed(
|
||||||
|
aligned_new_brk,
|
||||||
|
(self.brk - aligned_new_brk) as usize,
|
||||||
|
MmapPerms::ReadWrite,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
for acc in &mut self.accesses {
|
for acc in &mut self.accesses {
|
||||||
unsafe { &mut (*acc.get()) }.dirty.retain(|page| {
|
unsafe { &mut (*acc.get()) }.dirty.retain(|page| {
|
||||||
if let Some(info) = self.pages.get_mut(page) {
|
if let Some(info) = self.pages.get_mut(page) {
|
||||||
@ -524,7 +538,12 @@ impl SnapshotModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn change_mapped(&mut self, start: GuestAddr, mut size: usize, perms: Option<MmapPerms>) {
|
pub fn change_mapped_perms(
|
||||||
|
&mut self,
|
||||||
|
start: GuestAddr,
|
||||||
|
mut size: usize,
|
||||||
|
perms: Option<MmapPerms>,
|
||||||
|
) {
|
||||||
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);
|
||||||
}
|
}
|
||||||
@ -851,18 +870,8 @@ where
|
|||||||
h.access(a0, a1 as usize);
|
h.access(a0, a1 as usize);
|
||||||
}
|
}
|
||||||
SYS_brk => {
|
SYS_brk => {
|
||||||
let h = emulator_modules.get_mut::<SnapshotModule>().unwrap();
|
// We don't handle brk here. It is handled in the reset function only when it's needed.
|
||||||
if h.brk != result && result != 0 && result > h.initial_brk {
|
log::debug!("New brk ({:#x?}) received.", result);
|
||||||
/* brk has changed, and it doesn't shrink below initial_brk. We change mapping from the snapshotted initial brk address to the new target_brk
|
|
||||||
* If no brk mapping has been made until now, change_mapped won't change anything and just create a new mapping.
|
|
||||||
* It is safe to assume RW perms here
|
|
||||||
*/
|
|
||||||
h.change_mapped(
|
|
||||||
h.initial_brk,
|
|
||||||
(result - h.initial_brk) as usize,
|
|
||||||
Some(MmapPerms::ReadWrite),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// mmap syscalls
|
// mmap syscalls
|
||||||
sys_const => {
|
sys_const => {
|
||||||
@ -898,7 +907,7 @@ where
|
|||||||
} else if sys_const == SYS_mprotect {
|
} else if sys_const == SYS_mprotect {
|
||||||
if let Ok(prot) = MmapPerms::try_from(a2 as i32) {
|
if let Ok(prot) = MmapPerms::try_from(a2 as i32) {
|
||||||
let h = emulator_modules.get_mut::<SnapshotModule>().unwrap();
|
let h = emulator_modules.get_mut::<SnapshotModule>().unwrap();
|
||||||
h.change_mapped(a0, a1 as usize, Some(prot));
|
h.change_mapped_perms(a0, a1 as usize, Some(prot));
|
||||||
}
|
}
|
||||||
} 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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user