Make MmapShMem::new take a AsRef<Path> instead of a byte array (#2742)

* Make MmapShMem take a AsRef<Path> instead of a byte array

* Make the test actually test if MmapShMem::persist works

* 0.14.1 (#2698)

* 0.14.1

* fixer

* don't build nyx

---------

Co-authored-by: Dominik Maier <domenukk@gmail.com>

* Intel PT minor fixes/improvements (#2724)

* waitpid_filtered to ignore SIGWINCH

* Fix warnings unused manifest key: *.version

* Add export_raw feature to libafl_intelpt

* derive Debug for IntelPTHook

* Clippy

* Update target program ELF offsets

* Add comment to KVM pt_mode check

* refactor

* Add intel_pt_export_raw feature in libafl

* map_error instead of unwrap

* borrow checker friendly join_split_trace

and copy trace before deocde to prevent decoding failures

* Set ip_filters (also) with builder

* Move trace to file

* Fix Cargo.toml docs

* Ignore blocks with no instruction

most likely they are filtered out

* Fix assertion in snapshot module for pages that are equal to SNAPSHOT_PAGE_SIZE (#2738)

Co-authored-by: Scott Powell <scott.powell@str.us>

* Remove non_basic const_panic features (#2739)

* Remove non_basic const_panic features

* fmt

* Make FridaInProcessExecutor compatible with TargetBytesConverter, decouple input type from FridaRuntime trait (#2741)

* decouple input type from FridaRuntime trait

* fmt

* fmt2

* remove HasTargetBytes requirement from FridaInProcessExecutor

* fmt

* restore comment

* fix clippy comment error

* adding entry to MIGRATION.md

* only running persist test on unix

* move cfg dependent imports to function

---------

Co-authored-by: Dongjia "toka" Zhang <tokazerkje@outlook.com>
Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: Marco C. <46560192+Marcondiro@users.noreply.github.com>
Co-authored-by: Scott <55210664+scottmpowell@users.noreply.github.com>
Co-authored-by: Scott Powell <scott.powell@str.us>
Co-authored-by: jejuisland87654 <jejuisland87654@gmail.com>
This commit is contained in:
Valentin Huber 2024-12-04 00:56:24 +01:00 committed by GitHub
parent 85796f952b
commit 2758a1c2fb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 73 additions and 34 deletions

View File

@ -4,3 +4,6 @@
# 0.14.0 -> 0.14.1 # 0.14.0 -> 0.14.1
- Removed `with_observers` from `Executor` trait. - Removed `with_observers` from `Executor` trait.
- `MmapShMemProvider::new_shmem_persistent` has been removed in favour of `MmapShMem::persist`. You probably want to do something like this: `let shmem = MmapShMemProvider::new()?.new_shmem(size)?.persist()?;` - `MmapShMemProvider::new_shmem_persistent` has been removed in favour of `MmapShMem::persist`. You probably want to do something like this: `let shmem = MmapShMemProvider::new()?.new_shmem(size)?.persist()?;`
# 0.14.1 -> 0.14.2
- `MmapShMem::new` and `MmapShMemProvider::new_shmem_with_id` now take `AsRef<Path>` instead of a byte array for the filename/id.

View File

@ -656,7 +656,7 @@ pub mod unix_shmem {
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
ptr, slice, ptr, slice,
}; };
use std::{io, process}; use std::{io, path::Path, process};
use libc::{ use libc::{
c_int, c_uchar, close, fcntl, ftruncate, mmap, munmap, shm_open, shm_unlink, shmat, c_int, c_uchar, close, fcntl, ftruncate, mmap, munmap, shm_open, shm_unlink, shmat,
@ -692,26 +692,29 @@ pub mod unix_shmem {
impl MmapShMem { impl MmapShMem {
/// Create a new [`MmapShMem`] /// Create a new [`MmapShMem`]
/// ///
/// At most [`MAX_MMAP_FILENAME_LEN`] - 2 values from filename will be used. Do not include any characters that are illegal as filenames /// At most [`MAX_MMAP_FILENAME_LEN`] - 2 bytes from filename will be used.
/// ///
/// This will *NOT* automatically delete the shmem files, meaning that it's user's responsibility to delete them after fuzzing /// This will *NOT* automatically delete the shmem files, meaning that it's user's responsibility to delete them after fuzzing
pub fn new(map_size: usize, filename: &[u8]) -> Result<Self, Error> { pub fn new(map_size: usize, filename: impl AsRef<Path>) -> Result<Self, Error> {
// # Safety let filename_bytes = filename.as_ref().as_os_str().as_encoded_bytes();
// No user-provided potentially unsafe parameters.
// FFI Calls.
unsafe {
let mut filename_path: [u8; 20] = [0_u8; MAX_MMAP_FILENAME_LEN]; let mut filename_path: [u8; 20] = [0_u8; MAX_MMAP_FILENAME_LEN];
// Keep room for the leading slash and trailing NULL. // Keep room for the leading slash and trailing NULL.
let max_copy = usize::min(filename.len(), MAX_MMAP_FILENAME_LEN - 2); let max_copy = usize::min(filename_bytes.len(), MAX_MMAP_FILENAME_LEN - 2);
filename_path[0] = b'/'; filename_path[0] = b'/';
filename_path[1..=max_copy].copy_from_slice(&filename[..max_copy]); filename_path[1..=max_copy].copy_from_slice(&filename_bytes[..max_copy]);
log::info!( log::info!(
"{} Creating shmem {} {:#?}", "{} Creating shmem {} {:?}",
map_size, map_size,
process::id(), process::id(),
filename_path filename_path
); );
// # Safety
// No user-provided potentially unsafe parameters.
// FFI Calls.
unsafe {
/* create the shared memory segment as if it was a file */ /* create the shared memory segment as if it was a file */
let shm_fd = shm_open( let shm_fd = shm_open(
filename_path.as_ptr() as *const _, filename_path.as_ptr() as *const _,
@ -942,12 +945,12 @@ pub mod unix_shmem {
impl MmapShMemProvider { impl MmapShMemProvider {
/// Create a [`MmapShMem`] with the specified size and id. /// Create a [`MmapShMem`] with the specified size and id.
/// ///
/// At most [`MAX_MMAP_FILENAME_LEN`] - 2 values from filename will be used. Do not include any characters that are illegal as filenames. /// At most [`MAX_MMAP_FILENAME_LEN`] - 2 bytes from id will be used.
#[cfg(any(unix, doc))] #[cfg(any(unix, doc))]
pub fn new_shmem_with_id( pub fn new_shmem_with_id(
&mut self, &mut self,
map_size: usize, map_size: usize,
id: &[u8], id: impl AsRef<Path>,
) -> Result<MmapShMem, Error> { ) -> Result<MmapShMem, Error> {
MmapShMem::new(map_size, id) MmapShMem::new(map_size, id)
} }
@ -974,10 +977,10 @@ pub mod unix_shmem {
fn new_shmem(&mut self, map_size: usize) -> Result<Self::ShMem, Error> { fn new_shmem(&mut self, map_size: usize) -> Result<Self::ShMem, Error> {
let mut rand = StdRand::with_seed(crate::rands::random_seed()); let mut rand = StdRand::with_seed(crate::rands::random_seed());
let id = rand.next() as u32; let id = rand.next() as u32;
let mut full_file_name = format!("/libafl_{}_{}", process::id(), id); let mut full_file_name = format!("libafl_{}_{}", process::id(), id);
// leave one byte space for the null byte. // leave one byte space for the null byte.
full_file_name.truncate(MAX_MMAP_FILENAME_LEN - 1); full_file_name.truncate(MAX_MMAP_FILENAME_LEN - 1);
MmapShMem::new(map_size, full_file_name.as_bytes()) MmapShMem::new(map_size, full_file_name)
} }
fn shmem_from_id_and_size( fn shmem_from_id_and_size(
@ -1844,27 +1847,60 @@ mod tests {
} }
#[test] #[test]
#[cfg(all(unix, not(miri)))] #[cfg(unix)]
#[cfg_attr(miri, ignore)] #[cfg_attr(miri, ignore)]
fn test_persist_shmem() -> Result<(), Error> { fn test_persist_shmem() -> Result<(), Error> {
use std::thread; use core::ffi::CStr;
use std::{
env,
process::{Command, Stdio},
string::ToString,
};
use crate::shmem::{MmapShMemProvider, ShMem as _}; use crate::shmem::{MmapShMemProvider, ShMem as _, ShMemId};
// relies on the fact that the ID in a ShMemDescription is always a string for MmapShMem
match env::var("SHMEM_SIZE") {
Ok(size) => {
let mut provider = MmapShMemProvider::new()?;
let id = ShMemId::from_string(&env::var("SHMEM_ID").unwrap());
let size = size.parse().unwrap();
let mut shmem = provider.shmem_from_id_and_size(id, size)?;
shmem[0] = 1;
}
Err(env::VarError::NotPresent) => {
let mut provider = MmapShMemProvider::new()?; let mut provider = MmapShMemProvider::new()?;
let mut shmem = provider.new_shmem(1)?.persist()?; let mut shmem = provider.new_shmem(1)?.persist()?;
shmem.fill(0); shmem.fill(0);
let description = shmem.description(); let description = shmem.description();
let handle = thread::spawn(move || -> Result<(), Error> { // call the test binary again
let mut provider = MmapShMemProvider::new()?; // with certain env variables set to prevent infinite loops
let mut shmem = provider.shmem_from_description(description)?; // and with an added arg to only run this test
shmem.as_slice_mut()[0] = 1; //
Ok(()) // a command is necessary to create the required distance between the two processes
}); // with threads/fork it works without the additional steps to persist the ShMem regardless
handle.join().unwrap()?; let status = Command::new(env::current_exe().unwrap())
assert_eq!(1, shmem.as_slice()[0]); .env(
"SHMEM_ID",
CStr::from_bytes_until_nul(description.id.as_array())
.unwrap()
.to_str()
.unwrap(),
)
.env("SHMEM_SIZE", description.size.to_string())
.arg("shmem::tests::test_persist_shmem")
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
.unwrap();
assert!(status.success());
assert_eq!(shmem[0], 1);
}
Err(e) => panic!("{e}"),
}
Ok(()) Ok(())
} }
} }