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

Introspection #58

Merged
merged 24 commits into from
May 7, 2021
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
12b9584
Rework to put `ClientPerfStats` in `State` and pass that along. Still…
ctfhacker Apr 7, 2021
c017d72
Add perf_stats feature to libafl/Cargo.toml
ctfhacker Apr 7, 2021
23061ef
Update feedbacks to have with_perf
ctfhacker Apr 12, 2021
9469776
Merge branch 'real_time_benchmarks' of github.com:AFLplusplus/LibAFL …
ctfhacker Apr 12, 2021
542738c
Merge branch 'dev' into real_time_benchmarks
ctfhacker Apr 18, 2021
fedb5f8
Remove unneeeded print statement
ctfhacker Apr 18, 2021
7423cef
cargo fmt all the things
ctfhacker Apr 18, 2021
4ad9c10
use local llvmint vs cpu specific asm for reading cycle counter
ctfhacker Apr 19, 2021
b9a0c7c
Remove debug testing code
ctfhacker Apr 19, 2021
2a96fe3
Stats timeout to 3 seconds
ctfhacker Apr 19, 2021
55703cb
Inline smallish functions for ClientPerfStats
ctfhacker Apr 19, 2021
042bfce
Remove .libs/llvmint and have the correct conditional compilation of …
ctfhacker Apr 19, 2021
2b6b369
pub(crate) the NUM_FEEDBACK and NUM_STAGES consts
ctfhacker Apr 19, 2021
8219da3
Merge branch 'dev' into real_time_benchmarks
domenukk Apr 26, 2021
33df973
perf_stats->instrospection; merged dev; moved back to x86 stable
domenukk May 1, 2021
b9e75c0
Tcp Broker to Broker Communication (#66)
domenukk May 1, 2021
3fb4626
merged dev
domenukk May 1, 2021
0ac407a
adapted to new feedback interface;;
domenukk May 6, 2021
6cc1e96
clippy fixes
domenukk May 6, 2021
1fa893e
fallback to systemtime on non-x86
domenukk May 6, 2021
5d1eb27
make clippy more strict
domenukk May 7, 2021
f56f340
small fixes
andreafioraldi May 7, 2021
1e61748
bump 0.2.1
andreafioraldi May 7, 2021
92116b9
readme
andreafioraldi May 7, 2021
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
3 changes: 2 additions & 1 deletion fuzzers/libfuzzer_libpng/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ which = { version = "4.0.2" }
num_cpus = "1.0"

[dependencies]
libafl = { path = "../../libafl/" }
libafl = { path = "../../libafl/", features = ["default", "perf_stats"] }
# libafl = { path = "../../libafl/", features = ["default"] }
libafl_targets = { path = "../../libafl_targets/", features = ["pcguard_hitcounts", "libfuzzer"] }
# TODO Include it only when building cc
libafl_cc = { path = "../../libafl_cc/" }
Expand Down
52 changes: 52 additions & 0 deletions fuzzers/libfuzzer_libpng/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
PWD=`pwd`

all:
# Build the libpng libfuzzer library
cargo build --release

# Build the libpng harness
$(PWD)/target/release/cxx \
$(PWD)/harness.cc \
$(PWD)/libpng-1.6.37/.libs/libpng16.a \
-I$(PWD)/libpng-1.6.37/ \
-o fuzzer \
-lm -lz

run: all
./fuzzer &
./fuzzer >/dev/null 2>/dev/null &

test: all
timeout 60s ./fuzzer &
timeout 59s taskset 0x00000001 ./fuzzer >/dev/null 2>/dev/null &
timeout 59s taskset 0x00000002 ./fuzzer >/dev/null 2>/dev/null &
timeout 59s taskset 0x00000004 ./fuzzer >/dev/null 2>/dev/null &
timeout 59s taskset 0x00000008 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x00000010 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x00000020 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x00000040 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x00000080 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x00000100 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x00000200 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x00000400 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x00000800 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x00001000 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x00002000 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x00004000 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x00008000 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x00010000 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x00020000 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x00040000 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x00080000 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x00100000 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x00200000 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x00400000 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x00800000 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x01000000 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x02000000 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x04000000 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x08000000 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x10000000 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x20000000 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x40000000 ./fuzzer >/dev/null 2>/dev/null &
# timeout 59s taskset 0x80000000 ./fuzzer >/dev/null 2>/dev/null &
5 changes: 4 additions & 1 deletion fuzzers/libfuzzer_libpng/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
StdRand::with_seed(current_nanos()),
// Corpus that will be evolved, we keep it in memory for performance
InMemoryCorpus::new(),

// Feedbacks to rate the interestingness of an input
tuple_list!(
MaxMapFeedback::new_with_observer_track(&edges_observer, true, false),
Expand All @@ -84,11 +85,13 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
// Corpus in which we store solutions (crashes in this example),
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(objective_dir).unwrap(),
// Feedbacks to recognize an input as solution

// Objectives to recognize an input as solution
tuple_list!(CrashFeedback::new(), TimeoutFeedback::new()),
)
});


