Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compile-time edge module compilation check, native support for ConstMapObserver #2592

Merged
merged 39 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
3ccc726
compile-time edge module compilation trick
rmalmain Oct 8, 2024
ef8d01a
clippy
rmalmain Oct 8, 2024
6bb94fa
possible since rust 1.79
rmalmain Oct 9, 2024
aa50cb2
split edge module in submodules
rmalmain Oct 9, 2024
5b39956
Update frida to 0.14.0 (#2596)
rmalmain Oct 9, 2024
4350245
tracers and generators private modules
rmalmain Oct 9, 2024
decaa67
do not use star export.
rmalmain Oct 9, 2024
d04be02
same for drcov
rmalmain Oct 9, 2024
964da23
forgot a file...
rmalmain Oct 9, 2024
d66d787
first draft of generic-based edge module for ConstantLengthMapObserver.
rmalmain Oct 9, 2024
505c88d
integration of OwnedSizedSlice.
rmalmain Oct 10, 2024
6bf7530
Merge branch 'main' into improve_edge_module_builder
rmalmain Oct 25, 2024
6e838aa
fix serde stuff
rmalmain Oct 25, 2024
0611e32
no std
rmalmain Oct 25, 2024
d9dc77c
import
rmalmain Oct 25, 2024
35297dc
fixed qemu_cmin with new constant map abstraction.
rmalmain Oct 25, 2024
65c3ff7
fix const map
rmalmain Oct 25, 2024
2b59798
fix clippy from another pr...
rmalmain Oct 25, 2024
b22cf6c
fix non-null usage
rmalmain Oct 25, 2024
f8ac5b0
fix ci?
rmalmain Oct 25, 2024
bfe4b14
Merge branch 'main' into improve_edge_module_builder
rmalmain Oct 25, 2024
925dab2
new feature stuff
rmalmain Oct 25, 2024
c7c8cd8
Merge branch 'main' into improve_edge_module_builder
rmalmain Oct 28, 2024
6b8035a
Merge branch 'main' into improve_edge_module_builder
rmalmain Oct 30, 2024
bb70553
Merge branch 'main' into improve_edge_module_builder
rmalmain Oct 31, 2024
ad413e7
Merge branch 'main' into improve_edge_module_builder
rmalmain Nov 3, 2024
606f5e0
fixes
rmalmain Nov 3, 2024
c870076
minor fixes
rmalmain Nov 3, 2024
f715038
fmt
rmalmain Nov 3, 2024
236b2b3
non null
rmalmain Nov 3, 2024
481cee8
im stupid
rmalmain Nov 3, 2024
3d51d58
fmt
rmalmain Nov 3, 2024
1a69530
fix fuzzer
rmalmain Nov 3, 2024
7982f7f
fix fuzzers
rmalmain Nov 3, 2024
93b5bbf
sized slice
rmalmain Nov 3, 2024
cb21994
fuzzer fixes
rmalmain Nov 4, 2024
f520a9a
ptr::NonNull -> NonNull
rmalmain Nov 4, 2024
fa035af
shorter trait length
rmalmain Nov 4, 2024
7263d91
fmt
rmalmain Nov 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/qemu-fuzzer-tester-prepare/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ runs:
steps:
- name: Install QEMU deps
shell: bash
run: apt-get update && apt-get install -y qemu-utils sudo python3-msgpack python3-jinja2 curl
run: apt-get update && apt-get install -y qemu-utils sudo python3-msgpack python3-jinja2 curl python3-dev
- uses: dtolnay/rust-toolchain@stable
- name: enable mult-thread for `make`
shell: bash
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::path::PathBuf;
use std::{path::PathBuf, ptr};

use libafl::{
corpus::{InMemoryCorpus, OnDiskCorpus},
Expand Down Expand Up @@ -35,7 +35,8 @@ pub fn main() {
libafl::executors::ExitKind::Ok
};
// Create an observation channel using the signals map
let observer = unsafe { ConstMapObserver::<u8, 3>::from_mut_ptr("signals", array_ptr) };
let observer =
unsafe { ConstMapObserver::<u8, 3>::from_mut_ptr("signals", ptr::NonNull::new(array_ptr)) };
// Create a stacktrace observer
let bt_observer = BacktraceObserver::owned(
"BacktraceObserver",
Expand Down
8 changes: 4 additions & 4 deletions fuzzers/binary_only/qemu_cmin/src/fuzzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//!
#[cfg(feature = "i386")]
use core::mem::size_of;
use std::{env, io, path::PathBuf, process};
use std::{env, io, path::PathBuf, process, ptr::NonNull};

use clap::{builder::Str, Parser};
use libafl::{
Expand Down Expand Up @@ -162,7 +162,7 @@ pub fn fuzz() -> Result<(), Error> {
let mut edges_observer = unsafe {
HitcountsMapObserver::new(ConstMapObserver::<_, EDGES_MAP_DEFAULT_SIZE>::from_mut_ptr(
"edges",
edges.as_mut_ptr(),
NonNull::new(edges.as_mut_ptr()).expect("The edge map pointer is null."),
))
};

Expand Down Expand Up @@ -196,7 +196,7 @@ pub fn fuzz() -> Result<(), Error> {
let len = len as GuestReg;

unsafe {
qemu.write_mem(input_addr, buf);
qemu.write_mem(input_addr, buf).expect("qemu write failed.");
qemu.write_reg(Regs::Pc, test_one_input_ptr).unwrap();
qemu.write_reg(Regs::Sp, stack_ptr).unwrap();
qemu.write_return_address(ret_addr).unwrap();
Expand All @@ -219,7 +219,7 @@ pub fn fuzz() -> Result<(), Error> {
};

let modules = tuple_list!(StdEdgeCoverageChildModule::builder()
.map_observer(edges_observer.as_mut())
.const_map_observer(edges_observer.as_mut())
.build()?);

let emulator = Emulator::empty().qemu(qemu).modules(modules).build()?;
Expand Down
2 changes: 1 addition & 1 deletion libafl/src/executors/forkserver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1635,7 +1635,7 @@ mod tests {

let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap();
shmem.write_to_env("__AFL_SHM_ID").unwrap();
let shmem_buf = shmem.as_slice_mut();
let shmem_buf: &mut [u8; MAP_SIZE] = shmem.as_slice_mut().try_into().unwrap();
rmalmain marked this conversation as resolved.
Show resolved Hide resolved

let edges_observer = HitcountsMapObserver::new(ConstMapObserver::<_, MAP_SIZE>::new(
"shared_mem",
Expand Down
80 changes: 24 additions & 56 deletions libafl/src/observers/map/const_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,26 @@ use core::{
fmt::Debug,
hash::{Hash, Hasher},
ops::{Deref, DerefMut},
ptr,
};

use ahash::RandomState;
use libafl_bolts::{ownedref::OwnedMutSlice, AsSlice, AsSliceMut, HasLen, Named};
use libafl_bolts::{ownedref::OwnedMutSizedSlice, HasLen, Named};
use serde::{de::DeserializeOwned, Deserialize, Serialize};

use crate::{
observers::{map::MapObserver, Observer, VariableLengthMapObserver},
observers::{map::MapObserver, ConstantLengthMapObserver, Observer},
Error,
};

// TODO: remove the size field and implement ConstantLengthMapObserver

/// Use a const size to speedup `Feedback::is_interesting` when the user can
/// know the size of the map at compile time.
#[derive(Serialize, Deserialize, Debug)]
#[allow(clippy::unsafe_derive_deserialize)]
pub struct ConstMapObserver<'a, T, const N: usize> {
map: OwnedMutSlice<'a, T>,
map: OwnedMutSizedSlice<'a, T, N>,
initial: T,
name: Cow<'static, str>,
size: usize,
}

impl<I, S, T, const N: usize> Observer<I, S> for ConstMapObserver<'_, T, N>
Expand Down Expand Up @@ -87,19 +85,19 @@ where

#[inline]
fn get(&self, idx: usize) -> T {
self.as_slice()[idx]
self[idx]
}

#[inline]
fn set(&mut self, idx: usize, val: T) {
self.map.as_slice_mut()[idx] = val;
(*self)[idx] = val;
}

/// Count the set bytes in the map
fn count_bytes(&self) -> u64 {
let initial = self.initial();
let cnt = self.usable_count();
let map = self.as_slice();
let map = self.map.as_slice();
let mut res = 0;
for x in &map[0..cnt] {
if *x != initial {
Expand All @@ -110,7 +108,7 @@ where
}

fn usable_count(&self) -> usize {
self.as_slice().len()
self.len()
}

#[inline]
Expand All @@ -124,22 +122,22 @@ where
// Normal memset, see https://rust.godbolt.org/z/Trs5hv
let initial = self.initial();
let cnt = self.usable_count();
let map = self.as_slice_mut();
let map = &mut (*self);
for x in &mut map[0..cnt] {
*x = initial;
}
Ok(())
}

fn to_vec(&self) -> Vec<T> {
self.as_slice().to_vec()
self.map.to_vec()
}

/// Get the number of set entries with the specified indexes
fn how_many_set(&self, indexes: &[usize]) -> usize {
let initial = self.initial();
let cnt = self.usable_count();
let map = self.as_slice();
let map = self.map.as_slice();
let mut res = 0;
for i in indexes {
if *i < cnt && map[*i] != initial {
Expand All @@ -150,37 +148,30 @@ where
}
}

impl<T, const N: usize> VariableLengthMapObserver for ConstMapObserver<'_, T, N>
impl<T, const N: usize> ConstantLengthMapObserver<N> for ConstMapObserver<'_, T, N>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about renaming them to ConstLenMapObserver and VarLenMapObserver btw? Seems shorter and just as to clear.
Random idea of course, feel free to ignore.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok for me, both work out imho

where
T: PartialEq + Copy + Hash + Serialize + DeserializeOwned + Debug + 'static,
{
fn map_slice(&mut self) -> &[Self::Entry] {
self.map.as_slice()
}

fn map_slice_mut(&mut self) -> &mut [Self::Entry] {
self.map.as_slice_mut()
}

fn size(&mut self) -> &usize {
&N
fn map_slice(&self) -> &[Self::Entry; N] {
&self.map
}

fn size_mut(&mut self) -> &mut usize {
&mut self.size
fn map_slice_mut(&mut self) -> &mut [Self::Entry; N] {
&mut self.map
}
}

impl<T, const N: usize> Deref for ConstMapObserver<'_, T, N> {
type Target = [T];

fn deref(&self) -> &[T] {
&self.map
self.map.as_slice()
}
}

impl<T, const N: usize> DerefMut for ConstMapObserver<'_, T, N> {
fn deref_mut(&mut self) -> &mut [T] {
&mut self.map
self.map.as_mut_slice()
}
}

Expand All @@ -194,48 +185,25 @@ where
/// Will get a pointer to the map and dereference it at any point in time.
/// The map must not move in memory!
#[must_use]
pub fn new(name: &'static str, map: &'a mut [T]) -> Self {
pub fn new(name: &'static str, map: &'a mut [T; N]) -> Self {
assert!(map.len() >= N);
Self {
map: OwnedMutSlice::from(map),
map: OwnedMutSizedSlice::from(map),
name: Cow::from(name),
initial: T::default(),
size: N,
}
}

/// Creates a new [`MapObserver`] from a raw pointer
///
/// # Safety
/// Will dereference the `map_ptr` with up to len elements.
pub unsafe fn from_mut_ptr(name: &'static str, map_ptr: *mut T) -> Self {
#[must_use]
pub unsafe fn from_mut_ptr(name: &'static str, map_ptr: ptr::NonNull<T>) -> Self {
ConstMapObserver {
map: OwnedMutSlice::from_raw_parts_mut(map_ptr, N),
map: OwnedMutSizedSlice::from_raw_parts_mut(map_ptr),
name: Cow::from(name),
initial: T::default(),
size: N,
}
}
}

impl<T, const N: usize> ConstMapObserver<'_, T, N>
where
T: Default + Clone,
{
/// Creates a new [`MapObserver`] with an owned map
#[must_use]
pub fn owned(name: &'static str, map: Vec<T>) -> Self {
assert!(map.len() >= N);
let initial = if map.is_empty() {
T::default()
} else {
map[0].clone()
};
Self {
map: OwnedMutSlice::from(map),
name: Cow::from(name),
initial,
size: N,
}
}
}
22 changes: 19 additions & 3 deletions libafl/src/observers/map/hitcount_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ use serde::{Deserialize, Serialize};

use crate::{
executors::ExitKind,
observers::{map::MapObserver, DifferentialObserver, Observer, VariableLengthMapObserver},
observers::{
map::MapObserver, ConstantLengthMapObserver, DifferentialObserver, Observer,
VariableLengthMapObserver,
},
Error,
};

Expand Down Expand Up @@ -230,19 +233,32 @@ where
}
}

impl<M, const N: usize> ConstantLengthMapObserver<N> for HitcountsMapObserver<M>
where
M: ConstantLengthMapObserver<N> + MapObserver<Entry = u8>,
{
fn map_slice(&self) -> &[Self::Entry; N] {
self.base.map_slice()
}

fn map_slice_mut(&mut self) -> &mut [Self::Entry; N] {
self.base.map_slice_mut()
}
}

impl<M> VariableLengthMapObserver for HitcountsMapObserver<M>
where
M: VariableLengthMapObserver + MapObserver<Entry = u8>,
{
fn map_slice(&mut self) -> &[Self::Entry] {
fn map_slice(&self) -> &[Self::Entry] {
self.base.map_slice()
}

fn map_slice_mut(&mut self) -> &mut [Self::Entry] {
self.base.map_slice_mut()
}

fn size(&mut self) -> &usize {
fn size(&self) -> &usize {
self.base.size()
}

Expand Down
7 changes: 5 additions & 2 deletions libafl/src/observers/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,14 +390,14 @@ pub trait MapObserver:
pub trait VariableLengthMapObserver: MapObserver {
/// A mutable slice reference to the map.
/// The length of the map gives the maximum allocatable size.
fn map_slice(&mut self) -> &[Self::Entry];
fn map_slice(&self) -> &[Self::Entry];

/// A slice reference to the map.
/// The length of the map gives the maximum allocatable size.
fn map_slice_mut(&mut self) -> &mut [Self::Entry];

/// A reference to the size of the map.
fn size(&mut self) -> &usize;
fn size(&self) -> &usize;

/// A mutable reference to the size of the map.
fn size_mut(&mut self) -> &mut usize;
Expand All @@ -408,6 +408,9 @@ pub trait ConstantLengthMapObserver<const N: usize>: MapObserver {
/// The size of the map
const LENGTH: usize = N;

/// A mutable slice reference to the map
fn map_slice(&self) -> &[Self::Entry; N];

/// A mutable slice reference to the map
fn map_slice_mut(&mut self) -> &mut [Self::Entry; N];
}
Expand Down
4 changes: 2 additions & 2 deletions libafl/src/observers/map/variable_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,15 +153,15 @@ impl<T> VariableLengthMapObserver for VariableMapObserver<'_, T>
where
T: PartialEq + Copy + Hash + Serialize + DeserializeOwned + Debug,
{
fn map_slice(&mut self) -> &[Self::Entry] {
fn map_slice(&self) -> &[Self::Entry] {
self.map.as_ref()
}

fn map_slice_mut(&mut self) -> &mut [Self::Entry] {
self.map.as_mut()
}

fn size(&mut self) -> &usize {
fn size(&self) -> &usize {
self.size.as_ref()
}

Expand Down
Loading
Loading