Skip to content

allow failed afl mapping to allow non-forkserver usage #3087

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

Closed
wants to merge 13 commits into from
2 changes: 1 addition & 1 deletion libafl/src/events/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ where
return Err(Error::shutting_down());
}

#[cfg(all(unix, feature = "std"))]
#[cfg(all(unix, feature = "std", not(miri)))]
if child_status == SIGNAL_RECURSION_EXIT {
return Err(Error::illegal_state(
"The client is stuck in an unexpected signal handler recursion. It is most likely a fuzzer bug.",
Expand Down
6 changes: 6 additions & 0 deletions libafl_targets/src/coverage.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ uint8_t *__afl_area_ptr = __afl_area_ptr_local;
extern uint8_t __ddg_area_ptr_local[DDG_MAP_SIZE];
uint8_t *__ddg_area_ptr = __ddg_area_ptr_local;

extern uint8_t __afl_fuzz_ptr_local[EDGES_MAP_ALLOCATED_SIZE];
uint8_t *__afl_fuzz_ptr = __afl_fuzz_ptr_local;

extern uint32_t __afl_fuzz_len_local;
uint32_t *__afl_fuzz_len = &__afl_fuzz_len_local;

extern uint32_t __afl_acc_memop_ptr_local[ACCOUNTING_MAP_SIZE];
uint32_t *__afl_acc_memop_ptr = __afl_acc_memop_ptr_local;

Expand Down
25 changes: 25 additions & 0 deletions libafl_targets/src/coverage.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Coverage maps as static mut array

use core::ffi::c_uint;

#[cfg(any(
feature = "sancov_pcguard_edges",
feature = "sancov_pcguard_hitcounts",
Expand All @@ -20,6 +22,19 @@ use crate::{ACCOUNTING_MAP_SIZE, DDG_MAP_SIZE, EDGES_MAP_ALLOCATED_SIZE, EDGES_M
pub static mut __afl_area_ptr_local: [u8; EDGES_MAP_ALLOCATED_SIZE] = [0; EDGES_MAP_ALLOCATED_SIZE];
pub use __afl_area_ptr_local as EDGES_MAP;

/// The map for input.
#[unsafe(no_mangle)]
#[allow(non_upper_case_globals)] // expect breaks here for some reason
pub static mut __afl_fuzz_ptr_local: [u8; EDGES_MAP_ALLOCATED_SIZE] = [0; EDGES_MAP_ALLOCATED_SIZE];
pub use __afl_fuzz_ptr_local as INPUT_MAP;

/// The length of input mapping
#[unsafe(no_mangle)]
#[allow(non_upper_case_globals)] // expect breaks here for some reason
pub static mut __afl_fuzz_len_local: u32 = 0;
pub use __afl_fuzz_len_local as INPUT_LENGTH;


/// The map for data dependency
#[unsafe(no_mangle)]
#[allow(non_upper_case_globals)] // expect breaks here for some reason
Expand All @@ -39,6 +54,12 @@ pub use __afl_acc_memop_ptr_local as ACCOUNTING_MEMOP_MAP;
pub static mut MAX_EDGES_FOUND: usize = 0;

unsafe extern "C" {
/// The sharedmemort fuzzing flag
pub static mut __afl_sharedmem_fuzzing: c_uint;
/// The pointer points to the length of AFL++ inputs
pub static mut __afl_fuzz_len: *mut u32;
/// The pointer points to the AFL++ inputs
pub static mut __afl_fuzz_ptr: *mut u8;
/// The area pointer points to the edges map.
pub static mut __afl_area_ptr: *mut u8;

Expand All @@ -56,9 +77,12 @@ unsafe extern "C" {
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
pub static __token_stop: *const u8;
}
pub use __afl_sharedmem_fuzzing as SHM_FUZZING;
pub use __afl_acc_memop_ptr as ACCOUNTING_MEMOP_MAP_PTR;
pub use __afl_area_ptr as EDGES_MAP_PTR;
pub use __ddg_area_ptr as DDG_MAP_PTR;
pub use __afl_fuzz_ptr as INPUT_PTR;
pub use __afl_fuzz_len as INPUT_LENGTH_PTR;

/// Return Tokens from the compile-time token section
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
Expand All @@ -81,6 +105,7 @@ pub fn autotokens() -> Result<Tokens, Error> {
#[allow(non_upper_case_globals)] // expect breaks here for some reason
#[unsafe(no_mangle)]
pub static mut __afl_map_size: usize = EDGES_MAP_DEFAULT_SIZE;
pub use __afl_map_size as EDGES_MAP_SIZE;

#[cfg(any(
feature = "sancov_pcguard_edges",
Expand Down
42 changes: 26 additions & 16 deletions libafl_targets/src/forkserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@
#define SHM_ENV_VAR "__AFL_SHM_ID"
#define SHM_FUZZ_ENV_VAR "__AFL_SHM_FUZZ_ID"
#define DEFAULT_PERMISSION 0600
#define MAP_SIZE (1U << MAP_SIZE_POW2)
#if MAP_SIZE <= 2097152
#define MAP_INITIAL_SIZE (2 << 20) // = 2097152
#else
#define MAP_INITIAL_SIZE MAP_SIZE
#endif

/* Reporting errors */
#define FS_OPT_ERROR 0xf800008f
Expand Down Expand Up @@ -64,14 +70,19 @@

int __afl_sharedmem_fuzzing __attribute__((weak));

static uint8_t __afl_area_initial[MAP_INITIAL_SIZE];
static uint8_t *__afl_area_ptr_dummy = __afl_area_initial;
static uint8_t *__afl_area_ptr_backup = __afl_area_initial;

extern uint8_t *__afl_area_ptr;
extern size_t __afl_map_size;
extern uint8_t *__token_start;
extern uint8_t *__token_stop;
extern uint8_t *__afl_fuzz_ptr;
extern uint32_t *__afl_fuzz_len;

uint8_t *__afl_fuzz_ptr;
static uint32_t __afl_fuzz_len_local;
uint32_t *__afl_fuzz_len = &__afl_fuzz_len_local;
static uint8_t __afl_fuzz_ptr_initial[MAP_INITIAL_SIZE];
static uint32_t __afl_fuzz_len_local = 0;

int already_initialized_shm;
int already_initialized_forkserver;
Expand Down Expand Up @@ -109,9 +120,8 @@ static void at_exit(int signal) {

/* SHM fuzzing setup. */

void __afl_map_shm(void) {
if (already_initialized_shm) return;
already_initialized_shm = 1;
uint8_t __afl_map_shm(void){
if (already_initialized_shm) return 1;

char *id_str = getenv(SHM_ENV_VAR);

Expand Down Expand Up @@ -161,15 +171,15 @@ void __afl_map_shm(void) {
our parent doesn't give up on us. */

__afl_area_ptr[0] = 1;
already_initialized_shm = 1;
return 1;
} else {
fprintf(stderr,
"Error: variable for edge coverage shared memory is not set\n");
send_forkserver_error(FS_ERROR_SHM_OPEN);
exit(1);
__afl_area_ptr = __afl_area_initial;
return 0;
}
}

static void map_input_shared_memory() {
uint8_t __afl_map_input_shm() {
char *id_str = getenv(SHM_FUZZ_ENV_VAR);

if (id_str) {
Expand Down Expand Up @@ -206,11 +216,11 @@ static void map_input_shared_memory() {

__afl_fuzz_len = (uint32_t *)map;
__afl_fuzz_ptr = map + sizeof(uint32_t);

return 1;
} else {
fprintf(stderr, "Error: variable for fuzzing shared memory is not set\n");
send_forkserver_error(FS_ERROR_SHM_OPEN);
exit(1);
__afl_fuzz_ptr = __afl_fuzz_ptr_initial;
__afl_fuzz_len = &__afl_fuzz_len_local;
return 0;
}
}

Expand Down Expand Up @@ -294,7 +304,7 @@ void __afl_start_forkserver(void) {
status = version;
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }

if (__afl_sharedmem_fuzzing) { map_input_shared_memory(); }
if (__afl_sharedmem_fuzzing && !__afl_fuzz_ptr) { __afl_map_input_shm(); }

while (1) {
int status;
Expand Down
34 changes: 30 additions & 4 deletions libafl_targets/src/forkserver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,44 @@

unsafe extern "C" {
/// Map a shared memory region for the edge coverage map.
fn __afl_map_shm();
fn __afl_map_shm() -> u8;
/// Map the input shared memory
fn __afl_map_input_shm() -> u8;
/// Start the forkserver.
fn __afl_start_forkserver();
}

/// Map a shared memory region for the edge coverage map.
/// Map a shared memory region for the edge coverage map, also referred as
/// [`crate::coverage::EDGES_MAP_PTR`]. This function will intialize
/// [`crate::coverage::EDGES_MAP_PTR`] to a dummy memory region if
/// AFL is not present and return false.
///
/// # Note
///
/// The function's logic is written in C and this code is a wrapper.
pub fn map_shared_memory() {
unsafe { __afl_map_shm() }
pub fn map_shared_memory() -> bool {
let ret = unsafe { __afl_map_shm() > 0 };
if !ret {
log::debug!("Shared memory for edge coverage map is not detected!");
}
ret
}

/// Map the input shared memory region, also referred as [`crate::coverage::INPUT_PTR`].
/// [`start_forkserver`] will call this function automatically if the shared
/// memory feature is enabled. Likewise, [`crate::coverage::INPUT_PTR`] will be
/// initialized to a dummy memory region if AFL is not present.
///
/// # Note
///
/// The function's logic is written in C and this code is a wrapper.
pub fn map_input_shared_memory() -> bool {
let ret = unsafe { __afl_map_input_shm() > 0};

if !ret {
log::debug!("Shared memory for AFL++ inputs is not detected!");
}
ret
}

/// Start the forkserver from this point. Any shared memory must be created before.
Expand Down
Loading