Restrict more on edges map API (#2117)

* fix

* fix

* feature guard

* use

* cannnot find

* fmt

* more

* fix

* fix

* more

* fucking fmt just shut

* rename and change stuff

* fix

* fix

* fixxxxxxxxxx
This commit is contained in:
Dongjia "toka" Zhang 2024-04-29 16:28:40 +02:00 committed by GitHub
parent b0248461e2
commit 50f14d44fa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 122 additions and 68 deletions

View File

@ -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. ## 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. 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`). 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`).

View File

@ -57,7 +57,7 @@ On your fuzzer side, you can allocate a shared memory region and make the `EDGES
```rust,ignore ```rust,ignore
let mut shmem; let mut shmem;
unsafe{ unsafe{
shmem = StdShMemProvider::new().unwrap().new_shmem(MAX_EDGES_NUM).unwrap(); shmem = StdShMemProvider::new().unwrap().new_shmem(EDGES_MAP_SIZE_IN_USE).unwrap();
} }
let shmem_buf = shmem.as_slice_mut(); let shmem_buf = shmem.as_slice_mut();
unsafe{ unsafe{

View File

@ -169,7 +169,7 @@ from libafl_target's `EDGES_MAP`.
In the future, instead of using: In the future, instead of using:
```rust,ignore ```rust,ignore
let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] }; let edges = unsafe { &mut EDGES_MAP[0..EDGES_MAP_SIZE_IN_USE] };
let edges_observer = StdMapObserver::new("edges", edges); let edges_observer = StdMapObserver::new("edges", edges);
``` ```

View File

@ -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")] #[cfg(feature = "multimap")]
let ( let (
@ -202,7 +202,7 @@ pub fn main() {
// The Monitor trait define how the fuzzer stats are displayed to the user // The Monitor trait define how the fuzzer stats are displayed to the user
#[cfg(not(feature = "tui"))] #[cfg(not(feature = "tui"))]
let mon = SimpleMonitor::new(|s| println!("{s}")); let mon = SimpleMonitor::with_user_monitor(|s| println!("{s}"));
#[cfg(feature = "tui")] #[cfg(feature = "tui")]
let ui = TuiUI::new(String::from("Baby Fuzzer"), false); let ui = TuiUI::new(String::from("Baby Fuzzer"), false);
#[cfg(feature = "tui")] #[cfg(feature = "tui")]

View File

@ -39,6 +39,7 @@ use libafl::{
use libafl_bolts::{ use libafl_bolts::{
current_nanos, current_time, current_nanos, current_time,
os::{dup2, unix_signals::Signal}, os::{dup2, unix_signals::Signal},
ownedref::OwnedMutSlice,
rands::StdRand, rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider}, shmem::{ShMemProvider, StdShMemProvider},
tuples::{tuple_list, Merge}, tuples::{tuple_list, Merge},
@ -47,9 +48,9 @@ use libafl_bolts::{
use libafl_qemu::{ use libafl_qemu::{
// asan::{init_with_asan, QemuAsanHelper}, // asan::{init_with_asan, QemuAsanHelper},
cmplog::{CmpLogObserver, QemuCmpLogHelper}, cmplog::{CmpLogObserver, QemuCmpLogHelper},
edges::edges_map_mut_slice, edges::edges_map_mut_ptr,
edges::QemuEdgeCoverageHelper, edges::QemuEdgeCoverageHelper,
edges::MAX_EDGES_NUM, edges::{EDGES_MAP_SIZE_IN_USE, MAX_EDGES_FOUND},
elf::EasyElf, elf::EasyElf,
filter_qemu_args, filter_qemu_args,
hooks::QemuHooks, hooks::QemuHooks,
@ -257,8 +258,8 @@ fn fuzz(
let edges_observer = unsafe { let edges_observer = unsafe {
HitcountsMapObserver::new(VariableMapObserver::from_mut_slice( HitcountsMapObserver::new(VariableMapObserver::from_mut_slice(
"edges", "edges",
edges_map_mut_slice(), OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), EDGES_MAP_SIZE_IN_USE),
addr_of_mut!(MAX_EDGES_NUM), addr_of_mut!(MAX_EDGES_FOUND),
)) ))
.track_indices() .track_indices()
}; };

View File

@ -32,7 +32,7 @@ use libafl_bolts::{
tuples::{tuple_list, Merge}, tuples::{tuple_list, Merge},
AsSlice, AsSlice,
}; };
use libafl_targets::{libfuzzer_initialize, libfuzzer_test_one_input, EDGES_MAP, MAX_EDGES_NUM}; use libafl_targets::{libfuzzer_initialize, libfuzzer_test_one_input, EDGES_MAP, MAX_EDGES_FOUND};
use mimalloc::MiMalloc; use mimalloc::MiMalloc;
#[global_allocator] #[global_allocator]
@ -83,7 +83,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
HitcountsMapObserver::new(StdMapObserver::from_mut_ptr( HitcountsMapObserver::new(StdMapObserver::from_mut_ptr(
"edges", "edges",
EDGES_MAP.as_mut_ptr(), EDGES_MAP.as_mut_ptr(),
MAX_EDGES_NUM, MAX_EDGES_FOUND,
)) ))
.track_indices() .track_indices()
}; };

View File

@ -34,7 +34,8 @@ use libafl_bolts::{
AsSlice, AsSlice,
}; };
use libafl_targets::{ use libafl_targets::{
libfuzzer_initialize, libfuzzer_test_one_input, ACCOUNTING_MEMOP_MAP, EDGES_MAP, MAX_EDGES_NUM, libfuzzer_initialize, libfuzzer_test_one_input, ACCOUNTING_MEMOP_MAP, EDGES_MAP,
MAX_EDGES_FOUND,
}; };
use mimalloc::MiMalloc; use mimalloc::MiMalloc;
@ -139,7 +140,7 @@ pub extern "C" fn libafl_main() {
let mut run_client = |state: Option<_>, mut restarting_mgr, _core_id| { let mut run_client = |state: Option<_>, mut restarting_mgr, _core_id| {
// Create an observation channel using the coverage map // Create an observation channel using the coverage map
let edges_observer = HitcountsMapObserver::new(unsafe { let edges_observer = HitcountsMapObserver::new(unsafe {
StdMapObserver::from_mut_ptr("edges", EDGES_MAP.as_mut_ptr(), MAX_EDGES_NUM) StdMapObserver::from_mut_ptr("edges", EDGES_MAP.as_mut_ptr(), MAX_EDGES_FOUND)
}) })
.track_indices(); .track_indices();

View File

@ -32,7 +32,7 @@ use libafl_bolts::{
tuples::{tuple_list, Merge}, tuples::{tuple_list, Merge},
AsSlice, AsSlice,
}; };
use libafl_targets::{libfuzzer_initialize, libfuzzer_test_one_input, EDGES_MAP, MAX_EDGES_NUM}; use libafl_targets::{libfuzzer_initialize, libfuzzer_test_one_input, EDGES_MAP, MAX_EDGES_FOUND};
use mimalloc::MiMalloc; use mimalloc::MiMalloc;
#[global_allocator] #[global_allocator]
@ -97,7 +97,7 @@ fn fuzz(
HitcountsMapObserver::new(StdMapObserver::from_mut_ptr( HitcountsMapObserver::new(StdMapObserver::from_mut_ptr(
"edges", "edges",
EDGES_MAP.as_mut_ptr(), EDGES_MAP.as_mut_ptr(),
MAX_EDGES_NUM, MAX_EDGES_FOUND,
)) ))
.track_indices() .track_indices()
}; };

View File

@ -32,7 +32,7 @@ use libafl_bolts::{
tuples::{tuple_list, Merge}, tuples::{tuple_list, Merge},
AsSlice, AsSlice,
}; };
use libafl_targets::{libfuzzer_initialize, libfuzzer_test_one_input, EDGES_MAP, MAX_EDGES_NUM}; use libafl_targets::{libfuzzer_initialize, libfuzzer_test_one_input, EDGES_MAP, MAX_EDGES_FOUND};
use mimalloc::MiMalloc; use mimalloc::MiMalloc;
#[global_allocator] #[global_allocator]
@ -81,7 +81,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
HitcountsMapObserver::new(StdMapObserver::from_mut_ptr( HitcountsMapObserver::new(StdMapObserver::from_mut_ptr(
"edges", "edges",
EDGES_MAP.as_mut_ptr(), EDGES_MAP.as_mut_ptr(),
MAX_EDGES_NUM, MAX_EDGES_FOUND,
)) ))
.track_indices() .track_indices()
}; };

View File

@ -38,7 +38,7 @@ vergen = { version = "8.2.1", features = ["build", "cargo", "git", "gitcl", "rus
[dependencies] [dependencies]
clap = { version = "4.3.0", features = ["derive", "string"]} clap = { version = "4.3.0", features = ["derive", "string"]}
libafl = { path = "../../libafl/" } libafl = { path = "../../libafl/" }
libafl_bolts = { path = "../../libafl_bolts/" } libafl_bolts = { path = "../../libafl_bolts/", features = ["errors_backtrace"] }
libafl_qemu = { path = "../../libafl_qemu/", features = ["usermode"] } libafl_qemu = { path = "../../libafl_qemu/", features = ["usermode"] }
log = {version = "0.4.20" } log = {version = "0.4.20" }
nix = { version = "0.27", features = ["fs"] } nix = { version = "0.27", features = ["fs"] }

View File

@ -34,12 +34,13 @@ use libafl_bolts::shmem::StdShMemProvider;
use libafl_bolts::{ use libafl_bolts::{
core_affinity::CoreId, core_affinity::CoreId,
current_nanos, current_nanos,
ownedref::OwnedMutSlice,
rands::StdRand, rands::StdRand,
tuples::{tuple_list, Merge}, tuples::{tuple_list, Merge},
}; };
use libafl_qemu::{ use libafl_qemu::{
cmplog::CmpLogObserver, cmplog::CmpLogObserver,
edges::{edges_map_mut_slice, MAX_EDGES_NUM}, edges::{edges_map_mut_ptr, EDGES_MAP_SIZE_IN_USE, MAX_EDGES_FOUND},
helpers::QemuHelperTuple, helpers::QemuHelperTuple,
Qemu, QemuExecutor, QemuHooks, Qemu, QemuExecutor, QemuHooks,
}; };
@ -78,8 +79,8 @@ impl<'a, M: Monitor> Instance<'a, M> {
let edges_observer = unsafe { let edges_observer = unsafe {
HitcountsMapObserver::new(VariableMapObserver::from_mut_slice( HitcountsMapObserver::new(VariableMapObserver::from_mut_slice(
"edges", "edges",
edges_map_mut_slice(), OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), EDGES_MAP_SIZE_IN_USE),
addr_of_mut!(MAX_EDGES_NUM), addr_of_mut!(MAX_EDGES_FOUND),
)) ))
.track_indices() .track_indices()
}; };

View File

@ -22,6 +22,7 @@ use libafl::{
use libafl_bolts::{ use libafl_bolts::{
core_affinity::Cores, core_affinity::Cores,
current_nanos, current_nanos,
ownedref::OwnedMutSlice,
rands::StdRand, rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider}, shmem::{ShMemProvider, StdShMemProvider},
tuples::tuple_list, tuples::tuple_list,
@ -29,7 +30,7 @@ use libafl_bolts::{
use libafl_qemu::{ use libafl_qemu::{
breakpoint::Breakpoint, breakpoint::Breakpoint,
command::{Command, EmulatorMemoryChunk, EndCommand, StartCommand}, command::{Command, EmulatorMemoryChunk, EndCommand, StartCommand},
edges::{edges_map_mut_slice, QemuEdgeCoverageHelper, MAX_EDGES_NUM}, edges::{edges_map_mut_ptr, QemuEdgeCoverageHelper, EDGES_MAP_SIZE_IN_USE, MAX_EDGES_FOUND},
elf::EasyElf, elf::EasyElf,
emu::Emulator, emu::Emulator,
executor::{stateful::StatefulQemuExecutor, QemuExecutorState}, executor::{stateful::StatefulQemuExecutor, QemuExecutorState},
@ -154,8 +155,8 @@ pub fn fuzz() {
let edges_observer = unsafe { let edges_observer = unsafe {
HitcountsMapObserver::new(VariableMapObserver::from_mut_slice( HitcountsMapObserver::new(VariableMapObserver::from_mut_slice(
"edges", "edges",
edges_map_mut_slice(), OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), EDGES_MAP_SIZE_IN_USE),
addr_of_mut!(MAX_EDGES_NUM), addr_of_mut!(MAX_EDGES_FOUND),
)) ))
.track_indices() .track_indices()
}; };

View File

@ -23,13 +23,14 @@ use libafl_bolts::{
core_affinity::Cores, core_affinity::Cores,
current_nanos, current_nanos,
os::unix_signals::Signal, os::unix_signals::Signal,
ownedref::OwnedMutSlice,
rands::StdRand, rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider}, shmem::{ShMemProvider, StdShMemProvider},
tuples::tuple_list, tuples::tuple_list,
AsSlice, AsSlice,
}; };
use libafl_qemu::{ use libafl_qemu::{
edges::{edges_map_mut_slice, QemuEdgeCoverageHelper, MAX_EDGES_NUM}, edges::{edges_map_mut_ptr, QemuEdgeCoverageHelper, EDGES_MAP_SIZE_IN_USE, MAX_EDGES_FOUND},
elf::EasyElf, elf::EasyElf,
emu::Qemu, emu::Qemu,
QemuExecutor, QemuExitReason, QemuExitReasonError, QemuHooks, QemuShutdownCause, Regs, QemuExecutor, QemuExitReason, QemuExitReasonError, QemuHooks, QemuShutdownCause, Regs,
@ -161,8 +162,8 @@ pub fn fuzz() {
let edges_observer = unsafe { let edges_observer = unsafe {
HitcountsMapObserver::new(VariableMapObserver::from_mut_slice( HitcountsMapObserver::new(VariableMapObserver::from_mut_slice(
"edges", "edges",
edges_map_mut_slice(), OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), EDGES_MAP_SIZE_IN_USE),
addr_of_mut!(MAX_EDGES_NUM), addr_of_mut!(MAX_EDGES_FOUND),
)) ))
.track_indices() .track_indices()
}; };

View File

@ -22,12 +22,13 @@ use libafl::{
use libafl_bolts::{ use libafl_bolts::{
core_affinity::Cores, core_affinity::Cores,
current_nanos, current_nanos,
ownedref::OwnedMutSlice,
rands::StdRand, rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider}, shmem::{ShMemProvider, StdShMemProvider},
tuples::tuple_list, tuples::tuple_list,
}; };
use libafl_qemu::{ use libafl_qemu::{
edges::{edges_map_mut_slice, QemuEdgeCoverageHelper, MAX_EDGES_NUM}, edges::{edges_map_mut_ptr, QemuEdgeCoverageHelper, EDGES_MAP_SIZE_IN_USE, MAX_EDGES_FOUND},
emu::Emulator, emu::Emulator,
executor::{stateful::StatefulQemuExecutor, QemuExecutorState}, executor::{stateful::StatefulQemuExecutor, QemuExecutorState},
EmuExitReasonError, FastSnapshotManager, HandlerError, HandlerResult, QemuHooks, EmuExitReasonError, FastSnapshotManager, HandlerError, HandlerResult, QemuHooks,
@ -95,8 +96,8 @@ pub fn fuzz() {
let edges_observer = unsafe { let edges_observer = unsafe {
HitcountsMapObserver::new(VariableMapObserver::from_mut_slice( HitcountsMapObserver::new(VariableMapObserver::from_mut_slice(
"edges", "edges",
edges_map_mut_slice(), OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), EDGES_MAP_SIZE_IN_USE),
addr_of_mut!(MAX_EDGES_NUM), addr_of_mut!(MAX_EDGES_FOUND),
)) ))
.track_indices() .track_indices()
}; };

View File

@ -6,8 +6,8 @@ use libafl_qemu_sys::GuestAddr;
#[cfg(emulation_mode = "systemmode")] #[cfg(emulation_mode = "systemmode")]
use libafl_qemu_sys::GuestPhysAddr; use libafl_qemu_sys::GuestPhysAddr;
pub use libafl_targets::{ pub use libafl_targets::{
edges_map_mut_ptr, edges_map_mut_slice, edges_max_num, std_edges_map_observer, EDGES_MAP, edges_map_mut_ptr, EDGES_MAP, EDGES_MAP_PTR, EDGES_MAP_SIZE_IN_USE, EDGES_MAP_SIZE_MAX,
EDGES_MAP_PTR, EDGES_MAP_PTR_NUM, EDGES_MAP_SIZE_IN_USE, MAX_EDGES_NUM, MAX_EDGES_FOUND,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -553,18 +553,18 @@ where
match meta.map.entry((src, dest)) { match meta.map.entry((src, dest)) {
Entry::Occupied(e) => { Entry::Occupied(e) => {
let id = *e.get(); let id = *e.get();
let nxt = (id as usize + 1) & (EDGES_MAP_SIZE_IN_USE - 1); let nxt = (id as usize + 1) & (EDGES_MAP_SIZE_MAX - 1);
unsafe { unsafe {
MAX_EDGES_NUM = max(MAX_EDGES_NUM, nxt); MAX_EDGES_FOUND = max(MAX_EDGES_FOUND, nxt);
} }
Some(id) Some(id)
} }
Entry::Vacant(e) => { Entry::Vacant(e) => {
let id = meta.current_id; let id = meta.current_id;
e.insert(id); e.insert(id);
meta.current_id = (id + 1) & (EDGES_MAP_SIZE_IN_USE as u64 - 1); meta.current_id = (id + 1) & (EDGES_MAP_SIZE_MAX as u64 - 1);
unsafe { unsafe {
MAX_EDGES_NUM = meta.current_id as usize; MAX_EDGES_FOUND = meta.current_id as usize;
} }
// GuestAddress is u32 for 32 bit guests // GuestAddress is u32 for 32 bit guests
#[allow(clippy::unnecessary_cast)] #[allow(clippy::unnecessary_cast)]
@ -619,7 +619,7 @@ where
} }
// GuestAddress is u32 for 32 bit guests // GuestAddress is u32 for 32 bit guests
#[allow(clippy::unnecessary_cast)] #[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) { pub extern "C" fn trace_edge_hitcount_ptr(_: *const (), id: u64) {
@ -692,7 +692,7 @@ where
pub extern "C" fn trace_block_transition_hitcount(_: *const (), id: u64) { pub extern "C" fn trace_block_transition_hitcount(_: *const (), id: u64) {
unsafe { unsafe {
PREV_LOC.with(|prev_loc| { 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); let entry = EDGES_MAP_PTR.add(x);
*entry = (*entry).wrapping_add(1); *entry = (*entry).wrapping_add(1);
*prev_loc.get() = id.overflowing_shr(1).0; *prev_loc.get() = id.overflowing_shr(1).0;
@ -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) { pub extern "C" fn trace_block_transition_single(_: *const (), id: u64) {
unsafe { unsafe {
PREV_LOC.with(|prev_loc| { 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); let entry = EDGES_MAP_PTR.add(x);
*entry = 1; *entry = 1;
*prev_loc.get() = id.overflowing_shr(1).0; *prev_loc.get() = id.overflowing_shr(1).0;

View File

@ -18,7 +18,7 @@ use libafl::{
scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator},
token_mutations::{I2SRandReplace, Tokens}, token_mutations::{I2SRandReplace, Tokens},
}, },
observers::{CanTrack, HitcountsMapObserver, TimeObserver}, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver},
schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler},
stages::{ShadowTracingStage, StdMutationalStage}, stages::{ShadowTracingStage, StdMutationalStage},
state::{HasCorpus, StdState}, state::{HasCorpus, StdState},
@ -27,12 +27,13 @@ use libafl::{
use libafl_bolts::{ use libafl_bolts::{
core_affinity::Cores, core_affinity::Cores,
current_nanos, current_nanos,
ownedref::OwnedMutSlice,
rands::StdRand, rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider}, shmem::{ShMemProvider, StdShMemProvider},
tuples::{tuple_list, Merge, Referenceable}, tuples::{tuple_list, Merge, Referenceable},
AsSlice, AsSlice,
}; };
use libafl_targets::{std_edges_map_observer, CmpLogObserver}; use libafl_targets::{edges_map_mut_ptr, CmpLogObserver};
use typed_builder::TypedBuilder; use typed_builder::TypedBuilder;
use crate::{CORPUS_CACHE_SIZE, DEFAULT_TIMEOUT_SECS}; use crate::{CORPUS_CACHE_SIZE, DEFAULT_TIMEOUT_SECS};
@ -72,6 +73,9 @@ where
/// Bytes harness /// Bytes harness
#[builder(setter(strip_option))] #[builder(setter(strip_option))]
harness: Option<H>, 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` /// Fuzz `iterations` number of times, instead of indefinitely; implies use of `fuzz_loop_for`
#[builder(default = None)] #[builder(default = None)]
iterations: Option<u64>, iterations: Option<u64>,
@ -148,9 +152,13 @@ where
let time_observer = time_observer.clone(); let time_observer = time_observer.clone();
// Create an observation channel using the coverage map // Create an observation channel using the coverage map
let edges_observer = let edges_observer = HitcountsMapObserver::new(unsafe {
HitcountsMapObserver::new(unsafe { std_edges_map_observer("edges") }) StdMapObserver::from_mut_slice(
.track_indices(); "edges",
OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), self.map_size),
)
})
.track_indices();
let cmplog_observer = CmpLogObserver::new("cmplog", true); let cmplog_observer = CmpLogObserver::new("cmplog", true);

