diff --git a/fuzzers/backtrace_baby_fuzzers/c_code_with_fork_executor/src/main.rs b/fuzzers/backtrace_baby_fuzzers/c_code_with_fork_executor/src/main.rs index 49323a435a..80df367be7 100644 --- a/fuzzers/backtrace_baby_fuzzers/c_code_with_fork_executor/src/main.rs +++ b/fuzzers/backtrace_baby_fuzzers/c_code_with_fork_executor/src/main.rs @@ -18,8 +18,9 @@ use libafl::{ }; use libafl_bolts::{ current_nanos, + ownedref::OwnedRefMut, rands::StdRand, - shmem::{ShMem, ShMemProvider, StdShMemProvider}, + shmem::{ShMemProvider, StdShMemProvider}, tuples::tuple_list, AsSlice, }; @@ -47,10 +48,10 @@ pub fn main() { // Create an observation channel using the signals map let observer = unsafe { ConstMapObserver::::from_mut_ptr("signals", map_ptr) }; // Create a stacktrace observer - let mut bt = shmem_provider.new_shmem_object::>().unwrap(); + let mut bt = shmem_provider.new_on_shmem::>(None).unwrap(); let bt_observer = BacktraceObserver::new( "BacktraceObserver", - unsafe { bt.as_object_mut::>() }, + unsafe { OwnedRefMut::from_shmem(&mut bt) }, libafl::observers::HarnessType::Child, ); diff --git a/fuzzers/backtrace_baby_fuzzers/c_code_with_inprocess_executor/src/main.rs b/fuzzers/backtrace_baby_fuzzers/c_code_with_inprocess_executor/src/main.rs index 48d3a28d72..295ddc4762 100644 --- a/fuzzers/backtrace_baby_fuzzers/c_code_with_inprocess_executor/src/main.rs +++ b/fuzzers/backtrace_baby_fuzzers/c_code_with_inprocess_executor/src/main.rs @@ -37,10 +37,8 @@ pub fn main() { // Create an observation channel using the signals map let observer = unsafe { ConstMapObserver::::from_mut_ptr("signals", array_ptr) }; // Create a stacktrace observer - let mut bt = None; - let bt_observer = BacktraceObserver::new( + let bt_observer = BacktraceObserver::owned( "BacktraceObserver", - &mut bt, libafl::observers::HarnessType::InProcess, ); diff --git a/fuzzers/backtrace_baby_fuzzers/rust_code_with_fork_executor/src/main.rs b/fuzzers/backtrace_baby_fuzzers/rust_code_with_fork_executor/src/main.rs index 1f5c34e2ed..193f8d101c 100644 --- a/fuzzers/backtrace_baby_fuzzers/rust_code_with_fork_executor/src/main.rs +++ b/fuzzers/backtrace_baby_fuzzers/rust_code_with_fork_executor/src/main.rs @@ -20,6 +20,7 @@ use libafl::{ }; use libafl_bolts::{ current_nanos, + ownedref::OwnedRefMut, rands::StdRand, shmem::{unix_shmem, ShMem, ShMemProvider}, tuples::tuple_list, @@ -32,7 +33,7 @@ pub fn main() { let mut signals = shmem_provider.new_shmem(16).unwrap(); let signals_len = signals.len(); let signals_ptr = signals.as_mut_slice().as_mut_ptr(); - let mut bt = shmem_provider.new_shmem_object::>().unwrap(); + let mut bt = shmem_provider.new_on_shmem::>(None).unwrap(); let signals_set = |idx: usize| { unsafe { write(signals_ptr.add(idx), 1) }; @@ -69,7 +70,7 @@ pub fn main() { // Create a stacktrace observer let bt_observer = BacktraceObserver::new( "BacktraceObserver", - unsafe { bt.as_object_mut::>() }, + unsafe { OwnedRefMut::from_shmem(&mut bt) }, libafl::observers::HarnessType::Child, ); diff --git a/fuzzers/backtrace_baby_fuzzers/rust_code_with_inprocess_executor/src/main.rs b/fuzzers/backtrace_baby_fuzzers/rust_code_with_inprocess_executor/src/main.rs index 5970b7104b..a76726f7b1 100644 --- a/fuzzers/backtrace_baby_fuzzers/rust_code_with_inprocess_executor/src/main.rs +++ b/fuzzers/backtrace_baby_fuzzers/rust_code_with_inprocess_executor/src/main.rs @@ -61,10 +61,8 @@ pub fn main() { // Create an observation channel using the signals map let observer = unsafe { StdMapObserver::from_mut_ptr("signals", SIGNALS_PTR, SIGNALS.len()) }; // Create a stacktrace observer to add the observers tuple - let mut bt = None; - let bt_observer = BacktraceObserver::new( + let bt_observer = BacktraceObserver::owned( "BacktraceObserver", - &mut bt, libafl::observers::HarnessType::InProcess, ); diff --git a/fuzzers/fuzzbench_fork_qemu/src/fuzzer.rs b/fuzzers/fuzzbench_fork_qemu/src/fuzzer.rs index 0970d5a544..c4431a4dfd 100644 --- a/fuzzers/fuzzbench_fork_qemu/src/fuzzer.rs +++ b/fuzzers/fuzzbench_fork_qemu/src/fuzzer.rs @@ -209,9 +209,7 @@ fn fuzz( let edges = edges_shmem.as_mut_slice(); unsafe { EDGES_MAP_PTR = edges.as_mut_ptr() }; - let mut cmp_shmem = shmem_provider - .new_shmem(core::mem::size_of::()) - .unwrap(); + let mut cmp_shmem = shmem_provider.uninit_on_shmem::().unwrap(); let cmplog = cmp_shmem.as_mut_slice(); // Beginning of a page should be properly aligned. diff --git a/fuzzers/fuzzbench_forkserver/src/main.rs b/fuzzers/fuzzbench_forkserver/src/main.rs index 1bac2f050c..ca4bcec46e 100644 --- a/fuzzers/fuzzbench_forkserver/src/main.rs +++ b/fuzzers/fuzzbench_forkserver/src/main.rs @@ -34,6 +34,7 @@ use libafl::{ }; use libafl_bolts::{ current_nanos, current_time, + ownedref::OwnedRefMut, rands::StdRand, shmem::{ShMem, ShMemProvider, UnixShMemProvider}, tuples::{tuple_list, Merge}, @@ -204,6 +205,7 @@ pub fn main() { } /// The actual fuzzer +#[allow(clippy::too_many_arguments)] fn fuzz( corpus_dir: PathBuf, objective_dir: PathBuf, @@ -340,12 +342,10 @@ fn fuzz( if let Some(exec) = &cmplog_exec { // The cmplog map shared between observer and executor - let mut cmplog_shmem = shmem_provider - .new_shmem(core::mem::size_of::()) - .unwrap(); + let mut cmplog_shmem = shmem_provider.uninit_on_shmem::().unwrap(); // let the forkserver know the shmid cmplog_shmem.write_to_env("__AFL_CMPLOG_SHM_ID").unwrap(); - let cmpmap = unsafe { cmplog_shmem.as_object_mut::() }; + let cmpmap = unsafe { OwnedRefMut::::from_shmem(&mut cmplog_shmem) }; let cmplog_observer = StdCmpValuesObserver::new("cmplog", cmpmap, true); diff --git a/fuzzers/fuzzbench_forkserver_cmplog/src/main.rs b/fuzzers/fuzzbench_forkserver_cmplog/src/main.rs index c2f64560ec..862ecf4754 100644 --- a/fuzzers/fuzzbench_forkserver_cmplog/src/main.rs +++ b/fuzzers/fuzzbench_forkserver_cmplog/src/main.rs @@ -34,6 +34,7 @@ use libafl::{ }; use libafl_bolts::{ current_nanos, current_time, + ownedref::OwnedRefMut, rands::StdRand, shmem::{ShMem, ShMemProvider, UnixShMemProvider}, tuples::{tuple_list, Merge}, @@ -207,6 +208,7 @@ pub fn main() { } /// The actual fuzzer +#[allow(clippy::too_many_arguments)] fn fuzz( corpus_dir: PathBuf, objective_dir: PathBuf, @@ -344,12 +346,10 @@ fn fuzz( if let Some(exec) = &cmplog_exec { // The cmplog map shared between observer and executor - let mut cmplog_shmem = shmem_provider - .new_shmem(core::mem::size_of::()) - .unwrap(); + let mut cmplog_shmem = shmem_provider.uninit_on_shmem::().unwrap(); // let the forkserver know the shmid cmplog_shmem.write_to_env("__AFL_CMPLOG_SHM_ID").unwrap(); - let cmpmap = unsafe { cmplog_shmem.as_object_mut::() }; + let cmpmap = unsafe { OwnedRefMut::from_shmem(&mut cmplog_shmem) }; let cmplog_observer = AFLppCmpLogObserver::new("cmplog", cmpmap, true); diff --git a/libafl/src/observers/cmp.rs b/libafl/src/observers/cmp.rs index 746f33ea6e..0c77f9aaa6 100644 --- a/libafl/src/observers/cmp.rs +++ b/libafl/src/observers/cmp.rs @@ -333,11 +333,11 @@ where { /// Creates a new [`StdCmpObserver`] with the given name and map. #[must_use] - pub fn new(name: &'static str, map: &'a mut CM, add_meta: bool) -> Self { + pub fn new(name: &'static str, map: OwnedRefMut<'a, CM>, add_meta: bool) -> Self { Self { name: name.to_string(), size: None, - cmp_map: OwnedRefMut::Ref(map), + cmp_map: map, add_meta, data: M::Data::default(), phantom: PhantomData, @@ -347,11 +347,16 @@ where /// Creates a new [`StdCmpObserver`] with the given name, map, and auxiliary data used to /// populate metadata #[must_use] - pub fn with_data(name: &'static str, map: &'a mut CM, add_meta: bool, data: M::Data) -> Self { + pub fn with_data( + name: &'static str, + cmp_map: OwnedRefMut<'a, CM>, + add_meta: bool, + data: M::Data, + ) -> Self { Self { name: name.to_string(), size: None, - cmp_map: OwnedRefMut::Ref(map), + cmp_map, add_meta, data, phantom: PhantomData, @@ -362,14 +367,14 @@ where #[must_use] pub fn with_size( name: &'static str, - map: &'a mut CM, + cmp_map: OwnedRefMut<'a, CM>, add_meta: bool, - size: &'a mut usize, + size: OwnedRefMut<'a, usize>, ) -> Self { Self { name: name.to_string(), - size: Some(OwnedRefMut::Ref(size)), - cmp_map: OwnedRefMut::Ref(map), + size: Some(size), + cmp_map, add_meta, data: M::Data::default(), phantom: PhantomData, @@ -381,15 +386,15 @@ where #[must_use] pub fn with_size_data( name: &'static str, - map: &'a mut CM, + cmp_map: OwnedRefMut<'a, CM>, add_meta: bool, data: M::Data, - size: &'a mut usize, + size: OwnedRefMut<'a, usize>, ) -> Self { Self { name: name.to_string(), - size: Some(OwnedRefMut::Ref(size)), - cmp_map: OwnedRefMut::Ref(map), + size: Some(size), + cmp_map, add_meta, data, phantom: PhantomData, diff --git a/libafl/src/observers/stacktrace.rs b/libafl/src/observers/stacktrace.rs index ae63b27981..b1d2ee1719 100644 --- a/libafl/src/observers/stacktrace.rs +++ b/libafl/src/observers/stacktrace.rs @@ -127,12 +127,12 @@ impl<'a> BacktraceObserver<'a> { #[must_use] pub fn new( observer_name: &str, - backtrace_hash: &'a mut Option, + backtrace_hash: OwnedRefMut<'a, Option>, harness_type: HarnessType, ) -> Self { Self { observer_name: observer_name.to_string(), - hash: OwnedRefMut::Ref(backtrace_hash), + hash: backtrace_hash, harness_type, } } @@ -142,17 +142,23 @@ impl<'a> BacktraceObserver<'a> { #[must_use] pub fn new( observer_name: &str, - backtrace_hash: &'a mut Option, + backtrace_hash: OwnedRefMut<'a, Option>, harness_type: HarnessType, ) -> Self { init_ignored_frames!("rust", "cpp", "go"); Self { observer_name: observer_name.to_string(), - hash: OwnedRefMut::Ref(backtrace_hash), + hash: backtrace_hash, harness_type, } } + /// Creates a new [`BacktraceObserver`] with the given name, owning a new `backtrace_hash` variable. + #[must_use] + pub fn owned(observer_name: &str, harness_type: HarnessType) -> Self { + Self::new(observer_name, OwnedRefMut::owned(None), harness_type) + } + /// Updates the hash value of this observer. fn update_hash(&mut self, hash: u64) { *self.hash.as_mut() = Some(hash); diff --git a/libafl/src/observers/value.rs b/libafl/src/observers/value.rs index e2ed1cd745..d8610486c2 100644 --- a/libafl/src/observers/value.rs +++ b/libafl/src/observers/value.rs @@ -40,10 +40,10 @@ where { /// Creates a new [`ValueObserver`] with the given name. #[must_use] - pub fn new(name: &'static str, value: &'a T) -> Self { + pub fn new(name: &'static str, value: OwnedRef<'a, T>) -> Self { Self { name: name.to_string(), - value: OwnedRef::Ref(value), + value, } } @@ -65,6 +65,7 @@ where T: Clone, { match self.value { + OwnedRef::RefRaw(r, _) => unsafe { (*r).clone() }, OwnedRef::Ref(r) => r.clone(), OwnedRef::Owned(v) => *v, } @@ -119,10 +120,10 @@ where { /// Creates a new [`RefCellValueObserver`] with the given name. #[must_use] - pub fn new(name: &'static str, value: &'a RefCell) -> Self { + pub fn new(name: &'static str, value: OwnedRef<'a, RefCell>) -> Self { Self { name: name.to_string(), - value: OwnedRef::Ref(value), + value, } } @@ -147,6 +148,7 @@ where T: Clone, { match self.value { + OwnedRef::RefRaw(r, _) => unsafe { (*r).borrow().deref().clone() }, OwnedRef::Ref(r) => r.borrow().deref().clone(), OwnedRef::Owned(v) => v.borrow().clone(), } diff --git a/libafl_bolts/src/ownedref.rs b/libafl_bolts/src/ownedref.rs index de9c592838..f778f1b31e 100644 --- a/libafl_bolts/src/ownedref.rs +++ b/libafl_bolts/src/ownedref.rs @@ -10,7 +10,28 @@ use core::{clone::Clone, fmt::Debug, slice}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use crate::{AsMutSlice, AsSlice, IntoOwned, Truncate}; +use crate::{shmem::ShMem, AsMutSlice, AsSlice, IntoOwned, Truncate}; + +/// Private part of the unsafe marker, making sure this cannot be initialized directly. +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +struct UnsafeMarkerInner; + +/// A struct or enum containing this [`UnsafeMarker`] cannot directly be instantiated. +/// Usually, this means you'll have to use a constructor like `unsafe { Self::new() }` or similar. +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct UnsafeMarker(UnsafeMarkerInner); + +impl UnsafeMarker { + /// Return a new unsafe marker. + /// This usually means you're about to do something unsafe. + /// + /// # Safety + /// Instantiating an [`UnsafeMarker`] isn't unsafe, but the location you need it for + /// will likely have potential unsafety. + unsafe fn new() -> Self { + Self(UnsafeMarkerInner) + } +} impl<'a, T> Truncate for &'a [T] { fn truncate(&mut self, len: usize) { @@ -32,12 +53,54 @@ pub enum OwnedRef<'a, T> where T: 'a + ?Sized, { + /// A pointer to a type + RefRaw(*const T, UnsafeMarker), /// A ref to a type Ref(&'a T), /// An owned [`Box`] of a type Owned(Box), } +impl<'a, T> OwnedRef<'a, T> +where + T: 'a + ?Sized, +{ + /// Returns a new [`OwnedRef`], wrapping a pointer of type `T`. + /// + /// # Safety + /// The pointer needs to point to a valid object of type `T`. + /// Any use of this [`OwnedRef`] will dereference the pointer accordingly. + pub unsafe fn from_ptr(ptr: *const T) -> Self { + assert!( + !ptr.is_null(), + "Null pointer passed to OwnedRef::ref_raw constructor!" + ); + Self::RefRaw(ptr, UnsafeMarker::new()) + } +} + +impl<'a, T> OwnedRef<'a, T> +where + T: Sized + 'static, +{ + /// Returns a new [`OwnedRef`], pointing to the given [`ShMem`]. + /// + /// # Panics + /// Panics if the given shared mem is too small + /// + /// # Safety + /// The shared memory needs to start with a valid object of type `T`. + /// Any use of this [`OwnedRef`] will dereference a pointer to the shared memory accordingly. + pub unsafe fn from_shmem(shmem: &mut S) -> Self { + Self::from_ptr(shmem.as_mut_ptr_of().unwrap()) + } + + /// Returns a new [`OwnedRef`], owning the given value. + pub fn owned(val: T) -> Self { + Self::Owned(Box::new(val)) + } +} + impl<'a, T> Serialize for OwnedRef<'a, T> where T: 'a + ?Sized + Serialize, @@ -47,6 +110,7 @@ where S: Serializer, { match self { + OwnedRef::RefRaw(r, _) => unsafe { (*r).as_ref().unwrap() }.serialize(se), OwnedRef::Ref(r) => r.serialize(se), OwnedRef::Owned(b) => b.serialize(se), } @@ -73,6 +137,7 @@ where #[must_use] fn as_ref(&self) -> &T { match self { + OwnedRef::RefRaw(r, _) => unsafe { (*r).as_ref().unwrap() }, OwnedRef::Ref(r) => r, OwnedRef::Owned(v) => v.as_ref(), } @@ -86,7 +151,7 @@ where #[must_use] fn is_owned(&self) -> bool { match self { - OwnedRef::Ref(_) => false, + OwnedRef::RefRaw(..) | OwnedRef::Ref(_) => false, OwnedRef::Owned(_) => true, } } @@ -94,6 +159,9 @@ where #[must_use] fn into_owned(self) -> Self { match self { + OwnedRef::RefRaw(r, _) => { + OwnedRef::Owned(Box::new(unsafe { r.as_ref().unwrap().clone() })) + } OwnedRef::Ref(r) => OwnedRef::Owned(Box::new(r.clone())), OwnedRef::Owned(v) => OwnedRef::Owned(v), } @@ -102,13 +170,61 @@ where /// Wrap a mutable reference and convert to a Box on serialize #[derive(Debug)] -pub enum OwnedRefMut<'a, T: 'a + ?Sized> { +pub enum OwnedRefMut<'a, T> +where + T: 'a + ?Sized, +{ + /// A mutable pointer to a type + RefRaw(*mut T, UnsafeMarker), /// A mutable ref to a type Ref(&'a mut T), /// An owned [`Box`] of a type Owned(Box), } +impl<'a, T> OwnedRefMut<'a, T> +where + T: 'a + ?Sized, +{ + /// Returns a new [`OwnedRefMut`], wrapping a mutable pointer. + /// + /// # Panics + /// Panics if the given pointer is `null` + /// + /// # Safety + /// The pointer needs to point to a valid object of type `T`. + /// Any use of this [`OwnedRefMut`] will dereference the pointer accordingly. + pub unsafe fn from_mut_ptr(ptr: *mut T) -> Self { + assert!( + !ptr.is_null(), + "Null pointer passed to OwnedRefMut::from_mut_ptr constructor!" + ); + Self::RefRaw(ptr, UnsafeMarker::new()) + } +} + +impl<'a, T> OwnedRefMut<'a, T> +where + T: Sized + 'static, +{ + /// Returns a new [`OwnedRefMut`], pointing to the given [`ShMem`]. + /// + /// # Panics + /// Panics if the given shared mem is too small + /// + /// # Safety + /// The shared memory needs to start with a valid object of type `T`. + /// Any use of this [`OwnedRefMut`] will dereference a pointer to the shared memory accordingly. + pub unsafe fn from_shmem(shmem: &mut S) -> Self { + Self::from_mut_ptr(shmem.as_mut_ptr_of().unwrap()) + } + + /// Returns a new [`OwnedRefMut`], owning the given value. + pub fn owned(val: T) -> Self { + Self::Owned(Box::new(val)) + } +} + impl<'a, T: 'a + ?Sized + Serialize> Serialize for OwnedRefMut<'a, T> { fn serialize(&self, se: S) -> Result where @@ -116,6 +232,7 @@ impl<'a, T: 'a + ?Sized + Serialize> Serialize for OwnedRefMut<'a, T> { { match self { OwnedRefMut::Ref(r) => r.serialize(se), + OwnedRefMut::RefRaw(r, _) => unsafe { r.as_ref().unwrap().serialize(se) }, OwnedRefMut::Owned(b) => b.serialize(se), } } @@ -137,6 +254,7 @@ impl<'a, T: Sized> AsRef for OwnedRefMut<'a, T> { #[must_use] fn as_ref(&self) -> &T { match self { + OwnedRefMut::RefRaw(r, _) => unsafe { r.as_ref().unwrap() }, OwnedRefMut::Ref(r) => r, OwnedRefMut::Owned(v) => v.as_ref(), } @@ -147,6 +265,7 @@ impl<'a, T: Sized> AsMut for OwnedRefMut<'a, T> { #[must_use] fn as_mut(&mut self) -> &mut T { match self { + OwnedRefMut::RefRaw(r, _) => unsafe { r.as_mut().unwrap() }, OwnedRefMut::Ref(r) => r, OwnedRefMut::Owned(v) => v.as_mut(), } @@ -160,7 +279,7 @@ where #[must_use] fn is_owned(&self) -> bool { match self { - OwnedRefMut::Ref(_) => false, + OwnedRefMut::RefRaw(..) | OwnedRefMut::Ref(_) => false, OwnedRefMut::Owned(_) => true, } } @@ -168,6 +287,9 @@ where #[must_use] fn into_owned(self) -> Self { match self { + OwnedRefMut::RefRaw(r, _) => unsafe { + OwnedRefMut::Owned(Box::new(r.as_ref().unwrap().clone())) + }, OwnedRefMut::Ref(r) => OwnedRefMut::Owned(Box::new(r.clone())), OwnedRefMut::Owned(v) => OwnedRefMut::Owned(v), } @@ -178,7 +300,7 @@ where #[derive(Clone, Debug)] enum OwnedSliceInner<'a, T: 'a + Sized> { /// A ref to a raw slice and length - RefRaw(*const T, usize), + RefRaw(*const T, usize, UnsafeMarker), /// A ref to a slice Ref(&'a [T]), /// A ref to an owned [`Vec`] @@ -191,7 +313,7 @@ impl<'a, T: 'a + Sized + Serialize> Serialize for OwnedSliceInner<'a, T> { S: Serializer, { match self { - OwnedSliceInner::RefRaw(rr, len) => unsafe { + OwnedSliceInner::RefRaw(rr, len, _) => unsafe { slice::from_raw_parts(*rr, *len).serialize(se) }, OwnedSliceInner::Ref(r) => r.serialize(se), @@ -239,14 +361,14 @@ impl<'a, T> OwnedSlice<'a, T> { #[must_use] pub unsafe fn from_raw_parts(ptr: *const T, len: usize) -> Self { Self { - inner: OwnedSliceInner::RefRaw(ptr, len), + inner: OwnedSliceInner::RefRaw(ptr, len, UnsafeMarker::new()), } } /// Truncate the inner slice or vec returning the old size on success or `None` on failure pub fn truncate(&mut self, new_len: usize) -> Option { match &mut self.inner { - OwnedSliceInner::RefRaw(_rr, len) => { + OwnedSliceInner::RefRaw(_rr, len, _) => { let tmp = *len; if new_len <= tmp { *len = new_len; @@ -323,7 +445,9 @@ impl<'a, T> From> for OwnedSlice<'a, T> { fn from(mut_slice: OwnedMutSlice<'a, T>) -> Self { Self { inner: match mut_slice.inner { - OwnedMutSliceInner::RefRaw(ptr, len) => OwnedSliceInner::RefRaw(ptr as _, len), + OwnedMutSliceInner::RefRaw(ptr, len, unsafe_marker) => { + OwnedSliceInner::RefRaw(ptr as _, len, unsafe_marker) + } OwnedMutSliceInner::Ref(r) => OwnedSliceInner::Ref(r as _), OwnedMutSliceInner::Owned(v) => OwnedSliceInner::Owned(v), }, @@ -338,7 +462,7 @@ impl<'a, T: Sized> AsSlice for OwnedSlice<'a, T> { fn as_slice(&self) -> &[T] { match &self.inner { OwnedSliceInner::Ref(r) => r, - OwnedSliceInner::RefRaw(rr, len) => unsafe { slice::from_raw_parts(*rr, *len) }, + OwnedSliceInner::RefRaw(rr, len, _) => unsafe { slice::from_raw_parts(*rr, *len) }, OwnedSliceInner::Owned(v) => v.as_slice(), } } @@ -351,7 +475,7 @@ where #[must_use] fn is_owned(&self) -> bool { match self.inner { - OwnedSliceInner::RefRaw(_, _) | OwnedSliceInner::Ref(_) => false, + OwnedSliceInner::RefRaw(..) | OwnedSliceInner::Ref(_) => false, OwnedSliceInner::Owned(_) => true, } } @@ -359,7 +483,7 @@ where #[must_use] fn into_owned(self) -> Self { match self.inner { - OwnedSliceInner::RefRaw(rr, len) => Self { + OwnedSliceInner::RefRaw(rr, len, _) => Self { inner: OwnedSliceInner::Owned(unsafe { slice::from_raw_parts(rr, len).to_vec() }), }, OwnedSliceInner::Ref(r) => Self { @@ -392,7 +516,7 @@ where #[derive(Debug)] pub enum OwnedMutSliceInner<'a, T: 'a + Sized> { /// A raw ptr to a memory location and a length - RefRaw(*mut T, usize), + RefRaw(*mut T, usize, UnsafeMarker), /// A ptr to a mutable slice of the type Ref(&'a mut [T]), /// An owned [`Vec`] of the type @@ -405,7 +529,7 @@ impl<'a, T: 'a + Sized + Serialize> Serialize for OwnedMutSliceInner<'a, T> { S: Serializer, { match self { - OwnedMutSliceInner::RefRaw(rr, len) => { + OwnedMutSliceInner::RefRaw(rr, len, _) => { unsafe { slice::from_raw_parts_mut(*rr, *len) }.serialize(se) } OwnedMutSliceInner::Ref(r) => r.serialize(se), @@ -466,7 +590,7 @@ impl<'a, T: 'a + Sized> OwnedMutSlice<'a, T> { } } else { Self { - inner: OwnedMutSliceInner::RefRaw(ptr, len), + inner: OwnedMutSliceInner::RefRaw(ptr, len, UnsafeMarker::new()), } } } @@ -474,7 +598,7 @@ impl<'a, T: 'a + Sized> OwnedMutSlice<'a, T> { /// Truncate the inner slice or vec returning the old size on success or `None` on failure pub fn truncate(&mut self, new_len: usize) -> Option { match &mut self.inner { - OwnedMutSliceInner::RefRaw(_rr, len) => { + OwnedMutSliceInner::RefRaw(_rr, len, _) => { let tmp = *len; if new_len <= tmp { *len = new_len; @@ -521,7 +645,7 @@ impl<'a, T: Sized> AsSlice for OwnedMutSlice<'a, T> { #[must_use] fn as_slice(&self) -> &[T] { match &self.inner { - OwnedMutSliceInner::RefRaw(rr, len) => unsafe { slice::from_raw_parts(*rr, *len) }, + OwnedMutSliceInner::RefRaw(rr, len, _) => unsafe { slice::from_raw_parts(*rr, *len) }, OwnedMutSliceInner::Ref(r) => r, OwnedMutSliceInner::Owned(v) => v.as_slice(), } @@ -533,7 +657,9 @@ impl<'a, T: Sized> AsMutSlice for OwnedMutSlice<'a, T> { #[must_use] fn as_mut_slice(&mut self) -> &mut [T] { match &mut self.inner { - OwnedMutSliceInner::RefRaw(rr, len) => unsafe { slice::from_raw_parts_mut(*rr, *len) }, + OwnedMutSliceInner::RefRaw(rr, len, _) => unsafe { + slice::from_raw_parts_mut(*rr, *len) + }, OwnedMutSliceInner::Ref(r) => r, OwnedMutSliceInner::Owned(v) => v.as_mut_slice(), } @@ -547,7 +673,7 @@ where #[must_use] fn is_owned(&self) -> bool { match self.inner { - OwnedMutSliceInner::RefRaw(_, _) | OwnedMutSliceInner::Ref(_) => false, + OwnedMutSliceInner::RefRaw(..) | OwnedMutSliceInner::Ref(_) => false, OwnedMutSliceInner::Owned(_) => true, } } @@ -555,7 +681,7 @@ where #[must_use] fn into_owned(self) -> Self { let vec = match self.inner { - OwnedMutSliceInner::RefRaw(rr, len) => unsafe { + OwnedMutSliceInner::RefRaw(rr, len, _) => unsafe { slice::from_raw_parts_mut(rr, len).to_vec() }, OwnedMutSliceInner::Ref(r) => r.to_vec(), diff --git a/libafl_bolts/src/shmem.rs b/libafl_bolts/src/shmem.rs index d4b67f02c4..fb55a9f2cd 100644 --- a/libafl_bolts/src/shmem.rs +++ b/libafl_bolts/src/shmem.rs @@ -3,11 +3,11 @@ #[cfg(feature = "alloc")] use alloc::{rc::Rc, string::ToString}; -use core::fmt::Debug; #[cfg(feature = "alloc")] use core::fmt::Display; #[cfg(feature = "alloc")] use core::{cell::RefCell, fmt, mem::ManuallyDrop}; +use core::{fmt::Debug, mem}; #[cfg(feature = "std")] use std::env; #[cfg(all(unix, feature = "std", not(target_os = "haiku")))] @@ -204,52 +204,24 @@ pub trait ShMem: Sized + Debug + Clone + AsSlice + AsMutSlice() = T::new();` - unsafe fn as_object(&self) -> &T { - assert!(self.len() >= core::mem::size_of::()); - (self.as_slice().as_ptr() as *const () as *const T) - .as_ref() - .unwrap() + /// Convert to a ptr of a given type, checking the size. + /// If the map is too small, returns `None` + fn as_ptr_of(&self) -> Option<*const T> { + if self.len() >= mem::size_of::() { + Some(self.as_slice().as_ptr() as *const T) + } else { + None + } } - /// Convert to an owned object mutable reference - /// - /// # Safety - /// This function is not safe as the object may be not initialized. - /// The user is responsible to initialize the object with something like - /// `*shmem.as_object_mut::() = T::new();` - unsafe fn as_object_mut(&mut self) -> &mut T { - assert!(self.len() >= core::mem::size_of::()); - (self.as_mut_slice().as_mut_ptr() as *mut () as *mut T) - .as_mut() - .unwrap() - } - - /// Convert to a slice of type &\[T\] - /// - /// # Safety - /// This function is not safe as the object may be not initialized. - /// The user is responsible to initialize the objects in the slice - unsafe fn as_objects_slice(&self, len: usize) -> &[T] { - assert!(self.len() >= core::mem::size_of::() * len); - let ptr = self.as_slice().as_ptr() as *const () as *const T; - core::slice::from_raw_parts(ptr, len) - } - - /// Convert to a slice of type &mut \[T\] - /// - /// # Safety - /// This function is not safe as the object may be not initialized. - /// The user is responsible to initialize the objects in the slice - unsafe fn as_objects_slice_mut(&mut self, len: usize) -> &mut [T] { - assert!(self.len() >= core::mem::size_of::() * len); - let ptr = self.as_mut_slice().as_mut_ptr() as *mut () as *mut T; - core::slice::from_raw_parts_mut(ptr, len) + /// Convert to a mut ptr of a given type, checking the size. + /// If the map is too small, returns `None` + fn as_mut_ptr_of(&mut self) -> Option<*mut T> { + if self.len() >= mem::size_of::() { + Some(self.as_mut_slice().as_mut_ptr() as *mut T) + } else { + None + } } /// Get the description of the shared memory mapping @@ -287,25 +259,20 @@ pub trait ShMemProvider: Clone + Default + Debug { /// Get a mapping given its id and size fn shmem_from_id_and_size(&mut self, id: ShMemId, size: usize) -> Result; - /// Create a new shared memory mapping to hold an object of the given type - fn new_shmem_object(&mut self) -> Result { - self.new_shmem(core::mem::size_of::()) + /// Create a new shared memory mapping to hold an object of the given type, and initializes it with the given value. + fn new_on_shmem(&mut self, value: T) -> Result { + self.uninit_on_shmem::().map(|mut shmem| { + // # Safety + // The map has been created at this point in time, and is large enough. + // The map is fresh from the OS and, hence, the pointer should be properly aligned for any object. + unsafe { shmem.as_mut_ptr_of::().unwrap().write_volatile(value) }; + shmem + }) } - /// Create a new shared memory mapping to hold an array of objects of the given type - fn new_shmem_objects_array( - &mut self, - len: usize, - ) -> Result { - self.new_shmem(core::mem::size_of::() * len) - } - - /// Get a mapping given its id to hold an object of the given type - fn shmem_object_from_id( - &mut self, - id: ShMemId, - ) -> Result { - self.shmem_from_id_and_size(id, core::mem::size_of::()) + /// Create a new shared memory mapping to hold an object of the given type, and initializes it with the given value. + fn uninit_on_shmem(&mut self) -> Result { + self.new_shmem(mem::size_of::()) } /// Get a mapping given a description diff --git a/libafl_libfuzzer/libafl_libfuzzer_runtime/src/lib.rs b/libafl_libfuzzer/libafl_libfuzzer_runtime/src/lib.rs index a5de859b98..11afce8242 100644 --- a/libafl_libfuzzer/libafl_libfuzzer_runtime/src/lib.rs +++ b/libafl_libfuzzer/libafl_libfuzzer_runtime/src/lib.rs @@ -115,8 +115,6 @@ use mimalloc::MiMalloc; #[cfg(feature = "mimalloc")] static GLOBAL: MiMalloc = MiMalloc; -static mut BACKTRACE: Option = None; - #[allow(clippy::struct_excessive_bools)] struct CustomMutationStatus { std_mutational: bool, @@ -184,11 +182,13 @@ macro_rules! fuzz_with { use rand::{thread_rng, RngCore}; use std::{env::temp_dir, fs::create_dir, path::PathBuf}; - use crate::{BACKTRACE, CustomMutationStatus}; - use crate::corpus::{ArtifactCorpus, LibfuzzerCorpus}; - use crate::feedbacks::{LibfuzzerCrashCauseFeedback, LibfuzzerKeepFeedback, ShrinkMapFeedback}; - use crate::misc::should_use_grimoire; - use crate::observers::{MappedEdgeMapObserver, SizeValueObserver}; + use crate::{ + CustomMutationStatus, + corpus::{ArtifactCorpus, LibfuzzerCorpus}, + feedbacks::{LibfuzzerCrashCauseFeedback, LibfuzzerKeepFeedback, ShrinkMapFeedback}, + misc::should_use_grimoire, + observers::{MappedEdgeMapObserver, SizeValueObserver}, + }; let edge_maker = &$edge_maker; @@ -213,9 +213,8 @@ macro_rules! fuzz_with { let cmplog_observer = CmpLogObserver::new("cmplog", true); // Create a stacktrace observer - let backtrace_observer = BacktraceObserver::new( + let backtrace_observer = BacktraceObserver::owned( "BacktraceObserver", - unsafe { &mut BACKTRACE }, if $options.forks().is_some() || $options.tui() { libafl::observers::HarnessType::Child } else { libafl::observers::HarnessType::InProcess } ); diff --git a/libafl_targets/src/cmps/mod.rs b/libafl_targets/src/cmps/mod.rs index 5cdf0d7067..155674dbea 100644 --- a/libafl_targets/src/cmps/mod.rs +++ b/libafl_targets/src/cmps/mod.rs @@ -428,7 +428,7 @@ pub static mut libafl_cmplog_map_extended: AFLppCmpLogMap = AFLppCmpLogMap { pub use libafl_cmplog_map as CMPLOG_MAP; pub use libafl_cmplog_map_extended as CMPLOG_MAP_EXTENDED; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] #[repr(C, packed)] /// Comparison map compatible with AFL++ cmplog instrumentation pub struct AFLppCmpLogMap { diff --git a/libafl_targets/src/cmps/observers/aflpp.rs b/libafl_targets/src/cmps/observers/aflpp.rs index 93701b9304..20a5d8e30a 100644 --- a/libafl_targets/src/cmps/observers/aflpp.rs +++ b/libafl_targets/src/cmps/observers/aflpp.rs @@ -179,11 +179,15 @@ where { /// Creates a new [`AFLppCmpLogObserver`] with the given name and map. #[must_use] - pub fn new(name: &'static str, map: &'a mut AFLppCmpLogMap, add_meta: bool) -> Self { + pub fn new( + name: &'static str, + cmp_map: OwnedRefMut<'a, AFLppCmpLogMap>, + add_meta: bool, + ) -> Self { Self { name: name.to_string(), size: None, - cmp_map: OwnedRefMut::Ref(map), + cmp_map, add_meta, original: false, phantom: PhantomData, @@ -198,15 +202,15 @@ where #[must_use] pub fn with_size( name: &'static str, - map: &'a mut AFLppCmpLogMap, + cmp_map: OwnedRefMut<'a, AFLppCmpLogMap>, add_meta: bool, original: bool, - size: &'a mut usize, + size: OwnedRefMut<'a, usize>, ) -> Self { Self { name: name.to_string(), - size: Some(OwnedRefMut::Ref(size)), - cmp_map: OwnedRefMut::Ref(map), + size: Some(size), + cmp_map, add_meta, original, phantom: PhantomData,