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
[env]
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_CXX = '${CARGO_TARGET_DIR}/release/libafl_cxx'
LIBAFL_LIBTOOL = '${CARGO_TARGET_DIR}/release/libafl_libtool'
@ -35,8 +35,9 @@ mac_alias = "cxx_unix"
windows_alias = "unsupported"
[tasks.cxx_unix]
command = "cargo"
args = ["build" , "--release"]
script="RUSTFLAGS=-Zsanitizer=address cargo +nightly build -Zbuild-std --target x86_64-unknown-linux-gnu --release"
#command = "cargo"
#args = ["build" , "--release"]
[tasks.cc]
linux_alias = "cc_unix"
@ -44,8 +45,9 @@ mac_alias = "cc_unix"
windows_alias = "unsupported"
[tasks.cc_unix]
command = "cargo"
args = ["build" , "--release"]
script="RUSTFLAGS=-Zsanitizer=address cargo +nightly build -Zbuild-std --target x86_64-unknown-linux-gnu --release"
#command = "cargo"
#args = ["build" , "--release"]
# Library
[tasks.lib]
@ -55,7 +57,7 @@ windows_alias = "unsupported"
[tasks.lib_unix]
script_runner="@shell"
script='''
cript='''
cd libpng-1.6.37 && ./configure --enable-shared=no --with-pic=yes --enable-hardware-optimizations=yes
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
@ -71,7 +73,7 @@ windows_alias = "unsupported"
[tasks.fuzzer_unix]
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" ]
# Run the fuzzer

View File

@ -2,9 +2,9 @@
//! The example harness is built for libpng.
//! In this example, you will see the use of the `launcher` feature.
//! The `launcher` will spawn new processes for each cpu core.
use mimalloc::MiMalloc;
#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc;
//use mimalloc::MiMalloc;
//#[global_allocator]
//static GLOBAL: MiMalloc = MiMalloc;
use core::time::Duration;
use std::{env, net::SocketAddr, path::PathBuf};
@ -197,7 +197,15 @@ pub fn libafl_main() {
let mut harness = |input: &BytesInput| {
let target = input.target_bytes();
let buf = target.as_slice();
// Artificial timeout to check timeout
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
};

View File

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

View File

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

View File

@ -499,7 +499,6 @@ where
Ok(cur)
} else {
if cur.as_millis() % 1000 == 0 {}
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
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
pub trait ConfigTarget {
@ -436,14 +436,20 @@ where
let last_run_timed_out = self.executor.forkserver().last_run_timed_out();
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 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();
// The first four bytes tells the size of the shmem.
shmem.as_mut_slice()[..4].copy_from_slice(&size_in_bytes[..4]);
shmem.as_mut_slice()[SHMEM_FUZZ_HDR_SIZE..(SHMEM_FUZZ_HDR_SIZE + size)]
.copy_from_slice(target_bytes.as_slice());
map.as_mut_slice()[..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)]
.copy_from_slice(&target_bytes.as_slice()[..size]);
} else {
self.executor
.input_file_mut()
@ -610,6 +616,7 @@ pub struct ForkserverExecutorBuilder<'a, SP> {
autotokens: Option<&'a mut Tokens>,
input_filename: Option<OsString>,
shmem_provider: Option<&'a mut SP>,
max_input_size: usize,
map_size: Option<usize>,
real_map_size: i32,
}
@ -716,10 +723,10 @@ impl<'a, SP> ForkserverExecutorBuilder<'a, SP> {
None => None,
Some(provider) => {
// 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")?;
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]);
Some(shmem)
}
@ -1035,6 +1042,7 @@ impl<'a> ForkserverExecutorBuilder<'a, UnixShMemProvider> {
shmem_provider: None,
map_size: None,
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),
map_size: self.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 target_bytes = input.target_bytes();
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
size = MAX_FILE;
size = max_size;
}
let size_in_bytes = size.to_ne_bytes();
// The first four bytes tells the size of the shmem.
map.as_mut_slice()[..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)]
.copy_from_slice(target_bytes.as_slice());
.copy_from_slice(&target_bytes.as_slice()[..size]);
} else {
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 last_diff: i64 = -1;
for (i, (this_el, other_el)) in this.iter().zip(other.iter()).enumerate() {
#[allow(clippy::cast_possible_wrap)]
if this_el != other_el {
if first_diff < 0 {
first_diff = i as i64;

View File

@ -693,7 +693,7 @@ impl AFLppRedQueen {
)),
0xffff,
),
4 | 5 | 6 | 7 => (
4..=7 => (
u64::from(u32::from_be_bytes(
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 {
let buf_32 = u32::from_be_bytes(buf[buf_idx..buf_idx + 4].try_into().unwrap());
let another_buf_32 =
@ -1448,7 +1448,7 @@ where
if !cmp_found {
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
{
let v = orig_v0.to_ne_bytes().to_vec();
@ -1456,7 +1456,7 @@ where
}
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
{
let v = orig_v1.to_ne_bytes().to_vec();
@ -1541,7 +1541,7 @@ where
if !cmp_found {
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
{
let v = orig_v0.to_ne_bytes().to_vec();
@ -1549,7 +1549,7 @@ where
}
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
{
let v = orig_v1.to_ne_bytes().to_vec();

View File

@ -353,7 +353,7 @@ where
let cnt = self.usable_count();
let map = self.as_slice();
let mut res = 0;
for x in map[0..cnt].iter() {
for x in &map[0..cnt] {
if *x != initial {
res += 1;
}
@ -386,7 +386,7 @@ where
let initial = self.initial();
let cnt = self.usable_count();
let map = self.as_mut_slice();
for x in map[0..cnt].iter_mut() {
for x in &mut map[0..cnt] {
*x = initial;
}
Ok(())
@ -815,7 +815,7 @@ where
let cnt = self.usable_count();
let map = self.as_slice();
let mut res = 0;
for x in map[0..cnt].iter() {
for x in &map[0..cnt] {
if *x != initial {
res += 1;
}
@ -838,7 +838,7 @@ where
let initial = self.initial();
let cnt = self.usable_count();
let map = self.as_mut_slice();
for x in map[0..cnt].iter_mut() {
for x in &mut map[0..cnt] {
*x = initial;
}
Ok(())
@ -1091,7 +1091,7 @@ where
let cnt = self.usable_count();
let map = self.as_slice();
let mut res = 0;
for x in map[0..cnt].iter() {
for x in &map[0..cnt] {
if *x != initial {
res += 1;
}
@ -1109,7 +1109,7 @@ where
let initial = self.initial();
let cnt = self.usable_count();
let map = self.as_mut_slice();
for x in map[0..cnt].iter_mut() {
for x in &mut map[0..cnt] {
*x = initial;
}
Ok(())
@ -2082,7 +2082,7 @@ where
let cnt = self.usable_count();
let map = self.as_slice();
let mut res = 0;
for x in map[0..cnt].iter() {
for x in &map[0..cnt] {
if *x != initial {
res += 1;
}
@ -2111,7 +2111,7 @@ where
let initial = self.initial();
let cnt = self.usable_count();
let map = self.as_mut_slice();
for x in map[0..cnt].iter_mut() {
for x in &mut map[0..cnt] {
*x = initial;
}
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
#[must_use]
pub fn get_asan_runtime_flags() -> String {
let flags = vec![
let flags = [
"exitcode=0",
"abort_on_error=1",
"handle_abort=1",

View File

@ -150,6 +150,7 @@ where
if !was_fuzzed {
let selection = Some(id);
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"));
}
}

View File

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

View File

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