println!("We're a client, let's fuzz :)");

// Create a PNG dictionary if not existing
Expand Down
2 changes: 1 addition & 1 deletion libafl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ anymapdbg = ["serde_json"] # uses serde_json to Debug the anymap trait. Disable
derive = ["libafl_derive"] # provide derive(SerdeAny) macro.
llmp_small_maps = [] # reduces initial map size for llmp
llmp_debug = [] # Enables debug output for LLMP
perf_stats = [] # Include performance statistics of the fuzzing pipeline

[[example]]
name = "llmp_test"
Expand All @@ -56,7 +57,6 @@ libafl_derive = { version = "*", optional = true, path = "../libafl_derive" }
serde_json = { version = "1.0", optional = true, default-features = false, features = ["alloc"] } # an easy way to debug print SerdeAnyMap
#TODO: for llmp brotli = { version = "3.3.0", default-features = false } # brotli compression
num_enum = "0.5.1"

backtrace = "0.3" # for llmp_debug

[target.'cfg(unix)'.dependencies]
Expand Down
15 changes: 15 additions & 0 deletions libafl/src/cpu.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//! Architecture agnostic processor features

extern {
#[link_name = "llvm.readcyclecounter"]
pub fn readcyclecounter() -> u64;
}

/// Read time counter using [`llvmint::readcyclecounter`]
///
/// This function is a wrapper around [`llvmint`] to make it easier to test various
/// implementations of reading a cycle counter. In this way, an experiment only has to
/// change this implementation rather than every instead of [`cpu::read_time_counter`]
pub fn read_time_counter() -> u64 {
unsafe { readcyclecounter() }
}
32 changes: 30 additions & 2 deletions libafl/src/events/llmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ where
let client = stats.client_stats_mut_for(sender_id);
client.update_corpus_size(*corpus_size as u64);
client.update_executions(*executions as u64, *time);
stats.display(event.name().to_string() + " #" + &sender_id.to_string());
// stats.display(event.name().to_string() + " #" + &sender_id.to_string());
Copy link
Member

@andreafioraldi andreafioraldi May 20, 2021

Choose a reason for hiding this comment

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

@domenukk porcodio, now we have to release again because this line was commented

