diff --git a/libafl_qemu/src/emu.rs b/libafl_qemu/src/emu.rs index a4273895cb..ff2ce683c1 100644 --- a/libafl_qemu/src/emu.rs +++ b/libafl_qemu/src/emu.rs @@ -6,6 +6,7 @@ use core::{ mem::{size_of, transmute, MaybeUninit}, ptr::{addr_of, addr_of_mut, copy_nonoverlapping, null}, }; +use libc::c_int; use num_enum::{IntoPrimitive, TryFromPrimitive}; use num_traits::Num; use std::{slice::from_raw_parts, str::from_utf8_unchecked}; @@ -190,6 +191,9 @@ extern "C" { fn target_mmap(start: u64, len: u64, target_prot: i32, flags: i32, fd: i32, offset: u64) -> u64; + /// int target_mprotect(abi_ulong start, abi_ulong len, int prot); + fn target_mprotect(start: u64, len: u64, target_prot: i32) -> i32; + /// int target_munmap(abi_ulong start, abi_ulong len) fn target_munmap(start: u64, len: u64) -> i32; @@ -465,24 +469,44 @@ impl Emulator { unsafe { libafl_set_brk(brk) }; } - pub fn map_private(&self, addr: u64, size: usize, perms: MmapPerms) -> Result { - let res = unsafe { - target_mmap( - addr, - size as u64, - perms.into(), - libc::MAP_PRIVATE | libc::MAP_ANONYMOUS, - -1, - 0, - ) - }; + fn mmap(&self, addr: u64, size: usize, perms: MmapPerms, flags: c_int) -> Result { + let res = unsafe { target_mmap(addr, size as u64, perms.into(), flags, -1, 0) }; if res == 0 { - Err(format!("Failed to map {}", addr)) + Err(()) } else { Ok(res) } } + pub fn map_private(&self, addr: u64, size: usize, perms: MmapPerms) -> Result { + self.mmap( + addr, + size, + perms.into(), + libc::MAP_PRIVATE | libc::MAP_ANONYMOUS, + ) + .map_err(|_| format!("Failed to map {}", addr)) + } + + pub fn map_fixed(&self, addr: u64, size: usize, perms: MmapPerms) -> Result { + self.mmap( + addr, + size, + perms.into(), + libc::MAP_FIXED | libc::MAP_PRIVATE | libc::MAP_ANONYMOUS, + ) + .map_err(|_| format!("Failed to map {}", addr)) + } + + pub fn mprotect(&self, addr: u64, size: usize, perms: MmapPerms) -> Result<(), String> { + let res = unsafe { target_mprotect(addr, size as u64, perms.into()) }; + if res == 0 { + Ok(()) + } else { + Err(format!("Failed to mprotect {}", addr)) + } + } + pub fn unmap(&self, addr: u64, size: usize) -> Result<(), String> { if unsafe { target_munmap(addr, size as u64) } == 0 { Ok(()) @@ -774,6 +798,26 @@ pub mod pybind { } } + fn map_fixed(&self, addr: u64, size: usize, perms: i32) -> PyResult { + if let Ok(p) = MmapPerms::try_from(perms) { + self.emu + .map_fixed(addr, size, p) + .map_err(PyValueError::new_err) + } else { + Err(PyValueError::new_err("Invalid perms")) + } + } + + fn mprotect(&self, addr: u64, size: usize, perms: i32) -> PyResult<()> { + if let Ok(p) = MmapPerms::try_from(perms) { + self.emu + .mprotect(addr, size, p) + .map_err(PyValueError::new_err) + } else { + Err(PyValueError::new_err("Invalid perms")) + } + } + fn unmap(&self, addr: u64, size: usize) -> PyResult<()> { self.emu.unmap(addr, size).map_err(PyValueError::new_err) }