diff --git a/fuzzers/baby/baby_no_std/src/main.rs b/fuzzers/baby/baby_no_std/src/main.rs index 58b5acc28a..826fc7b90d 100644 --- a/fuzzers/baby/baby_no_std/src/main.rs +++ b/fuzzers/baby/baby_no_std/src/main.rs @@ -33,6 +33,7 @@ use static_alloc::Bump; #[global_allocator] static A: Bump<[u8; 512 * 1024 * 1024]> = Bump::uninit(); +#[cfg(not(test))] #[panic_handler] fn panic(_info: &PanicInfo) -> ! { #[cfg(unix)] diff --git a/fuzzers/others/sqlite_centralized_multi_machine/build.sh b/fuzzers/others/sqlite_centralized_multi_machine/build.sh index 3edfe548fe..7ca12f128f 100755 --- a/fuzzers/others/sqlite_centralized_multi_machine/build.sh +++ b/fuzzers/others/sqlite_centralized_multi_machine/build.sh @@ -6,14 +6,14 @@ if [ ! -d "sqlite3" ]; then find ./sqlite3 -name "*.test" -exec cp {} corpus/ \; fi -if [ "$1" = "release" ]; then - cargo build --release -else +if [ "$1" = "d" ]; then cargo build +else + cargo build --release fi -export CC=`pwd`/target/debug/libafl_cc -export CXX=`pwd`/target/debug/libafl_cxx +export CC=`pwd`/target/release/libafl_cc +export CXX=`pwd`/target/release/libafl_cxx export CFLAGS='--libafl' export CXXFLAGS='--libafl' export CFLAGS="$CFLAGS -DSQLITE_MAX_LENGTH=128000000 \ diff --git a/fuzzers/others/sqlite_centralized_multi_machine/run_parent.sh b/fuzzers/others/sqlite_centralized_multi_machine/run_parent.sh index 105b1e3bce..7ef7721d0f 100755 --- a/fuzzers/others/sqlite_centralized_multi_machine/run_parent.sh +++ b/fuzzers/others/sqlite_centralized_multi_machine/run_parent.sh @@ -1,3 +1,3 @@ #!/bin/bash -./ossfuzz --cores 4-7 --input ./corpus +./ossfuzz --cores 0-1 --input ./corpus diff --git a/fuzzers/sqlite_centralized_multi_machine/Cargo.toml b/fuzzers/sqlite_centralized_multi_machine/Cargo.toml new file mode 100644 index 0000000000..acef08dfc5 --- /dev/null +++ b/fuzzers/sqlite_centralized_multi_machine/Cargo.toml @@ -0,0 +1,64 @@ +[package] +name = "libfuzzer_libpng_launcher_centralized_multi_machine" +version = "0.12.0" +authors = [ + "Romain Malmain ", + "Andrea Fioraldi ", + "Dominik Maier ", +] +edition = "2021" + +[features] +default = ["std"] +std = [] + +[profile.release] +lto = true +codegen-units = 1 +opt-level = 3 +debug = true + +[build-dependencies] +cc = { version = "1.0", features = ["parallel"] } +which = "6.0" + +[dependencies] +# no llmp compression for now, better perfs. +libafl = { path = "../../libafl", default-features = false, features = [ + "std", + "derive", + "llmp_small_maps", + "llmp_broker_timeouts", + "rand_trait", + "fork", + "prelude", + "gzip", + "regex", + "serdeany_autoreg", + "tui_monitor", + "std", + "derive", + "rand_trait", + "fork", + "prelude", + "gzip", + "regex", + "scalability_introspection", + "multi_machine", + "errors_backtrace", + "dump_state", +] } +libafl_bolts = { path = "../../libafl_bolts", features = ["xxh3"] } +libafl_targets = { path = "../../libafl_targets", features = [ + "sancov_pcguard_hitcounts", + "libfuzzer", +] } +# TODO Include it only when building cc +libafl_cc = { path = "../../libafl_cc" } +clap = { version = "4.0", features = ["derive"] } +mimalloc = { version = "*", default-features = false } +env_logger = "0.11" + +[lib] +name = "libfuzzer_libpng" +crate-type = ["staticlib"] diff --git a/libafl/Cargo.toml b/libafl/Cargo.toml index 88753194fd..872b9f7ecd 100644 --- a/libafl/Cargo.toml +++ b/libafl/Cargo.toml @@ -102,6 +102,9 @@ tcp_compression = ["tcp_manager", "libafl_bolts/gzip"] ## Enable multi-machine support multi_machine = ["tokio", "std", "enumflags2", "ahash/std"] +## Dump state of each client on exit +dump_state = ["std"] + ## Enables the `NaiveTokenizer` and `StacktraceObserver` regex = ["std", "dep:regex"] diff --git a/libafl/src/events/llmp/restarting.rs b/libafl/src/events/llmp/restarting.rs index 1bd66e1312..67846c8741 100644 --- a/libafl/src/events/llmp/restarting.rs +++ b/libafl/src/events/llmp/restarting.rs @@ -177,7 +177,7 @@ where fn on_restart(&mut self, state: &mut S) -> Result<(), Error> { state.on_restart()?; - // First, reset the page to 0 so the next iteration can read read from the beginning of this page + // First, reset the page to 0 so the next iteration can read from the beginning of this page self.staterestorer.reset(); self.staterestorer.save(&( if self.save_state.on_restart() { @@ -595,7 +595,7 @@ where } }; - // If this guy wants to fork, then ignore sigit + // If this guy wants to fork, then ignore sigint #[cfg(any(windows, not(feature = "fork")))] unsafe { #[cfg(windows)] @@ -614,7 +614,7 @@ where #[cfg(any(windows, not(feature = "fork")))] let child_status = child_status.code().unwrap_or_default(); - compiler_fence(Ordering::SeqCst); + compiler_fence(Ordering::SeqCst); // really useful? if child_status == CTRL_C_EXIT || staterestorer.wants_to_exit() { // if ctrl-c is pressed, we end up in this branch diff --git a/libafl/src/events/mod.rs b/libafl/src/events/mod.rs index c6bff54a46..db81bd09c5 100644 --- a/libafl/src/events/mod.rs +++ b/libafl/src/events/mod.rs @@ -34,7 +34,9 @@ pub use broker_hooks::*; #[cfg(feature = "std")] pub use launcher::*; #[cfg(all(unix, feature = "std"))] -use libafl_bolts::os::unix_signals::{siginfo_t, ucontext_t, Handler, Signal, CTRL_C_EXIT}; +use libafl_bolts::os::unix_signals::{siginfo_t, ucontext_t, Handler, Signal}; +#[cfg(all(unix, feature = "std"))] +use libafl_bolts::os::CTRL_C_EXIT; use libafl_bolts::{ current_time, tuples::{Handle, MatchNameRef}, @@ -86,10 +88,7 @@ impl Handler for ShutdownSignalData { _info: &mut siginfo_t, _context: Option<&mut ucontext_t>, ) { - // println!("in handler! {}", std::process::id()); unsafe { - // println!("Exiting from the handler...."); - #[cfg(unix)] libc::_exit(CTRL_C_EXIT); diff --git a/libafl/src/feedbacks/map.rs b/libafl/src/feedbacks/map.rs index 1b78089746..6f99e3505d 100644 --- a/libafl/src/feedbacks/map.rs +++ b/libafl/src/feedbacks/map.rs @@ -225,7 +225,7 @@ where } /// A testcase metadata holding a list of indexes of a map -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr( any(not(feature = "serdeany_autoreg"), miri), allow(clippy::unsafe_derive_deserialize) diff --git a/libafl/src/fuzzer/mod.rs b/libafl/src/fuzzer/mod.rs index 5610f8bc14..15d82f99d0 100644 --- a/libafl/src/fuzzer/mod.rs +++ b/libafl/src/fuzzer/mod.rs @@ -242,8 +242,8 @@ where ) -> Result<(), Error> { let monitor_timeout = STATS_TIMEOUT_DEFAULT; loop { - // log::info!("Starting another fuzz_loop"); manager.maybe_report_progress(state, monitor_timeout)?; + self.fuzz_one(stages, executor, state, manager)?; } } diff --git a/libafl/src/observers/map/mod.rs b/libafl/src/observers/map/mod.rs index d6409a3123..5a7a05de4c 100644 --- a/libafl/src/observers/map/mod.rs +++ b/libafl/src/observers/map/mod.rs @@ -82,8 +82,9 @@ pub use owned_map::*; /// # InMemoryCorpus::::new(), /// # InMemoryCorpus::new(), /// # &mut feedback, -/// # &mut () +/// # &mut (), /// # ).unwrap(); +/// /// # feedback.init_state(&mut state).unwrap(); /// /// let scheduler = IndexesLenTimeMinimizerScheduler::new(&edges_observer, QueueScheduler::new()); diff --git a/libafl_bolts/src/os/windows_exceptions.rs b/libafl_bolts/src/os/windows_exceptions.rs index 278795f32b..1cabf9e984 100644 --- a/libafl_bolts/src/os/windows_exceptions.rs +++ b/libafl_bolts/src/os/windows_exceptions.rs @@ -10,7 +10,6 @@ use core::{ }; use std::os::raw::{c_long, c_void}; -use log::info; use num_enum::FromPrimitive; pub use windows::Win32::{ Foundation::{BOOL, NTSTATUS}, @@ -462,7 +461,7 @@ unsafe fn internal_handle_exception( .unwrap(); match &EXCEPTION_HANDLERS[index] { Some(handler_holder) => { - info!( + log::info!( "{:?}: Handling exception {}", std::process::id(), exception_code @@ -472,7 +471,7 @@ unsafe fn internal_handle_exception( EXCEPTION_CONTINUE_EXECUTION } None => { - info!( + log::info!( "{:?}: No handler for exception {}", std::process::id(), exception_code @@ -601,11 +600,11 @@ pub(crate) unsafe fn setup_ctrl_handler( let result = SetConsoleCtrlHandler(Some(ctrl_handler), true); match result { Ok(()) => { - info!("SetConsoleCtrlHandler succeeded"); + log::info!("SetConsoleCtrlHandler succeeded"); Ok(()) } Err(err) => { - info!("SetConsoleCtrlHandler failed"); + log::info!("SetConsoleCtrlHandler failed"); Err(Error::from(err)) } } @@ -615,7 +614,7 @@ unsafe extern "system" fn ctrl_handler(ctrl_type: u32) -> BOOL { let handler = ptr::read_volatile(addr_of!(CTRL_HANDLER)); match handler { Some(handler_holder) => { - info!("{:?}: Handling ctrl {}", std::process::id(), ctrl_type); + log::info!("{:?}: Handling ctrl {}", std::process::id(), ctrl_type); let handler = &mut *handler_holder.handler.get(); if let Some(ctrl_handler) = handler.as_mut() { (*ctrl_handler).handle(ctrl_type).into() diff --git a/utils/multi_machine_generator/.gitignore b/utils/multi_machine_generator/.gitignore new file mode 100644 index 0000000000..8e392c77d0 --- /dev/null +++ b/utils/multi_machine_generator/.gitignore @@ -0,0 +1,2 @@ +*.txt +*.dot \ No newline at end of file diff --git a/utils/multi_machine_generator/Cargo.toml b/utils/multi_machine_generator/Cargo.toml index 3821b7616c..60ab384cdf 100644 --- a/utils/multi_machine_generator/Cargo.toml +++ b/utils/multi_machine_generator/Cargo.toml @@ -9,3 +9,6 @@ edition = "2021" [dependencies] petgraph = "0.6" +clap = { version = "4.5", features = ["derive"] } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" diff --git a/utils/multi_machine_generator/src/graph.rs b/utils/multi_machine_generator/src/graph.rs index 0cfc59c264..f65703f2cf 100644 --- a/utils/multi_machine_generator/src/graph.rs +++ b/utils/multi_machine_generator/src/graph.rs @@ -1,20 +1,48 @@ -use std::net::SocketAddr; +use std::{ + fmt::{Display, Formatter}, + mem, +}; use petgraph::{graph::NodeIndex, Direction, Graph}; +use serde::Serialize; /// A node of the network -#[derive(Debug, Clone, Default)] -pub struct MultiMachineNode {} +#[derive(Debug, Clone)] +pub struct MultiMachineNode { + addr: String, +} + +/// The final configuration of a node on the network +#[derive(Debug, Clone, Serialize)] +pub struct MultiMachineNodeConfig { + addr: String, + parent: Option, + port: u16, +} /// The tree pub struct MultiMachineTree { - pub graph: Graph, + pub graph: Graph, +} + +pub struct MultiMachineEdge; + +impl Display for MultiMachineEdge { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "") + } +} + +impl Display for MultiMachineNode { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.addr) + } } impl MultiMachineNode { #[must_use] - pub fn new() -> Self { - Self {} + pub fn new(addr: String) -> Self { + Self { addr } } } @@ -25,12 +53,13 @@ impl MultiMachineTree { /// - machines: machines to add. /// - `max_children_per_parent`: each parent will have at most this amount of children #[must_use] - pub fn generate(machines: &[SocketAddr], max_children_per_parent: u64) -> Self { - let mut graph = Graph::::new(); + pub fn generate(machines: &[String], max_children_per_parent: u64) -> Self { + let mut graph = Graph::::new(); let mut machines = Vec::from(machines); + machines.reverse(); - let root = if let Some(_root) = machines.pop() { - graph.add_node(MultiMachineNode::new()) + let root = if let Some(root) = machines.pop() { + graph.add_node(MultiMachineNode::new(root)) } else { return Self { graph }; }; @@ -43,17 +72,17 @@ impl MultiMachineTree { let mut nodes_to_populate_later: Vec = Vec::new(); // place all the machines in the graph - while let Some(_machine) = machines.pop() { + while let Some(machine) = machines.pop() { if graph.nb_children(nodes_to_populate_now[populate_idx as usize]) == max_children_per_parent { - nodes_to_populate_now = core::mem::take(&mut nodes_to_populate_later); + nodes_to_populate_now = mem::take(&mut nodes_to_populate_later); populate_idx = 0; // should be useless } let new_child = graph.add_child( nodes_to_populate_now[populate_idx as usize], - MultiMachineNode::new(), + MultiMachineNode::new(machine), ); nodes_to_populate_later.push(new_child); @@ -65,7 +94,7 @@ impl MultiMachineTree { fn add_child(&mut self, parent: NodeIndex, child: MultiMachineNode) -> NodeIndex { let child_idx = self.graph.add_node(child); - self.graph.add_edge(child_idx, parent, ()); + self.graph.add_edge(child_idx, parent, MultiMachineEdge); child_idx } @@ -74,4 +103,30 @@ impl MultiMachineTree { .neighbors_directed(node, Direction::Incoming) .count() as u64 } + + fn get_parent(&self, node: NodeIndex) -> Option { + self.graph + .neighbors_directed(node, Direction::Outgoing) + .next() + } + + #[must_use] + pub fn get_config(&self, default_port: u16) -> Vec { + let mut node_configs: Vec = Vec::new(); + for node_idx in self.graph.node_indices() { + let node = &self.graph[node_idx]; + + let parent = self + .get_parent(node_idx) + .map(|parent_idx| self.graph[parent_idx].addr.clone()); + + node_configs.push(MultiMachineNodeConfig { + addr: node.addr.clone(), + parent, + port: default_port, + }); + } + + node_configs + } } diff --git a/utils/multi_machine_generator/src/main.rs b/utils/multi_machine_generator/src/main.rs index dbbe3fe988..ccb560f033 100644 --- a/utils/multi_machine_generator/src/main.rs +++ b/utils/multi_machine_generator/src/main.rs @@ -6,39 +6,49 @@ //! //! We suppose everyone is on the same network and the machines have the fuzzer ready to run on each machine. -use std::{fs, net::SocketAddr, str::FromStr}; +use std::{fs, fs::File, io, io::BufRead, path::PathBuf}; +use clap::Parser; use petgraph::dot::Dot; use crate::graph::MultiMachineTree; pub mod graph; +#[derive(Parser)] +struct Opt { + #[arg(short, long)] + machines_file: PathBuf, + #[arg(long)] + dot_output: Option, + #[arg(short, long)] + json_output: Option, + #[arg(short, long, default_value_t = 50000)] + default_port: u16, + // #[arg(short, long)] + // cmd_file: PathBuf, +} + fn main() { - let machines = [ - SocketAddr::from_str("0.0.0.1:50000").unwrap(), - SocketAddr::from_str("0.0.0.2:50000").unwrap(), - SocketAddr::from_str("0.0.0.3:50000").unwrap(), - SocketAddr::from_str("0.0.0.4:50000").unwrap(), - SocketAddr::from_str("0.0.0.5:50000").unwrap(), - SocketAddr::from_str("0.0.0.6:50000").unwrap(), - SocketAddr::from_str("0.0.0.7:50000").unwrap(), - SocketAddr::from_str("0.0.0.8:50000").unwrap(), - SocketAddr::from_str("0.0.0.9:50000").unwrap(), - SocketAddr::from_str("0.0.0.10:50000").unwrap(), - SocketAddr::from_str("0.0.0.11:50000").unwrap(), - SocketAddr::from_str("0.0.0.12:50000").unwrap(), - SocketAddr::from_str("0.0.0.13:50000").unwrap(), - SocketAddr::from_str("0.0.0.14:50000").unwrap(), - SocketAddr::from_str("0.0.0.15:50000").unwrap(), - SocketAddr::from_str("0.0.0.16:50000").unwrap(), - SocketAddr::from_str("0.0.0.17:50000").unwrap(), - SocketAddr::from_str("0.0.0.18:50000").unwrap(), - ]; + let opt = Opt::parse(); + + let machine_file = File::open(opt.machines_file.as_path()).unwrap(); + let machines: Vec = io::BufReader::new(machine_file) + .lines() + .map(|m| m.unwrap()) + .collect(); let multi_machine_graph = MultiMachineTree::generate(&machines, 3); - let dot = Dot::new(&multi_machine_graph.graph); + // final graph + if let Some(dot_path) = opt.dot_output { + let dot = Dot::new(&multi_machine_graph.graph); + fs::write(dot_path, format!("{dot}")).unwrap(); + } - fs::write("multi_machine.dot", format!("{dot:?}")).unwrap(); + if let Some(json_path) = opt.json_output { + let cfg = multi_machine_graph.get_config(opt.default_port); + let cfg_json = serde_json::to_string_pretty(&cfg).unwrap(); + fs::write(json_path, cfg_json).unwrap(); + } }