Skip to content

Commit

Permalink
Use filename for MmapShMemProvider (AFLplusplus#2303)
Browse files Browse the repository at this point in the history
* fixer

* comment

* a

* bb

* apple
  • Loading branch information
tokatoka authored Jun 11, 2024
1 parent 03d8d2e commit 0ed2958
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 64 deletions.
2 changes: 1 addition & 1 deletion fuzzers/libfuzzer_libpng_centralized/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ which = "4.4"

[dependencies]
libafl = { path = "../../libafl/", features = ["std", "derive", "rand_trait", "fork", "prelude", "gzip", "regex", "scalability_introspection"] }
libafl_bolts = { path = "../../libafl_bolts/" }
libafl_bolts = { path = "../../libafl_bolts/", features = ["errors_backtrace"] }
libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_hitcounts", "libfuzzer"] }
# TODO Include it only when building cc
libafl_cc = { path = "../../libafl_cc/" }
Expand Down
3 changes: 2 additions & 1 deletion fuzzers/libfuzzer_libpng_norestart/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ cc = { version = "1.0", features = ["parallel"] }
which = "4.4"

[dependencies]
env_logger = "0.10"
libafl = { path = "../../libafl/" }
libafl_bolts = { path = "../../libafl_bolts/" }
libafl_bolts = { path = "../../libafl_bolts/", features = ["errors_backtrace"] }
libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_hitcounts", "libfuzzer"] }
# TODO Include it only when building cc
libafl_cc = { path = "../../libafl_cc/" }
Expand Down
14 changes: 2 additions & 12 deletions fuzzers/libfuzzer_libpng_norestart/Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,6 @@ wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
tar -xvf v1.6.37.tar.gz
'''

# Compilers
[tasks.cxx]
linux_alias = "cxx_unix"
mac_alias = "cxx_unix"
windows_alias = "unsupported"

[tasks.cxx_unix]
command = "cargo"
args = ["build" , "--profile", "${PROFILE}"]

[tasks.cc]
linux_alias = "cc_unix"
mac_alias = "cc_unix"
Expand All @@ -61,7 +51,7 @@ cd libpng-1.6.37 && ./configure --enable-shared=no --with-pic=yes --enable-hardw
cd "${PROJECT_DIR}"
make -C libpng-1.6.37 CC="${CARGO_TARGET_DIR}/${PROFILE_DIR}/libafl_cc" CXX="${CARGO_TARGET_DIR}/${PROFILE_DIR}/libafl_cxx"
'''
dependencies = [ "libpng", "cxx", "cc" ]
dependencies = [ "libpng", "cc" ]


# Harness
Expand All @@ -73,7 +63,7 @@ windows_alias = "unsupported"
[tasks.fuzzer_unix]
command = "${CARGO_TARGET_DIR}/${PROFILE_DIR}/libafl_cxx"
args = ["${PROJECT_DIR}/harness.cc", "${PROJECT_DIR}/libpng-1.6.37/.libs/libpng16.a", "-I", "${PROJECT_DIR}/libpng-1.6.37/", "-o", "${FUZZER_NAME}", "-lm", "-lz"]
dependencies = [ "lib", "cxx", "cc" ]
dependencies = [ "lib", "cc" ]

# Run the fuzzer
[tasks.run]
Expand Down
6 changes: 3 additions & 3 deletions fuzzers/libfuzzer_libpng_norestart/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use libafl::{
use libafl_bolts::{
core_affinity::Cores,
rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider},
shmem::{MmapShMemProvider, ShMemProvider},
tuples::{tuple_list, Merge},
AsSlice,
};
Expand Down Expand Up @@ -142,7 +142,7 @@ pub extern "C" fn libafl_main() {
// Needed only on no_std
// unsafe { RegistryBuilder::register::<Tokens>(); }
let opt = Opt::parse();

env_logger::init();
let broker_port = opt.broker_port;
let cores = opt.cores;

Expand All @@ -152,7 +152,7 @@ pub extern "C" fn libafl_main() {
opt.reload_corpus
);

let shmem_provider = StdShMemProvider::new().expect("Failed to init shared memory");
let shmem_provider = MmapShMemProvider::new().expect("Failed to init shared memory");

let monitor = OnDiskTOMLMonitor::new(
"./fuzzer_stats.toml",
Expand Down
127 changes: 85 additions & 42 deletions libafl_bolts/src/shmem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -644,13 +644,14 @@ pub mod unix_shmem {

#[cfg(all(unix, feature = "std", not(target_os = "android")))]
mod default {
#[cfg(target_vendor = "apple")]
use alloc::string::ToString;
use core::{
ffi::CStr,
ops::{Deref, DerefMut},
ptr, slice,
};
use std::{io::Write, process};
use std::process;

use libc::{
c_int, c_uchar, close, ftruncate, mmap, munmap, shm_open, shm_unlink, shmat, shmctl,
Expand All @@ -663,13 +664,7 @@ pub mod unix_shmem {
Error,
};

// This is macOS's limit
// https://stackoverflow.com/questions/38049068/osx-shm-open-returns-enametoolong
#[cfg(target_vendor = "apple")]
const MAX_MMAP_FILENAME_LEN: usize = 31;

#[cfg(not(target_vendor = "apple"))]
const MAX_MMAP_FILENAME_LEN: usize = 256;
const MAX_MMAP_FILENAME_LEN: usize = 20;

/// Mmap-based The sharedmap impl for unix using [`shm_open`] and [`mmap`].
/// Default on `MacOS` and `iOS`, where we need a central point to unmap
Expand All @@ -691,22 +686,27 @@ pub mod unix_shmem {

impl MmapShMem {
/// Create a new [`MmapShMem`]
/// This will *NOT* automatically delete the shmem files, meaning that it's user's responsibility to delete all `/dev/shm/libafl_*` after fuzzing
pub fn new(map_size: usize, rand_id: u32) -> Result<Self, Error> {
unsafe {
let full_file_name = format!("/libafl_{}_{}", process::id(), rand_id);
let mut filename_path = [0_u8; MAX_MMAP_FILENAME_LEN];
write!(
&mut filename_path[..MAX_MMAP_FILENAME_LEN - 1],
"/libafl_{}_{}",
filename_path
.copy_from_slice(&full_file_name.as_bytes()[..MAX_MMAP_FILENAME_LEN]);
filename_path[MAX_MMAP_FILENAME_LEN - 1] = 0; // Null terminate!
log::info!(
"{} Creating shmem {} {:#?}",
map_size,
process::id(),
rand_id
)?;

filename_path
);
/* create the shared memory segment as if it was a file */
let shm_fd = shm_open(
filename_path.as_ptr() as *const _,
libc::O_CREAT | libc::O_RDWR | libc::O_EXCL,
0o600,
);

if shm_fd == -1 {
return Err(Error::last_os_error(format!(
"Failed to shm_open map with id {filename_path:?}",
Expand Down Expand Up @@ -738,42 +738,84 @@ pub mod unix_shmem {
)));
}

// Apple uses it for served shmem provider, which uses fd
// Others will just use filename

#[cfg(target_vendor = "apple")]
let id = ShMemId::from_string(&format!("{shm_fd}"));
#[cfg(not(target_vendor = "apple"))]
let id = ShMemId::from_string(core::str::from_utf8(&filename_path)?);

Ok(Self {
filename_path: Some(filename_path),
map: map as *mut u8,
map_size,
shm_fd,
id: ShMemId::from_string(&format!("{shm_fd}")),
id,
})
}
}

#[allow(clippy::unnecessary_wraps)]
fn shmem_from_id_and_size(id: ShMemId, map_size: usize) -> Result<Self, Error> {
unsafe {
let shm_fd: i32 = id.to_string().parse().unwrap();

/* map the shared memory segment to the address space of the process */
let map = mmap(
ptr::null_mut(),
map_size,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_SHARED,
shm_fd,
0,
);
if map == libc::MAP_FAILED || map.is_null() {
close(shm_fd);
return Err(Error::last_os_error(format!(
"mmap() failed for map with fd {shm_fd:?}"
)));
}
#[cfg(target_vendor = "apple")]
let (map, shm_fd) = {
let shm_fd: i32 = id.to_string().parse().unwrap();
let map = mmap(
ptr::null_mut(),
map_size,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_SHARED,
shm_fd,
0,
);
(map, shm_fd)
};

#[cfg(not(target_vendor = "apple"))]
let (map, shm_fd) = {
let mut filename_path = [0_u8; MAX_MMAP_FILENAME_LEN];
filename_path.copy_from_slice(&id.id);

/* attach to the shared memory segment as if it was a file */
let shm_fd =
shm_open(filename_path.as_ptr() as *const _, libc::O_RDWR, 0o600);
if shm_fd == -1 {
log::info!(
"Trying to attach to {:#?} but failed {}",
filename_path,
process::id()
);
return Err(Error::last_os_error(format!(
"Failed to shm_open map with id {filename_path:?}",
)));
}
/* map the shared memory segment to the address space of the process */
let map = mmap(
ptr::null_mut(),
map_size,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_SHARED,
shm_fd,
0,
);
if map == libc::MAP_FAILED || map.is_null() {
close(shm_fd);
return Err(Error::last_os_error(format!(
"mmap() failed for map with fd {shm_fd:?}"
)));
}
(map, shm_fd)
};

Ok(Self {
filename_path: None,
map: map as *mut u8,
map_size,
shm_fd,
id: ShMemId::from_string(&format!("{shm_fd}")),
id,
})
}
}
Expand All @@ -788,9 +830,7 @@ pub mod unix_shmem {
/// A [`ShMemProvider`] which uses [`shm_open`] and [`mmap`] to provide shared memory mappings.
#[cfg(unix)]
#[derive(Clone, Debug)]
pub struct MmapShMemProvider {
rand: StdRand,
}
pub struct MmapShMemProvider {}

unsafe impl Send for MmapShMemProvider {}

Expand All @@ -807,12 +847,11 @@ pub mod unix_shmem {
type ShMem = MmapShMem;

fn new() -> Result<Self, Error> {
Ok(Self {
rand: StdRand::new(),
})
Ok(Self {})
}
fn new_shmem(&mut self, map_size: usize) -> Result<Self::ShMem, Error> {
let id = self.rand.next() as u32;
let mut rand = StdRand::with_seed(crate::rands::random_seed());
let id = rand.next() as u32;
MmapShMem::new(map_size, id)
}

Expand Down Expand Up @@ -872,9 +911,13 @@ pub mod unix_shmem {
);

// None in case we didn't [`shm_open`] this ourselves, but someone sent us the FD.
if let Some(filename_path) = self.filename_path {
shm_unlink(filename_path.as_ptr() as *const _);
}
// log::info!("Dropping {:#?}", self.filename_path);
// if let Some(filename_path) = self.filename_path {
// shm_unlink(filename_path.as_ptr() as *const _);
// }
// We cannot shm_unlink here!
// unlike unix common shmem we don't have refcounter.
// so there's no guarantee that there's no other process still using it.
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions libafl_frida/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,11 @@ fn main() {
);

// std::fs::write("compiler_output.txt", output_str.clone()).expect("Unable to write file");
assert!(output.status.success(),
"Failed to link test_harness.dll\n {:?}",
output_str.as_str()
);
assert!(
output.status.success(),
"Failed to link test_harness.dll\n {:?}",
output_str.as_str()
);
} else {
let compiler = cc::Build::new()
.cpp(true)
Expand Down
1 change: 0 additions & 1 deletion libafl_targets/src/sancov_pcguard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use libafl::executors::{hooks::ExecutorHook, HasObservers};
))]
use crate::coverage::EDGES_MAP;
use crate::coverage::MAX_EDGES_FOUND;

#[cfg(feature = "sancov_ngram4")]
#[allow(unused)]
use crate::EDGES_MAP_SIZE_IN_USE;
Expand Down

0 comments on commit 0ed2958

Please sign in to comment.