Ok(BrokerEventResult::Forward)
}
Event::UpdateStats {
Expand All @@ -250,7 +250,35 @@ where
// TODO: The stats buffer should be added on client add.
let client = stats.client_stats_mut_for(sender_id);
client.update_executions(*executions as u64, *time);
stats.display(event.name().to_string() + " #" + &sender_id.to_string());
if sender_id == 1 {
Copy link
Member

Choose a reason for hiding this comment

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

Why this?

Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't be needed, I agree

stats.display(event.name().to_string() + " #" + &sender_id.to_string());
}
Ok(BrokerEventResult::Handled)
}
#[cfg(feature = "perf_stats")]
Event::UpdatePerfStats {
time,
executions,
perf_stats,
phantom: _,
} => {
// TODO: The stats buffer should be added on client add.

// Get the client for the sender ID
let client = stats.client_stats_mut_for(sender_id);

// Update the normal stats for this client
client.update_executions(*executions as u64, *time);

// Update the performance stats for this client
client.update_perf_stats(*perf_stats);

// Display the stats via `.display` only on core #1
if sender_id == 1 {
stats.display(event.name().to_string() + " #" + &sender_id.to_string());
}

// Correctly handled the event
Ok(BrokerEventResult::Handled)
}
Event::Objective { objective_size } => {
Expand Down
24 changes: 24 additions & 0 deletions libafl/src/events/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ use crate::{
Error,
};

#[cfg(feature = "perf_stats")]
use crate::stats::ClientPerfStats;

/// The log event severity
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
pub enum LogSeverity {
Expand Down Expand Up @@ -97,6 +100,20 @@ where
executions: usize,
phantom: PhantomData<I>,
},
/// New stats with performance stats.
#[cfg(feature = "perf_stats")]
UpdatePerfStats {
/// The time of generation of the event
time: Duration,

/// The executions of this client
executions: usize,

/// Current performance statistics
perf_stats: ClientPerfStats,

phantom: PhantomData<I>,
},
/// A new objective was found
Objective {
/// Objective corpus size
Expand Down Expand Up @@ -136,6 +153,13 @@ where
executions: _,
phantom: _,
} => "Stats",
#[cfg(feature = "perf_stats")]
Event::UpdatePerfStats {
time: _,
executions: _,
perf_stats: _,
phantom: _,
} => "PerfStats",
Event::Objective { objective_size: _ } => "Objective",
Event::Log {
severity_level: _,
Expand Down
13 changes: 13 additions & 0 deletions libafl/src/events/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,19 @@ where
stats.display(event.name().to_string());
Ok(BrokerEventResult::Handled)
}
#[cfg(feature = "perf_stats")]
Event::UpdatePerfStats {
time,
executions,
perf_stats,
phantom: _,
} => {
// TODO: The stats buffer should be added on client add.
stats.client_stats_mut()[0].update_executions(*executions as u64, *time);
stats.client_stats_mut()[0].update_perf_stats(*perf_stats);
stats.display(event.name().to_string());
Ok(BrokerEventResult::Handled)
}
Event::Objective { objective_size } => {
stats.client_stats_mut()[0].update_objective_size(*objective_size as u64);
stats.display(event.name().to_string());
Expand Down
55 changes: 55 additions & 0 deletions libafl/src/feedbacks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ use crate::{
corpus::Testcase,
executors::ExitKind,
inputs::Input,
mark_feedback_time,
observers::{ObserversTuple, TimeObserver},
start_timer,
state::HasClientPerfStats,
stats::{PerfFeature, NUM_FEEDBACKS},
Error,
};

Expand Down Expand Up @@ -57,6 +61,20 @@ where
exit_kind: ExitKind,
) -> Result<u32, Error>;

/// Get the total interestingness value from all feedbacks with performance
/// statistics included
#[cfg(feature = "perf_stats")]
fn is_interesting_all_with_perf<OT: ObserversTuple>(
&mut self,
input: &I,
observers: &OT,
exit_kind: ExitKind,
feedback_stats: &mut [u64; NUM_FEEDBACKS],
feedback_index: usize,
) -> Result<u32, Error> {
return Ok(0);
}

/// Write metadata for this testcase
fn append_metadata_all(&mut self, testcase: &mut Testcase<I>) -> Result<(), Error>;

Expand Down Expand Up @@ -105,6 +123,43 @@ where
+ self.1.is_interesting_all(input, observers, exit_kind)?)
}

#[cfg(feature = "perf_stats")]
fn is_interesting_all_with_perf<OT: ObserversTuple>(
&mut self,
input: &I,
observers: &OT,
exit_kind: ExitKind,
feedback_stats: &mut [u64; NUM_FEEDBACKS],
feedback_index: usize,
) -> Result<u32, Error> {
let mut res = 0;

// Start a timer for this feedback
let start_time = crate::cpu::read_time_counter();

// Execute this feedback
res += self.0.is_interesting(input, observers, exit_kind.clone())?;

// Get the elapsed time for checking this feedback
let elapsed = crate::cpu::read_time_counter() - start_time;

// Add this stat to the feedback metrics
feedback_stats[feedback_index] = elapsed;

// Increment the index
let next_index = feedback_index + 1;

// Continue executing the chain
Ok(res
+ self.1.is_interesting_all_with_perf(
input,
observers,
exit_kind,
feedback_stats,
next_index,
)?)
}

fn append_metadata_all(&mut self, testcase: &mut Testcase<I>) -> Result<(), Error> {
self.0.append_metadata(testcase)?;
self.1.append_metadata_all(testcase)
Expand Down
Loading