Fixed Forkserver shmem input length, made it configurable (#1342)

* Fixed Forkserver shmem input length, made it configurable

* fix redqueen clippy

* Clippy

* Clippy

* WHY ARE THERE TWO TIMES THE SAME FN

* More clippy
This commit is contained in:
Dominik Maier 2023-07-04 14:57:09 +01:00 committed by GitHub
parent 829b5049e6
commit e5b3e5a677
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 64 additions and 47 deletions

View File

@ -1,7 +1,7 @@
# Variables # Variables
[env] [env]
FUZZER_NAME='fuzzer_libpng_launcher' FUZZER_NAME='fuzzer_libpng_launcher'
CARGO_TARGET_DIR = { value = "${PROJECT_DIR}/target", condition = { env_not_set = ["CARGO_TARGET_DIR"] } } CARGO_TARGET_DIR = { value = "${PROJECT_DIR}/target/x86_64-unknown-linux-gnu", condition = { env_not_set = ["CARGO_TARGET_DIR"] } }
LIBAFL_CC = '${CARGO_TARGET_DIR}/release/libafl_cc' LIBAFL_CC = '${CARGO_TARGET_DIR}/release/libafl_cc'
LIBAFL_CXX = '${CARGO_TARGET_DIR}/release/libafl_cxx' LIBAFL_CXX = '${CARGO_TARGET_DIR}/release/libafl_cxx'
LIBAFL_LIBTOOL = '${CARGO_TARGET_DIR}/release/libafl_libtool' LIBAFL_LIBTOOL = '${CARGO_TARGET_DIR}/release/libafl_libtool'
@ -35,8 +35,9 @@ mac_alias = "cxx_unix"
windows_alias = "unsupported" windows_alias = "unsupported"
[tasks.cxx_unix] [tasks.cxx_unix]
command = "cargo" script="RUSTFLAGS=-Zsanitizer=address cargo +nightly build -Zbuild-std --target x86_64-unknown-linux-gnu --release"
args = ["build" , "--release"] #command = "cargo"
#args = ["build" , "--release"]
[tasks.cc] [tasks.cc]
linux_alias = "cc_unix" linux_alias = "cc_unix"
@ -44,8 +45,9 @@ mac_alias = "cc_unix"
windows_alias = "unsupported" windows_alias = "unsupported"
[tasks.cc_unix] [tasks.cc_unix]
command = "cargo" script="RUSTFLAGS=-Zsanitizer=address cargo +nightly build -Zbuild-std --target x86_64-unknown-linux-gnu --release"
args = ["build" , "--release"] #command = "cargo"
#args = ["build" , "--release"]
# Library # Library
[tasks.lib] [tasks.lib]
@ -55,7 +57,7 @@ windows_alias = "unsupported"
[tasks.lib_unix] [tasks.lib_unix]
script_runner="@shell" script_runner="@shell"
script=''' cript='''
cd libpng-1.6.37 && ./configure --enable-shared=no --with-pic=yes --enable-hardware-optimizations=yes cd libpng-1.6.37 && ./configure --enable-shared=no --with-pic=yes --enable-hardware-optimizations=yes
cd "${PROJECT_DIR}" cd "${PROJECT_DIR}"
make -C libpng-1.6.37 CC="${CARGO_TARGET_DIR}/release/libafl_cc" CXX="${CARGO_TARGET_DIR}/release/libafl_cxx" LIBTOOL=${CARGO_TARGET_DIR}/release/libafl_libtool make -C libpng-1.6.37 CC="${CARGO_TARGET_DIR}/release/libafl_cc" CXX="${CARGO_TARGET_DIR}/release/libafl_cxx" LIBTOOL=${CARGO_TARGET_DIR}/release/libafl_libtool
@ -71,7 +73,7 @@ windows_alias = "unsupported"
[tasks.fuzzer_unix] [tasks.fuzzer_unix]
command = "${CARGO_TARGET_DIR}/release/libafl_cxx" command = "${CARGO_TARGET_DIR}/release/libafl_cxx"
args = ["${PROJECT_DIR}/harness.cc", "${PROJECT_DIR}/libpng-1.6.37/.libs/libpng16.a", "-I", "${PROJECT_DIR}/libpng-1.6.37/", "-o", "${FUZZER_NAME}", "-lm", "-lz"] args = ["${PROJECT_DIR}/harness.cc", "${PROJECT_DIR}/libpng-1.6.37/.libs/libpng16.a", "-I", "${PROJECT_DIR}/libpng-1.6.37/", "-o", "${FUZZER_NAME}", "-lm", "-lz", "-fsanitize=address"]
dependencies = [ "lib", "cxx", "cc" ] dependencies = [ "lib", "cxx", "cc" ]
# Run the fuzzer # Run the fuzzer

View File

@ -2,9 +2,9 @@
//! The example harness is built for libpng. //! The example harness is built for libpng.
//! In this example, you will see the use of the `launcher` feature. //! In this example, you will see the use of the `launcher` feature.
//! The `launcher` will spawn new processes for each cpu core. //! The `launcher` will spawn new processes for each cpu core.
use mimalloc::MiMalloc; //use mimalloc::MiMalloc;
#[global_allocator] //#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc; //static GLOBAL: MiMalloc = MiMalloc;
use core::time::Duration; use core::time::Duration;
use std::{env, net::SocketAddr, path::PathBuf}; use std::{env, net::SocketAddr, path::PathBuf};
@ -197,7 +197,15 @@ pub fn libafl_main() {
let mut harness = |input: &BytesInput| { let mut harness = |input: &BytesInput| {
let target = input.target_bytes(); let target = input.target_bytes();
let buf = target.as_slice(); let buf = target.as_slice();
// Artificial timeout to check timeout
libfuzzer_test_one_input(buf); libfuzzer_test_one_input(buf);
// We're timeouting
if buf.len() == 42 {
println!("TIMEOUT :)");
std::thread::sleep(Duration::from_millis(1_000_000));
}
ExitKind::Ok ExitKind::Ok
}; };

View File

@ -1443,7 +1443,7 @@ impl<T: ShMem> std::io::Seek for ShMemCursor<T> {
std::io::SeekFrom::End(offset) => { std::io::SeekFrom::End(offset) => {
let map_len = self.inner.as_slice().len(); let map_len = self.inner.as_slice().len();
i64::try_from(map_len).unwrap(); i64::try_from(map_len).unwrap();
let signed_pos = map_len as i64; let signed_pos = i64::try_from(map_len).unwrap();
let effective = signed_pos.checked_add(offset).unwrap(); let effective = signed_pos.checked_add(offset).unwrap();
assert!(effective >= 0); assert!(effective >= 0);
effective.try_into().unwrap() effective.try_into().unwrap()
@ -1451,7 +1451,7 @@ impl<T: ShMem> std::io::Seek for ShMemCursor<T> {
std::io::SeekFrom::Current(offset) => { std::io::SeekFrom::Current(offset) => {
let current_pos = self.pos; let current_pos = self.pos;
i64::try_from(current_pos).unwrap(); i64::try_from(current_pos).unwrap();
let signed_pos = current_pos as i64; let signed_pos = i64::try_from(current_pos).unwrap();
let effective = signed_pos.checked_add(offset).unwrap(); let effective = signed_pos.checked_add(offset).unwrap();
assert!(effective >= 0); assert!(effective >= 0);
effective.try_into().unwrap() effective.try_into().unwrap()

View File

@ -154,7 +154,7 @@ where
let shmem_content = self.content_mut(); let shmem_content = self.content_mut();
unsafe { unsafe {
ptr::copy_nonoverlapping( ptr::copy_nonoverlapping(
filename_buf.as_ptr() as *const u8, filename_buf.as_ptr(),
shmem_content.buf.as_mut_ptr(), shmem_content.buf.as_mut_ptr(),
len, len,
); );
@ -166,11 +166,7 @@ where
let len = serialized.len(); let len = serialized.len();
let shmem_content = self.content_mut(); let shmem_content = self.content_mut();
unsafe { unsafe {
ptr::copy_nonoverlapping( ptr::copy_nonoverlapping(serialized.as_ptr(), shmem_content.buf.as_mut_ptr(), len);
serialized.as_ptr() as *const u8,
shmem_content.buf.as_mut_ptr(),
len,
);
} }
shmem_content.buf_len = len; shmem_content.buf_len = len;
shmem_content.is_disk = false; shmem_content.is_disk = false;

View File

@ -499,7 +499,6 @@ where
Ok(cur) Ok(cur)
} else { } else {
if cur.as_millis() % 1000 == 0 {}
Ok(last_report_time) Ok(last_report_time)
} }
} }

View File

@ -65,7 +65,7 @@ const fn fs_opt_get_mapsize(x: i32) -> i32 {
/// The length of header bytes which tells shmem size /// The length of header bytes which tells shmem size
const SHMEM_FUZZ_HDR_SIZE: usize = 4; const SHMEM_FUZZ_HDR_SIZE: usize = 4;
const MAX_FILE: usize = 1024 * 1024; const MAX_INPUT_SIZE_DEFAULT: usize = 1024 * 1024;
/// Configure the target, `limit`, `setsid`, `pipe_stdin`, the code was borrowed from the [`Angora`](https://github.com/AngoraFuzzer/Angora) fuzzer /// Configure the target, `limit`, `setsid`, `pipe_stdin`, the code was borrowed from the [`Angora`](https://github.com/AngoraFuzzer/Angora) fuzzer
pub trait ConfigTarget { pub trait ConfigTarget {
@ -436,14 +436,20 @@ where
let last_run_timed_out = self.executor.forkserver().last_run_timed_out(); let last_run_timed_out = self.executor.forkserver().last_run_timed_out();
if self.executor.uses_shmem_testcase() { if self.executor.uses_shmem_testcase() {
let shmem = unsafe { self.executor.shmem_mut().as_mut().unwrap_unchecked() }; let map = unsafe { self.executor.shmem_mut().as_mut().unwrap_unchecked() };
let target_bytes = input.target_bytes(); let target_bytes = input.target_bytes();
let size = target_bytes.as_slice().len(); let mut size = target_bytes.as_slice().len();
let max_size = map.len() - SHMEM_FUZZ_HDR_SIZE;
if size > max_size {
// Truncate like AFL++ does
size = max_size;
}
let size_in_bytes = size.to_ne_bytes(); let size_in_bytes = size.to_ne_bytes();
// The first four bytes tells the size of the shmem. // The first four bytes tells the size of the shmem.
shmem.as_mut_slice()[..4].copy_from_slice(&size_in_bytes[..4]); map.as_mut_slice()[..SHMEM_FUZZ_HDR_SIZE]
shmem.as_mut_slice()[SHMEM_FUZZ_HDR_SIZE..(SHMEM_FUZZ_HDR_SIZE + size)] .copy_from_slice(&size_in_bytes[..SHMEM_FUZZ_HDR_SIZE]);
.copy_from_slice(target_bytes.as_slice()); map.as_mut_slice()[SHMEM_FUZZ_HDR_SIZE..(SHMEM_FUZZ_HDR_SIZE + size)]
.copy_from_slice(&target_bytes.as_slice()[..size]);
} else { } else {
self.executor self.executor
.input_file_mut() .input_file_mut()
@ -610,6 +616,7 @@ pub struct ForkserverExecutorBuilder<'a, SP> {
autotokens: Option<&'a mut Tokens>, autotokens: Option<&'a mut Tokens>,
input_filename: Option<OsString>, input_filename: Option<OsString>,
shmem_provider: Option<&'a mut SP>, shmem_provider: Option<&'a mut SP>,
max_input_size: usize,
map_size: Option<usize>, map_size: Option<usize>,
real_map_size: i32, real_map_size: i32,
} }
@ -716,10 +723,10 @@ impl<'a, SP> ForkserverExecutorBuilder<'a, SP> {
None => None, None => None,
Some(provider) => { Some(provider) => {
// setup shared memory // setup shared memory
let mut shmem = provider.new_shmem(MAX_FILE + SHMEM_FUZZ_HDR_SIZE)?; let mut shmem = provider.new_shmem(self.max_input_size + SHMEM_FUZZ_HDR_SIZE)?;
shmem.write_to_env("__AFL_SHM_FUZZ_ID")?; shmem.write_to_env("__AFL_SHM_FUZZ_ID")?;
let size_in_bytes = (MAX_FILE + SHMEM_FUZZ_HDR_SIZE).to_ne_bytes(); let size_in_bytes = (self.max_input_size + SHMEM_FUZZ_HDR_SIZE).to_ne_bytes();
shmem.as_mut_slice()[..4].clone_from_slice(&size_in_bytes[..4]); shmem.as_mut_slice()[..4].clone_from_slice(&size_in_bytes[..4]);
Some(shmem) Some(shmem)
} }
@ -1035,6 +1042,7 @@ impl<'a> ForkserverExecutorBuilder<'a, UnixShMemProvider> {
shmem_provider: None, shmem_provider: None,
map_size: None, map_size: None,
real_map_size: 0, real_map_size: 0,
max_input_size: MAX_INPUT_SIZE_DEFAULT,
} }
} }
@ -1057,6 +1065,7 @@ impl<'a> ForkserverExecutorBuilder<'a, UnixShMemProvider> {
shmem_provider: Some(shmem_provider), shmem_provider: Some(shmem_provider),
map_size: self.map_size, map_size: self.map_size,
real_map_size: self.real_map_size, real_map_size: self.real_map_size,
max_input_size: MAX_INPUT_SIZE_DEFAULT,
} }
} }
} }
@ -1091,16 +1100,17 @@ where
let map = unsafe { self.map.as_mut().unwrap_unchecked() }; let map = unsafe { self.map.as_mut().unwrap_unchecked() };
let target_bytes = input.target_bytes(); let target_bytes = input.target_bytes();
let mut size = target_bytes.as_slice().len(); let mut size = target_bytes.as_slice().len();
if size > MAX_FILE { let max_size = map.len() - SHMEM_FUZZ_HDR_SIZE;
if size > max_size {
// Truncate like AFL++ does // Truncate like AFL++ does
size = MAX_FILE; size = max_size;
} }
let size_in_bytes = size.to_ne_bytes(); let size_in_bytes = size.to_ne_bytes();
// The first four bytes tells the size of the shmem. // The first four bytes tells the size of the shmem.
map.as_mut_slice()[..SHMEM_FUZZ_HDR_SIZE] map.as_mut_slice()[..SHMEM_FUZZ_HDR_SIZE]
.copy_from_slice(&size_in_bytes[..SHMEM_FUZZ_HDR_SIZE]); .copy_from_slice(&size_in_bytes[..SHMEM_FUZZ_HDR_SIZE]);
map.as_mut_slice()[SHMEM_FUZZ_HDR_SIZE..(SHMEM_FUZZ_HDR_SIZE + size)] map.as_mut_slice()[SHMEM_FUZZ_HDR_SIZE..(SHMEM_FUZZ_HDR_SIZE + size)]
.copy_from_slice(target_bytes.as_slice()); .copy_from_slice(&target_bytes.as_slice()[..size]);
} else { } else {
self.input_file.write_buf(input.target_bytes().as_slice())?; self.input_file.write_buf(input.target_bytes().as_slice())?;
} }

