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

Restrict more on edges map API #2117

Merged
merged 17 commits into from
Apr 29, 2024
2 changes: 1 addition & 1 deletion docs/src/DEBUGGING.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ You should *never* use the `EDGES_MAP`'s size as this is just the size of the al
## Q. I still have problems with my fuzzer.
Finally, if you really have no idea what is going on, run your fuzzer with logging enabled. (You can use `env_logger`, `SimpleStdoutLogger`, `SimpleStderrLogger` from `libafl_bolts`. `fuzzbench_text` has an example to show how to use it.) (Don't forget to enable stdout and stderr), and you can open an issue or ask us in Discord.

## My fuzzer died of `Fuzzer-respawner: Storing state in crashed fuzzer instance did not work, no point to spawn the next client! This can happen if the child calls `exit()`, in that case make sure it uses `abort()`, if it got killed unrecoverable (OOM), or if there is a bug in the fuzzer itself. (Child exited with: 0)`.
## My fuzzer died of ``Storing state in crashed fuzzer instance did not work''.
If the exit code is zero, then this is because either your harness exited or you are using fuzzer_loop_for and forgot to add `mgr.on_restart` at the end of the fuzzer. In the first case, you should patch your harness not to exit. (or use `utils/deexit`).
6 changes: 3 additions & 3 deletions fuzzers/baby_fuzzer_swap_differential/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use libafl::{
state::{HasSolutions, StdState},
};
use libafl_bolts::{current_nanos, rands::StdRand, tuples::tuple_list, AsSlice};
use libafl_targets::{edges_max_num, DifferentialAFLMapSwapObserver};
use libafl_targets::{DifferentialAFLMapSwapObserver, edges_max_num};
#[cfg(not(miri))]
use mimalloc::MiMalloc;

Expand Down Expand Up @@ -84,7 +84,7 @@ pub fn main() {
}
};

let num_edges: usize = edges_max_num();
let num_edges: usize = edges_max_num(); // upper bound

