Multi machine follow-up (#2334)
* improved tree generator. possibility to dump state on exit. * warnings. * clippy * clippy * aaaaaa * aaaaaa * make nix mandatory for unix * stddddddd * stddddddd * stddddddd * aaa * clippy * doc * aaa * aaa * aaa * aaa * fix * aaaaaaaa * dump state * aaa * aaa * aaa * more minimal dump * aaa * aaa * aaa * simpler tc dump * pub * more pub * revert a bit * release by default * delete Makefile.toml * release * dump execs * merge * delete stuff * aa * ff * dig * FMT cargo stuf --------- Co-authored-by: Toka <tokazerkje@outlook.com>
This commit is contained in:
parent
1113879a34
commit
203d3d340a
@ -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)]
|
||||
|
@ -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 \
|
||||
|
@ -1,3 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
./ossfuzz --cores 4-7 --input ./corpus
|
||||
./ossfuzz --cores 0-1 --input ./corpus
|
||||
|
64
fuzzers/sqlite_centralized_multi_machine/Cargo.toml
Normal file
64
fuzzers/sqlite_centralized_multi_machine/Cargo.toml
Normal file
@ -0,0 +1,64 @@
|
||||
[package]
|
||||
name = "libfuzzer_libpng_launcher_centralized_multi_machine"
|
||||
version = "0.12.0"
|
||||
authors = [
|
||||
"Romain Malmain <romain.malmain@pm.me>",
|
||||
"Andrea Fioraldi <andreafioraldi@gmail.com>",
|
||||
"Dominik Maier <domenukk@gmail.com>",
|
||||
]
|
||||
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"]
|
@ -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"]
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)?;
|
||||
}
|
||||
}
|
||||
|
@ -82,8 +82,9 @@ pub use owned_map::*;
|
||||
/// # InMemoryCorpus::<BytesInput>::new(),
|
||||
/// # InMemoryCorpus::new(),
|
||||
/// # &mut feedback,
|
||||
/// # &mut ()
|
||||
/// # &mut (),
|
||||
/// # ).unwrap();
|
||||
///
|
||||
/// # feedback.init_state(&mut state).unwrap();
|
||||
///
|
||||
/// let scheduler = IndexesLenTimeMinimizerScheduler::new(&edges_observer, QueueScheduler::new());
|
||||
|
@ -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<T: 'static + CtrlHandler>(
|
||||
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()
|
||||
|
2
utils/multi_machine_generator/.gitignore
vendored
Normal file
2
utils/multi_machine_generator/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*.txt
|
||||
*.dot
|
@ -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"
|
||||
|
@ -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<String>,
|
||||
port: u16,
|
||||
}
|
||||
|
||||
/// The tree
|
||||
pub struct MultiMachineTree {
|
||||
pub graph: Graph<MultiMachineNode, ()>,
|
||||
pub graph: Graph<MultiMachineNode, MultiMachineEdge>,
|
||||
}
|
||||
|
||||
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::<MultiMachineNode, ()>::new();
|
||||
pub fn generate(machines: &[String], max_children_per_parent: u64) -> Self {
|
||||
let mut graph = Graph::<MultiMachineNode, MultiMachineEdge>::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<NodeIndex> = 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<NodeIndex> {
|
||||
self.graph
|
||||
.neighbors_directed(node, Direction::Outgoing)
|
||||
.next()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_config(&self, default_port: u16) -> Vec<MultiMachineNodeConfig> {
|
||||
let mut node_configs: Vec<MultiMachineNodeConfig> = 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
|
||||
}
|
||||
}
|
||||
|
@ -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<PathBuf>,
|
||||
#[arg(short, long)]
|
||||
json_output: Option<PathBuf>,
|
||||
#[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<String> = io::BufReader::new(machine_file)
|
||||
.lines()
|
||||
.map(|m| m.unwrap())
|
||||
.collect();
|
||||
|
||||
let multi_machine_graph = MultiMachineTree::generate(&machines, 3);
|
||||
|
||||
// final graph
|
||||
if let Some(dot_path) = opt.dot_output {
|
||||
let dot = Dot::new(&multi_machine_graph.graph);
|
||||
|
||||
fs::write("multi_machine.dot", format!("{dot:?}")).unwrap();
|
||||
fs::write(dot_path, 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();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user