View File

@ -30,6 +30,7 @@ use libafl::{
use libafl_bolts::{ use libafl_bolts::{
core_affinity::Cores, core_affinity::Cores,
current_nanos, current_nanos,
ownedref::OwnedMutSlice,
rands::StdRand, rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider}, shmem::{ShMemProvider, StdShMemProvider},
tuples::{tuple_list, Merge, Referenceable}, tuples::{tuple_list, Merge, Referenceable},
@ -39,7 +40,7 @@ pub use libafl_qemu::emu::Qemu;
#[cfg(not(any(feature = "mips", feature = "hexagon")))] #[cfg(not(any(feature = "mips", feature = "hexagon")))]
use libafl_qemu::QemuCmpLogHelper; use libafl_qemu::QemuCmpLogHelper;
use libafl_qemu::{edges, QemuEdgeCoverageHelper, QemuExecutor, QemuHooks}; 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 typed_builder::TypedBuilder;
use crate::{CORPUS_CACHE_SIZE, DEFAULT_TIMEOUT_SECS}; use crate::{CORPUS_CACHE_SIZE, DEFAULT_TIMEOUT_SECS};
@ -159,8 +160,11 @@ where
let edges_observer = unsafe { let edges_observer = unsafe {
HitcountsMapObserver::new(VariableMapObserver::from_mut_slice( HitcountsMapObserver::new(VariableMapObserver::from_mut_slice(
"edges", "edges",
edges_map_mut_slice(), OwnedMutSlice::from_raw_parts_mut(
addr_of_mut!(edges::MAX_EDGES_NUM), edges_map_mut_ptr(),
edges::EDGES_MAP_SIZE_IN_USE,
),
addr_of_mut!(edges::MAX_EDGES_FOUND),
)) ))
.track_indices() .track_indices()
}; };

View File

@ -1,5 +1,11 @@
//! Coverage maps as static mut array //! 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; use alloc::borrow::Cow;
#[cfg(any(target_os = "linux", target_vendor = "apple"))] #[cfg(any(target_os = "linux", target_vendor = "apple"))]
@ -22,8 +28,10 @@ pub use __ddg_area_ptr_local as DDG_MAP;
pub static mut __afl_acc_memop_ptr_local: [u32; ACCOUNTING_MAP_SIZE] = [0; ACCOUNTING_MAP_SIZE]; pub static mut __afl_acc_memop_ptr_local: [u32; ACCOUNTING_MAP_SIZE] = [0; ACCOUNTING_MAP_SIZE];
pub use __afl_acc_memop_ptr_local as ACCOUNTING_MEMOP_MAP; pub use __afl_acc_memop_ptr_local as ACCOUNTING_MEMOP_MAP;
/// The max count of edges tracked. /// The max count of edges found.
pub static mut MAX_EDGES_NUM: usize = 0; /// This is either computed during the compilation time or at runtime (in this case this is used to shrink the map).
/// You can use this for the initial map size for the observer only if you compute this time at compilation time.
pub static mut MAX_EDGES_FOUND: usize = 0;
extern "C" { extern "C" {
/// The area pointer points to the edges map. /// The area pointer points to the edges map.
@ -60,21 +68,40 @@ pub fn autotokens() -> Result<Tokens, Error> {
} }
} }
/// The size of the map for edges. /// The actual size we use for the map of edges.
/// This is used for forkserver backend
#[no_mangle] #[no_mangle]
pub static mut __afl_map_size: usize = EDGES_MAP_SIZE_IN_USE; 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; 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; use libafl_bolts::ownedref::OwnedMutSlice;
/// Gets the edges map from the `EDGES_MAP_PTR` raw pointer. /// 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 /// # Safety
/// ///
/// This function will crash if `edges_map_mut_ptr` is not a valid pointer. /// 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. /// The [`edges_max_num`] needs to be smaller than, or equal to the size of the map.
#[must_use] #[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> { pub unsafe fn edges_map_mut_slice<'a>() -> OwnedMutSlice<'a, u8> {
OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), edges_max_num()) OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), edges_max_num())
} }
@ -84,11 +111,11 @@ pub unsafe fn edges_map_mut_slice<'a>() -> OwnedMutSlice<'a, u8> {
/// ///
/// ```rust,ignore /// ```rust,ignore
/// use libafl::observers::StdMapObserver; /// use libafl::observers::StdMapObserver;
/// use libafl_targets::{EDGES_MAP, MAX_EDGES_NUM}; /// use libafl_targets::{EDGES_MAP, EDGES_MAP_SIZE_IN_USE};
/// ///
/// #[cfg(not(feature = "pointer_maps"))] /// #[cfg(not(feature = "pointer_maps"))]
/// let observer = unsafe { /// let observer = unsafe {
/// StdMapObserver::from_mut_ptr("edges", EDGES_MAP.as_mut_ptr(), MAX_EDGES_NUM) /// StdMapObserver::from_mut_ptr("edges", EDGES_MAP.as_mut_ptr(), EDGES_MAP_SIZE_IN_USE)
/// }; /// };
/// ``` /// ```
/// ///
@ -106,6 +133,12 @@ pub unsafe fn edges_map_mut_slice<'a>() -> OwnedMutSlice<'a, u8> {
/// ///
/// # Safety /// # Safety
/// This will dereference [`edges_map_mut_ptr`] and crash if it is not a valid address. /// 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> pub unsafe fn std_edges_map_observer<'a, S>(name: S) -> StdMapObserver<'a, u8, false>
where where
S: Into<Cow<'static, str>>, S: Into<Cow<'static, str>>,
@ -129,15 +162,21 @@ pub fn edges_map_mut_ptr() -> *mut u8 {
} }
/// Gets the current maximum number of edges tracked. /// Gets the current maximum number of edges tracked.
#[cfg(any(
feature = "sancov_pcguard_edges",
feature = "sancov_pcguard_hitcounts",
feature = "sancov_ngram4",
feature = "sancov_ctx"
))]
#[must_use] #[must_use]
pub fn edges_max_num() -> usize { pub fn edges_max_num() -> usize {
unsafe { unsafe {
if MAX_EDGES_NUM > 0 { if MAX_EDGES_FOUND > 0 {
MAX_EDGES_NUM MAX_EDGES_FOUND
} else { } else {
#[cfg(feature = "pointer_maps")] #[cfg(feature = "pointer_maps")]
{ {
EDGES_MAP_PTR_NUM EDGES_MAP_SIZE_MAX // the upper bound
} }
#[cfg(not(feature = "pointer_maps"))] #[cfg(not(feature = "pointer_maps"))]
{ {
@ -163,7 +202,7 @@ mod swap {
use libafl_bolts::{ownedref::OwnedMutSlice, AsSliceMut, Named}; use libafl_bolts::{ownedref::OwnedMutSlice, AsSliceMut, Named};
use serde::{Deserialize, Serialize}; 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 /// 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 /// the AFL map in order to swap out the maps (and thus allow for map observing the two targets
@ -243,7 +282,6 @@ mod swap {
let slice = self.first_map.as_slice_mut(); let slice = self.first_map.as_slice_mut();
unsafe { unsafe {
EDGES_MAP_PTR = slice.as_mut_ptr(); EDGES_MAP_PTR = slice.as_mut_ptr();
EDGES_MAP_PTR_NUM = slice.len();
} }
Ok(()) Ok(())
} }
@ -252,7 +290,6 @@ mod swap {
let slice = self.second_map.as_slice_mut(); let slice = self.second_map.as_slice_mut();
unsafe { unsafe {
EDGES_MAP_PTR = slice.as_mut_ptr(); EDGES_MAP_PTR = slice.as_mut_ptr();
EDGES_MAP_PTR_NUM = slice.len();
} }
Ok(()) Ok(())
} }

View File

@ -16,11 +16,11 @@ use libafl::executors::{hooks::ExecutorHook, HasObservers};
feature = "sancov_ngram4", feature = "sancov_ngram4",
))] ))]
use crate::coverage::EDGES_MAP; use crate::coverage::EDGES_MAP;
use crate::coverage::MAX_EDGES_NUM; use crate::coverage::MAX_EDGES_FOUND;
#[cfg(feature = "pointer_maps")]
use crate::coverage::{EDGES_MAP_PTR, EDGES_MAP_PTR_NUM};
#[cfg(feature = "sancov_ngram4")] #[cfg(feature = "sancov_ngram4")]
use crate::EDGES_MAP_SIZE_IN_USE; use crate::EDGES_MAP_SIZE_IN_USE;
#[cfg(feature = "pointer_maps")]
use crate::{coverage::EDGES_MAP_PTR, EDGES_MAP_SIZE_MAX};
#[cfg(all(feature = "sancov_pcguard_edges", feature = "sancov_pcguard_hitcounts"))] #[cfg(all(feature = "sancov_pcguard_edges", feature = "sancov_pcguard_hitcounts"))]
#[cfg(not(any(doc, feature = "clippy")))] #[cfg(not(any(doc, feature = "clippy")))]
@ -263,7 +263,6 @@ pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard_init(mut start: *mut u32
#[cfg(feature = "pointer_maps")] #[cfg(feature = "pointer_maps")]
if EDGES_MAP_PTR.is_null() { if EDGES_MAP_PTR.is_null() {
EDGES_MAP_PTR = EDGES_MAP.as_mut_ptr(); EDGES_MAP_PTR = EDGES_MAP.as_mut_ptr();
EDGES_MAP_PTR_NUM = EDGES_MAP.len();
} }
if start == stop || *start != 0 { if start == stop || *start != 0 {
@ -271,17 +270,17 @@ pub unsafe extern "C" fn __sanitizer_cov_trace_pc_guard_init(mut start: *mut u32
} }
while start < stop { while start < stop {
*start = MAX_EDGES_NUM as u32; *start = MAX_EDGES_FOUND as u32;
start = start.offset(1); start = start.offset(1);
#[cfg(feature = "pointer_maps")] #[cfg(feature = "pointer_maps")]
{ {
MAX_EDGES_NUM = MAX_EDGES_NUM.wrapping_add(1) % EDGES_MAP_PTR_NUM; MAX_EDGES_FOUND = MAX_EDGES_FOUND.wrapping_add(1) % EDGES_MAP_SIZE_MAX;
} }
#[cfg(not(feature = "pointer_maps"))] #[cfg(not(feature = "pointer_maps"))]
{ {
MAX_EDGES_NUM = MAX_EDGES_NUM.wrapping_add(1); MAX_EDGES_FOUND = MAX_EDGES_FOUND.wrapping_add(1);
assert!((MAX_EDGES_NUM <= EDGES_MAP.len()), "The number of edges reported by SanitizerCoverage exceed the size of the edges map ({}). Use the LIBAFL_EDGES_MAP_SIZE_IN_USE env to increase it at compile time.", EDGES_MAP.len()); assert!((MAX_EDGES_FOUND <= EDGES_MAP.len()), "The number of edges reported by SanitizerCoverage exceed the size of the edges map ({}). Use the LIBAFL_EDGES_MAP_SIZE_IN_USE env to increase it at compile time.", EDGES_MAP.len());
} }
} }
} }