#[cfg(feature = "multimap")]
let (
Expand Down Expand Up @@ -202,7 +202,7 @@ pub fn main() {

// The Monitor trait define how the fuzzer stats are displayed to the user
#[cfg(not(feature = "tui"))]
let mon = SimpleMonitor::new(|s| println!("{s}"));
let mon = SimpleMonitor::with_user_monitor(|s| println!("{s}"));
#[cfg(feature = "tui")]
let ui = TuiUI::new(String::from("Baby Fuzzer"), false);
#[cfg(feature = "tui")]
Expand Down
5 changes: 3 additions & 2 deletions fuzzers/fuzzbench_qemu/src/fuzzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use libafl::{
use libafl_bolts::{
current_nanos, current_time,
os::{dup2, unix_signals::Signal},
ownedref::OwnedMutSlice,
rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider},
tuples::{tuple_list, Merge},
Expand All @@ -47,7 +48,7 @@ use libafl_bolts::{
use libafl_qemu::{
// asan::{init_with_asan, QemuAsanHelper},
cmplog::{CmpLogObserver, QemuCmpLogHelper},
edges::edges_map_mut_slice,
edges::edges_map_mut_ptr,
edges::QemuEdgeCoverageHelper,
edges::MAX_EDGES_NUM,
elf::EasyElf,
Expand Down Expand Up @@ -257,7 +258,7 @@ fn fuzz(
let edges_observer = unsafe {
HitcountsMapObserver::new(VariableMapObserver::from_mut_slice(
"edges",
edges_map_mut_slice(),
OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), MAX_EDGES_NUM),
addr_of_mut!(MAX_EDGES_NUM),
))
.track_indices()
Expand Down
5 changes: 3 additions & 2 deletions fuzzers/qemu_launcher/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,13 @@ use libafl_bolts::shmem::StdShMemProvider;
use libafl_bolts::{
core_affinity::CoreId,
current_nanos,
ownedref::OwnedMutSlice,
rands::StdRand,
tuples::{tuple_list, Merge},
};
use libafl_qemu::{
cmplog::CmpLogObserver,
edges::{edges_map_mut_slice, MAX_EDGES_NUM},
edges::{edges_map_mut_ptr, MAX_EDGES_NUM},
helpers::QemuHelperTuple,
Qemu, QemuExecutor, QemuHooks,
};
Expand Down Expand Up @@ -78,7 +79,7 @@ impl<'a, M: Monitor> Instance<'a, M> {
let edges_observer = unsafe {
HitcountsMapObserver::new(VariableMapObserver::from_mut_slice(
"edges",
edges_map_mut_slice(),
OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), MAX_EDGES_NUM),
addr_of_mut!(MAX_EDGES_NUM),
))
.track_indices()
Expand Down
5 changes: 3 additions & 2 deletions fuzzers/qemu_systemmode/src/fuzzer_breakpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@ use libafl::{
use libafl_bolts::{
core_affinity::Cores,
current_nanos,
ownedref::OwnedMutSlice,
rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider},
tuples::tuple_list,
};
use libafl_qemu::{
breakpoint::Breakpoint,
command::{Command, EmulatorMemoryChunk, EndCommand, StartCommand},
edges::{edges_map_mut_slice, QemuEdgeCoverageHelper, MAX_EDGES_NUM},
edges::{edges_map_mut_ptr, QemuEdgeCoverageHelper, MAX_EDGES_NUM},
elf::EasyElf,
emu::Emulator,
executor::{stateful::StatefulQemuExecutor, QemuExecutorState},
Expand Down Expand Up @@ -154,7 +155,7 @@ pub fn fuzz() {
let edges_observer = unsafe {
HitcountsMapObserver::new(VariableMapObserver::from_mut_slice(
"edges",
edges_map_mut_slice(),
OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), MAX_EDGES_NUM),
addr_of_mut!(MAX_EDGES_NUM),
))
.track_indices()
Expand Down
5 changes: 3 additions & 2 deletions fuzzers/qemu_systemmode/src/fuzzer_classic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ use libafl_bolts::{
core_affinity::Cores,
current_nanos,
os::unix_signals::Signal,
ownedref::OwnedMutSlice,
rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider},
tuples::tuple_list,
AsSlice,
};
use libafl_qemu::{
edges::{edges_map_mut_slice, QemuEdgeCoverageHelper, MAX_EDGES_NUM},
edges::{edges_map_mut_ptr, QemuEdgeCoverageHelper, MAX_EDGES_NUM},
elf::EasyElf,
emu::Qemu,
QemuExecutor, QemuExitReason, QemuExitReasonError, QemuHooks, QemuShutdownCause, Regs,
Expand Down Expand Up @@ -161,7 +162,7 @@ pub fn fuzz() {
let edges_observer = unsafe {
HitcountsMapObserver::new(VariableMapObserver::from_mut_slice(
"edges",
edges_map_mut_slice(),
OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), MAX_EDGES_NUM),
addr_of_mut!(MAX_EDGES_NUM),
))
.track_indices()
Expand Down
5 changes: 3 additions & 2 deletions fuzzers/qemu_systemmode/src/fuzzer_sync_exit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ use libafl::{
use libafl_bolts::{
core_affinity::Cores,
current_nanos,
ownedref::OwnedMutSlice,
rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider},
tuples::tuple_list,
};
use libafl_qemu::{
edges::{edges_map_mut_slice, QemuEdgeCoverageHelper, MAX_EDGES_NUM},
edges::{edges_map_mut_ptr, QemuEdgeCoverageHelper, MAX_EDGES_NUM},
emu::Emulator,
executor::{stateful::StatefulQemuExecutor, QemuExecutorState},
EmuExitReasonError, FastSnapshotManager, HandlerError, HandlerResult, QemuHooks,
Expand Down Expand Up @@ -95,7 +96,7 @@ pub fn fuzz() {
let edges_observer = unsafe {
HitcountsMapObserver::new(VariableMapObserver::from_mut_slice(
"edges",
edges_map_mut_slice(),
OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), MAX_EDGES_NUM),
addr_of_mut!(MAX_EDGES_NUM),
))
.track_indices()
Expand Down
10 changes: 5 additions & 5 deletions libafl_qemu/src/helpers/edges.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use libafl_qemu_sys::GuestAddr;
#[cfg(emulation_mode = "systemmode")]
use libafl_qemu_sys::GuestPhysAddr;
pub use libafl_targets::{
edges_map_mut_ptr, edges_map_mut_slice, edges_max_num, std_edges_map_observer, EDGES_MAP,
EDGES_MAP_PTR, EDGES_MAP_PTR_NUM, EDGES_MAP_SIZE_IN_USE, MAX_EDGES_NUM,
edges_map_mut_ptr, EDGES_MAP, EDGES_MAP_PTR, EDGES_MAP_SIZE_IN_USE, EDGES_MAP_SIZE_MAX,
MAX_EDGES_NUM,
};
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -619,7 +619,7 @@ where
}
// GuestAddress is u32 for 32 bit guests
#[allow(clippy::unnecessary_cast)]
Some((hash_me(src as u64) ^ hash_me(dest as u64)) & (unsafe { EDGES_MAP_PTR_NUM } as u64 - 1))
Some((hash_me(src as u64) ^ hash_me(dest as u64)) & (EDGES_MAP_SIZE_MAX as u64 - 1))
}

pub extern "C" fn trace_edge_hitcount_ptr(_: *const (), id: u64) {
Expand Down Expand Up @@ -692,7 +692,7 @@ where
pub extern "C" fn trace_block_transition_hitcount(_: *const (), id: u64) {
unsafe {
PREV_LOC.with(|prev_loc| {
let x = ((*prev_loc.get() ^ id) as usize) & (EDGES_MAP_PTR_NUM - 1);
Copy link
Member Author

Choose a reason for hiding this comment

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

@rmalmain
can you check these are correct?

let x = ((*prev_loc.get() ^ id) as usize) & (EDGES_MAP_SIZE_MAX - 1);
let entry = EDGES_MAP_PTR.add(x);
*entry = (*entry).wrapping_add(1);
*prev_loc.get() = id.overflowing_shr(1).0;
Expand All @@ -703,7 +703,7 @@ pub extern "C" fn trace_block_transition_hitcount(_: *const (), id: u64) {
pub extern "C" fn trace_block_transition_single(_: *const (), id: u64) {
unsafe {
PREV_LOC.with(|prev_loc| {
let x = ((*prev_loc.get() ^ id) as usize) & (EDGES_MAP_PTR_NUM - 1);
let x = ((*prev_loc.get() ^ id) as usize) & (EDGES_MAP_SIZE_MAX - 1);
let entry = EDGES_MAP_PTR.add(x);
*entry = 1;
*prev_loc.get() = id.overflowing_shr(1).0;
Expand Down
18 changes: 13 additions & 5 deletions libafl_sugar/src/inmemory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use libafl::{
scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator},
token_mutations::{I2SRandReplace, Tokens},
},
observers::{CanTrack, HitcountsMapObserver, TimeObserver},
observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver},
schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler},
stages::{ShadowTracingStage, StdMutationalStage},
state::{HasCorpus, StdState},
Expand All @@ -27,12 +27,13 @@ use libafl::{
use libafl_bolts::{
core_affinity::Cores,
current_nanos,
ownedref::OwnedMutSlice,
rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider},
tuples::{tuple_list, Merge},
AsSlice,
};
use libafl_targets::{std_edges_map_observer, CmpLogObserver};
use libafl_targets::{edges_map_mut_ptr, CmpLogObserver};
use typed_builder::TypedBuilder;

use crate::{CORPUS_CACHE_SIZE, DEFAULT_TIMEOUT_SECS};
Expand Down Expand Up @@ -72,6 +73,9 @@ where
/// Bytes harness
#[builder(setter(strip_option))]
harness: Option<H>,
/// The map size used for the fuzzer
#[builder(default = 65536usize)]
map_size: usize,
/// Fuzz `iterations` number of times, instead of indefinitely; implies use of `fuzz_loop_for`
#[builder(default = None)]
iterations: Option<u64>,
Expand Down Expand Up @@ -142,9 +146,13 @@ where
mut mgr: LlmpRestartingEventManager<_, _, _>,
_core_id| {
// Create an observation channel using the coverage map
let edges_observer =
HitcountsMapObserver::new(unsafe { std_edges_map_observer("edges") })
.track_indices();
let edges_observer = HitcountsMapObserver::new(unsafe {
StdMapObserver::from_mut_slice(
"edges",
OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), self.map_size),
)
})
.track_indices();

// Create an observation channel to keep track of the execution time
let time_observer = TimeObserver::new("time");
Expand Down
5 changes: 3 additions & 2 deletions libafl_sugar/src/qemu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use libafl::{
use libafl_bolts::{
core_affinity::Cores,
current_nanos,
ownedref::OwnedMutSlice,
rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider},
tuples::{tuple_list, Merge},
Expand All @@ -39,7 +40,7 @@ pub use libafl_qemu::emu::Qemu;
#[cfg(not(any(feature = "mips", feature = "hexagon")))]
use libafl_qemu::QemuCmpLogHelper;
use libafl_qemu::{edges, QemuEdgeCoverageHelper, QemuExecutor, QemuHooks};
use libafl_targets::{edges_map_mut_slice, CmpLogObserver};
use libafl_targets::{edges_map_mut_ptr, CmpLogObserver};
use typed_builder::TypedBuilder;

use crate::{CORPUS_CACHE_SIZE, DEFAULT_TIMEOUT_SECS};
Expand Down Expand Up @@ -153,7 +154,7 @@ where
let edges_observer = unsafe {
HitcountsMapObserver::new(VariableMapObserver::from_mut_slice(
"edges",
edges_map_mut_slice(),
OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), edges::MAX_EDGES_NUM),
addr_of_mut!(edges::MAX_EDGES_NUM),
))
.track_indices()
Expand Down
40 changes: 34 additions & 6 deletions libafl_targets/src/coverage.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
//! Coverage maps as static mut array

#[cfg(any(
feature = "sancov_pcguard_edges",
feature = "sancov_pcguard_hitcounts",
feature = "sancov_ngram4",
feature = "sancov_ctx"
))]
use alloc::borrow::Cow;

#[cfg(any(target_os = "linux", target_vendor = "apple"))]
Expand Down Expand Up @@ -63,18 +69,36 @@ pub fn autotokens() -> Result<Tokens, Error> {
/// The size of the map for edges.
#[no_mangle]
pub static mut __afl_map_size: usize = EDGES_MAP_SIZE_IN_USE;
pub use __afl_map_size as EDGES_MAP_PTR_NUM;

#[cfg(any(
feature = "sancov_pcguard_edges",
feature = "sancov_pcguard_hitcounts",
feature = "sancov_ngram4",
feature = "sancov_ctx"
))]
use libafl::observers::StdMapObserver;
#[cfg(any(
feature = "sancov_pcguard_edges",
feature = "sancov_pcguard_hitcounts",
feature = "sancov_ngram4",
feature = "sancov_ctx"
))]
use libafl_bolts::ownedref::OwnedMutSlice;

/// Gets the edges map from the `EDGES_MAP_PTR` raw pointer.
/// Assumes a `len` of `EDGES_MAP_PTR_NUM`.
/// Assumes a `len` of at least `EDGES_MAP_PTR_MAX`.
///
/// # Safety
///
/// This function will crash if `edges_map_mut_ptr` is not a valid pointer.
/// The [`edges_max_num`] needs to be smaller than, or equal to the size of the map.
#[must_use]
#[cfg(any(
feature = "sancov_pcguard_edges",
feature = "sancov_pcguard_hitcounts",
feature = "sancov_ngram4",
feature = "sancov_ctx"
))]
pub unsafe fn edges_map_mut_slice<'a>() -> OwnedMutSlice<'a, u8> {
OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), edges_max_num())
}
Expand Down Expand Up @@ -106,6 +130,12 @@ pub unsafe fn edges_map_mut_slice<'a>() -> OwnedMutSlice<'a, u8> {
///
/// # Safety
/// This will dereference [`edges_map_mut_ptr`] and crash if it is not a valid address.
#[cfg(any(
feature = "sancov_pcguard_edges",
feature = "sancov_pcguard_hitcounts",
feature = "sancov_ngram4",
feature = "sancov_ctx"
))]
pub unsafe fn std_edges_map_observer<'a, S>(name: S) -> StdMapObserver<'a, u8, false>
where
S: Into<Cow<'static, str>>,
Expand Down Expand Up @@ -137,7 +167,7 @@ pub fn edges_max_num() -> usize {
} else {
#[cfg(feature = "pointer_maps")]
{
EDGES_MAP_PTR_NUM
EDGES_MAP_SIZE_MAX // the upper bound
}
#[cfg(not(feature = "pointer_maps"))]
{
Expand All @@ -163,7 +193,7 @@ mod swap {
use libafl_bolts::{ownedref::OwnedMutSlice, AsSliceMut, Named};
use serde::{Deserialize, Serialize};

use super::{EDGES_MAP_PTR, EDGES_MAP_PTR_NUM};
use super::EDGES_MAP_PTR;

/// Observer to be used with `DiffExecutor`s when executing a differential target that shares
/// the AFL map in order to swap out the maps (and thus allow for map observing the two targets
Expand Down Expand Up @@ -243,7 +273,6 @@ mod swap {
let slice = self.first_map.as_slice_mut();
unsafe {
EDGES_MAP_PTR = slice.as_mut_ptr();
EDGES_MAP_PTR_NUM = slice.len();
}
Ok(())
}
Expand All @@ -252,7 +281,6 @@ mod swap {
let slice = self.second_map.as_slice_mut();
unsafe {
EDGES_MAP_PTR = slice.as_mut_ptr();
EDGES_MAP_PTR_NUM = slice.len();
}
Ok(())
}
Expand Down
Loading
Loading