View File

@ -1243,6 +1243,7 @@ fn locate_diffs(this: &[u8], other: &[u8]) -> (i64, i64) {
let mut first_diff: i64 = -1; let mut first_diff: i64 = -1;
let mut last_diff: i64 = -1; let mut last_diff: i64 = -1;
for (i, (this_el, other_el)) in this.iter().zip(other.iter()).enumerate() { for (i, (this_el, other_el)) in this.iter().zip(other.iter()).enumerate() {
#[allow(clippy::cast_possible_wrap)]
if this_el != other_el { if this_el != other_el {
if first_diff < 0 { if first_diff < 0 {
first_diff = i as i64; first_diff = i as i64;

View File

@ -693,7 +693,7 @@ impl AFLppRedQueen {
)), )),
0xffff, 0xffff,
), ),
4 | 5 | 6 | 7 => ( 4..=7 => (
u64::from(u32::from_be_bytes( u64::from(u32::from_be_bytes(
buf[buf_idx..buf_idx + 4].try_into().unwrap(), buf[buf_idx..buf_idx + 4].try_into().unwrap(),
)), )),
@ -852,7 +852,7 @@ impl AFLppRedQueen {
} }
} }
} }
4 | 5 | 6 | 7 => { 4..=7 => {
if its_len >= 4 { if its_len >= 4 {
let buf_32 = u32::from_be_bytes(buf[buf_idx..buf_idx + 4].try_into().unwrap()); let buf_32 = u32::from_be_bytes(buf[buf_idx..buf_idx + 4].try_into().unwrap());
let another_buf_32 = let another_buf_32 =
@ -1448,7 +1448,7 @@ where
if !cmp_found { if !cmp_found {
if orig_v0 == new_v0 if orig_v0 == new_v0
&& check_if_text(&orig_v0.to_ne_bytes().to_vec(), hshape).size() && check_if_text(orig_v0.to_ne_bytes().as_ref(), hshape).size()
== hshape == hshape
{ {
let v = orig_v0.to_ne_bytes().to_vec(); let v = orig_v0.to_ne_bytes().to_vec();
@ -1456,7 +1456,7 @@ where
} }
if orig_v1 == new_v1 if orig_v1 == new_v1
&& check_if_text(&orig_v1.to_ne_bytes().to_vec(), hshape).size() && check_if_text(orig_v1.to_ne_bytes().as_ref(), hshape).size()
== hshape == hshape
{ {
let v = orig_v1.to_ne_bytes().to_vec(); let v = orig_v1.to_ne_bytes().to_vec();
@ -1541,7 +1541,7 @@ where
if !cmp_found { if !cmp_found {
if orig_v0 == new_v0 if orig_v0 == new_v0
&& check_if_text(&orig_v0.to_ne_bytes().to_vec(), hshape).size() && check_if_text(orig_v0.to_ne_bytes().as_ref(), hshape).size()
== hshape == hshape
{ {
let v = orig_v0.to_ne_bytes().to_vec(); let v = orig_v0.to_ne_bytes().to_vec();
@ -1549,7 +1549,7 @@ where
} }
if orig_v1 == new_v1 if orig_v1 == new_v1
&& check_if_text(&orig_v1.to_ne_bytes().to_vec(), hshape).size() && check_if_text(orig_v1.to_ne_bytes().as_ref(), hshape).size()
== hshape == hshape
{ {
let v = orig_v1.to_ne_bytes().to_vec(); let v = orig_v1.to_ne_bytes().to_vec();

View File

@ -353,7 +353,7 @@ where
let cnt = self.usable_count(); let cnt = self.usable_count();
let map = self.as_slice(); let map = self.as_slice();
let mut res = 0; let mut res = 0;
for x in map[0..cnt].iter() { for x in &map[0..cnt] {
if *x != initial { if *x != initial {
res += 1; res += 1;
} }
@ -386,7 +386,7 @@ where
let initial = self.initial(); let initial = self.initial();
let cnt = self.usable_count(); let cnt = self.usable_count();
let map = self.as_mut_slice(); let map = self.as_mut_slice();
for x in map[0..cnt].iter_mut() { for x in &mut map[0..cnt] {
*x = initial; *x = initial;
} }
Ok(()) Ok(())
@ -815,7 +815,7 @@ where
let cnt = self.usable_count(); let cnt = self.usable_count();
let map = self.as_slice(); let map = self.as_slice();
let mut res = 0; let mut res = 0;
for x in map[0..cnt].iter() { for x in &map[0..cnt] {
if *x != initial { if *x != initial {
res += 1; res += 1;
} }
@ -838,7 +838,7 @@ where
let initial = self.initial(); let initial = self.initial();
let cnt = self.usable_count(); let cnt = self.usable_count();
let map = self.as_mut_slice(); let map = self.as_mut_slice();
for x in map[0..cnt].iter_mut() { for x in &mut map[0..cnt] {
*x = initial; *x = initial;
} }
Ok(()) Ok(())
@ -1091,7 +1091,7 @@ where
let cnt = self.usable_count(); let cnt = self.usable_count();
let map = self.as_slice(); let map = self.as_slice();
let mut res = 0; let mut res = 0;
for x in map[0..cnt].iter() { for x in &map[0..cnt] {
if *x != initial { if *x != initial {
res += 1; res += 1;
} }
@ -1109,7 +1109,7 @@ where
let initial = self.initial(); let initial = self.initial();
let cnt = self.usable_count(); let cnt = self.usable_count();
let map = self.as_mut_slice(); let map = self.as_mut_slice();
for x in map[0..cnt].iter_mut() { for x in &mut map[0..cnt] {
*x = initial; *x = initial;
} }
Ok(()) Ok(())
@ -2082,7 +2082,7 @@ where
let cnt = self.usable_count(); let cnt = self.usable_count();
let map = self.as_slice(); let map = self.as_slice();
let mut res = 0; let mut res = 0;
for x in map[0..cnt].iter() { for x in &map[0..cnt] {
if *x != initial { if *x != initial {
res += 1; res += 1;
} }
@ -2111,7 +2111,7 @@ where
let initial = self.initial(); let initial = self.initial();
let cnt = self.usable_count(); let cnt = self.usable_count();
let map = self.as_mut_slice(); let map = self.as_mut_slice();
for x in map[0..cnt].iter_mut() { for x in &mut map[0..cnt] {
*x = initial; *x = initial;
} }
Ok(()) Ok(())

View File

@ -244,7 +244,7 @@ pub fn get_asan_runtime_flags_with_log_path() -> String {
/// returns the recommended ASAN runtime flags to capture the backtrace correctly /// returns the recommended ASAN runtime flags to capture the backtrace correctly
#[must_use] #[must_use]
pub fn get_asan_runtime_flags() -> String { pub fn get_asan_runtime_flags() -> String {
let flags = vec![ let flags = [
"exitcode=0", "exitcode=0",
"abort_on_error=1", "abort_on_error=1",
"handle_abort=1", "handle_abort=1",

View File

@ -150,6 +150,7 @@ where
if !was_fuzzed { if !was_fuzzed {
let selection = Some(id); let selection = Some(id);
state.metadata_mut::<EcoMetadata>()?.state = EcoState::Exploration; state.metadata_mut::<EcoMetadata>()?.state = EcoState::Exploration;
#[allow(clippy::unnecessary_literal_unwrap)] // false positive
return Ok(selection.expect("Error in the algorithm, this cannot be None")); return Ok(selection.expect("Error in the algorithm, this cannot be None"));
} }
} }

View File

@ -124,7 +124,7 @@ where
let threshold = meta.total_probability * rand_prob; let threshold = meta.total_probability * rand_prob;
let mut k: f64 = 0.0; let mut k: f64 = 0.0;
let mut ret = *meta.map.keys().last().unwrap(); let mut ret = *meta.map.keys().last().unwrap();
for (idx, prob) in meta.map.iter() { for (idx, prob) in &meta.map {
k += prob; k += prob;
if k >= threshold { if k >= threshold {
ret = *idx; ret = *idx;

View File

@ -159,7 +159,7 @@ where
sum += weight; sum += weight;
} }
for (i, w) in weights.iter() { for (i, w) in &weights {
p_arr.insert(*i, w * (n as f64) / sum); p_arr.insert(*i, w * (n as f64) / sum);
} }