mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-14 02:58:08 +00:00
persistent mode: shared memory test case transfer
This commit is contained in:
@ -10,6 +10,8 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
|
|||||||
|
|
||||||
|
|
||||||
### Version ++2.65d (dev)
|
### Version ++2.65d (dev)
|
||||||
|
- initial support for persistent mode shared memory testcase handover
|
||||||
|
(instead of via files/stdin)
|
||||||
- afl-fuzz:
|
- afl-fuzz:
|
||||||
- -S slaves now only sync from the master to increase performance,
|
- -S slaves now only sync from the master to increase performance,
|
||||||
the -M master stilly syncs from everyone. Added checks that exactly
|
the -M master stilly syncs from everyone. Added checks that exactly
|
||||||
|
@ -63,7 +63,7 @@ int main(int argc, char **argv) {
|
|||||||
We just have some trivial inline code that faults on 'foo!'. */
|
We just have some trivial inline code that faults on 'foo!'. */
|
||||||
|
|
||||||
/* do we have enough data? */
|
/* do we have enough data? */
|
||||||
if (len < 4) return 0;
|
if (len < 8) return 0;
|
||||||
|
|
||||||
if (buf[0] == 'f') {
|
if (buf[0] == 'f') {
|
||||||
|
|
||||||
@ -77,7 +77,17 @@ int main(int argc, char **argv) {
|
|||||||
if (buf[3] == '!') {
|
if (buf[3] == '!') {
|
||||||
|
|
||||||
printf("four\n");
|
printf("four\n");
|
||||||
abort();
|
if (buf[4] == '!') {
|
||||||
|
|
||||||
|
printf("five\n");
|
||||||
|
if (buf[5] == '!') {
|
||||||
|
|
||||||
|
printf("six\n");
|
||||||
|
abort();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
118
examples/persistent_demo/persistent_demo_new.c
Normal file
118
examples/persistent_demo/persistent_demo_new.c
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
american fuzzy lop++ - persistent mode example
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
|
Copyright 2015 Google Inc. All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at:
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
This file demonstrates the high-performance "persistent mode" that may be
|
||||||
|
suitable for fuzzing certain fast and well-behaved libraries, provided that
|
||||||
|
they are stateless or that their internal state can be easily reset
|
||||||
|
across runs.
|
||||||
|
|
||||||
|
To make this work, the library and this shim need to be compiled in LLVM
|
||||||
|
mode using afl-clang-fast (other compiler wrappers will *not* work).
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
__AFL_FUZZ_INIT();
|
||||||
|
|
||||||
|
unsigned int crc32_for_byte(unsigned int r) {
|
||||||
|
|
||||||
|
for (int j = 0; j < 8; ++j)
|
||||||
|
r = (r & 1 ? 0 : (unsigned int)0xEDB88320L) ^ r >> 1;
|
||||||
|
return r ^ (unsigned int)0xFF000000L;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int crc32(unsigned char *data, unsigned int n_bytes) {
|
||||||
|
|
||||||
|
static unsigned char table[0x100];
|
||||||
|
unsigned int crc = 0;
|
||||||
|
if (!*table)
|
||||||
|
for (unsigned int i = 0; i < 0x100; ++i)
|
||||||
|
table[i] = crc32_for_byte(i);
|
||||||
|
for (unsigned int i = 0; i < n_bytes; ++i)
|
||||||
|
crc = table[(unsigned char)crc ^ (data)[i]] ^ crc >> 8;
|
||||||
|
return crc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main entry point. */
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
|
ssize_t len; /* how much input did we read? */
|
||||||
|
unsigned char *buf; /* test case buffer pointer */
|
||||||
|
|
||||||
|
/* The number passed to __AFL_LOOP() controls the maximum number of
|
||||||
|
iterations before the loop exits and the program is allowed to
|
||||||
|
terminate normally. This limits the impact of accidental memory leaks
|
||||||
|
and similar hiccups. */
|
||||||
|
|
||||||
|
buf = __AFL_FUZZ_TESTCASE_BUF;
|
||||||
|
|
||||||
|
while (__AFL_LOOP(1000)) {
|
||||||
|
|
||||||
|
len = __AFL_FUZZ_TESTCASE_LEN;
|
||||||
|
|
||||||
|
/* do we have enough data? */
|
||||||
|
if (len < 8) return 0;
|
||||||
|
|
||||||
|
if (buf[0] == 'f') {
|
||||||
|
|
||||||
|
printf("one\n");
|
||||||
|
if (buf[1] == 'o') {
|
||||||
|
|
||||||
|
printf("two\n");
|
||||||
|
if (buf[2] == 'o') {
|
||||||
|
|
||||||
|
printf("three\n");
|
||||||
|
if (buf[3] == '!') {
|
||||||
|
|
||||||
|
printf("four\n");
|
||||||
|
if (buf[4] == '!') {
|
||||||
|
|
||||||
|
printf("five\n");
|
||||||
|
if (buf[6] == '!') {
|
||||||
|
|
||||||
|
printf("six\n");
|
||||||
|
abort();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** END PLACEHOLDER CODE ***/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Once the loop is exited, terminate normally - AFL will restart the process
|
||||||
|
when this happens, with a clean slate when it comes to allocated memory,
|
||||||
|
leftover file descriptors, etc. */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -342,6 +342,7 @@ typedef struct afl_state {
|
|||||||
|
|
||||||
afl_forkserver_t fsrv;
|
afl_forkserver_t fsrv;
|
||||||
sharedmem_t shm;
|
sharedmem_t shm;
|
||||||
|
sharedmem_t * shm_fuzz;
|
||||||
afl_env_vars_t afl_env;
|
afl_env_vars_t afl_env;
|
||||||
|
|
||||||
char **argv; /* argv if needed */
|
char **argv; /* argv if needed */
|
||||||
|
@ -304,6 +304,10 @@
|
|||||||
|
|
||||||
#define SHM_ENV_VAR "__AFL_SHM_ID"
|
#define SHM_ENV_VAR "__AFL_SHM_ID"
|
||||||
|
|
||||||
|
/* Environment variable used to pass SHM FUZZ ID to the called program. */
|
||||||
|
|
||||||
|
#define SHM_FUZZ_ENV_VAR "__AFL_SHM_FUZZ_ID"
|
||||||
|
|
||||||
/* Other less interesting, internal-only variables. */
|
/* Other less interesting, internal-only variables. */
|
||||||
|
|
||||||
#define CLANG_ENV_VAR "__AFL_CLANG_MODE"
|
#define CLANG_ENV_VAR "__AFL_CLANG_MODE"
|
||||||
|
@ -73,10 +73,18 @@ typedef struct afl_forkserver {
|
|||||||
|
|
||||||
u8 last_kill_signal; /* Signal that killed the child */
|
u8 last_kill_signal; /* Signal that killed the child */
|
||||||
|
|
||||||
|
u8 use_shdmen_fuzz; /* use shared mem for test cases */
|
||||||
|
|
||||||
|
u8 support_shdmen_fuzz; /* set by afl-fuzz */
|
||||||
|
|
||||||
u8 use_fauxsrv; /* Fauxsrv for non-forking targets? */
|
u8 use_fauxsrv; /* Fauxsrv for non-forking targets? */
|
||||||
|
|
||||||
u8 qemu_mode; /* if running in qemu mode or not */
|
u8 qemu_mode; /* if running in qemu mode or not */
|
||||||
|
|
||||||
|
u32 shdmem_fuzz_len; /* length of the fuzzing test case */
|
||||||
|
|
||||||
|
u8 *shdmem_fuzz; /* allocated memory for fuzzing */
|
||||||
|
|
||||||
char *cmplog_binary; /* the name of the cmplog binary */
|
char *cmplog_binary; /* the name of the cmplog binary */
|
||||||
|
|
||||||
/* Function to kick off the forkserver child */
|
/* Function to kick off the forkserver child */
|
||||||
|
@ -43,10 +43,11 @@ typedef uint32_t u32;
|
|||||||
#define FS_ERROR_MMAP 16
|
#define FS_ERROR_MMAP 16
|
||||||
|
|
||||||
/* Reporting options */
|
/* Reporting options */
|
||||||
#define FS_OPT_ENABLED 0x8f000001
|
#define FS_OPT_ENABLED 0x80000001
|
||||||
#define FS_OPT_MAPSIZE 0x40000000
|
#define FS_OPT_MAPSIZE 0x40000000
|
||||||
#define FS_OPT_SNAPSHOT 0x20000000
|
#define FS_OPT_SNAPSHOT 0x20000000
|
||||||
#define FS_OPT_AUTODICT 0x10000000
|
#define FS_OPT_AUTODICT 0x10000000
|
||||||
|
#define FS_OPT_SHDMEM_FUZZ 0x01000000
|
||||||
// FS_OPT_MAX_MAPSIZE is 8388608 = 0x800000 = 2^23 = 1 << 22
|
// FS_OPT_MAX_MAPSIZE is 8388608 = 0x800000 = 2^23 = 1 << 22
|
||||||
#define FS_OPT_MAX_MAPSIZE ((0x00fffffe >> 1) + 1)
|
#define FS_OPT_MAX_MAPSIZE ((0x00fffffe >> 1) + 1)
|
||||||
#define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1)
|
#define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1)
|
||||||
|
@ -489,6 +489,14 @@ static void edit_params(u32 argc, char **argv, char **envp) {
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
cc_params[cc_par_cnt++] =
|
||||||
|
"-D__AFL_FUZZ_INIT()="
|
||||||
|
"int __afl_sharedmem_fuzzing = 1;"
|
||||||
|
"extern unsigned int __afl_fuzz_len;"
|
||||||
|
"extern unsigned char *__afl_fuzz_ptr;";
|
||||||
|
cc_params[cc_par_cnt++] = "-D__AFL_FUZZ_TESTCASE_BUF=__afl_fuzz_ptr";
|
||||||
|
cc_params[cc_par_cnt++] = "-D__AFL_FUZZ_TESTCASE_LEN=__afl_fuzz_len";
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] =
|
cc_params[cc_par_cnt++] =
|
||||||
"-D__AFL_LOOP(_A)="
|
"-D__AFL_LOOP(_A)="
|
||||||
"({ static volatile char *_B __attribute__((used)); "
|
"({ static volatile char *_B __attribute__((used)); "
|
||||||
|
@ -76,6 +76,8 @@ u8 __afl_area_initial[MAP_SIZE];
|
|||||||
#endif
|
#endif
|
||||||
u8 *__afl_area_ptr = __afl_area_initial;
|
u8 *__afl_area_ptr = __afl_area_initial;
|
||||||
u8 *__afl_dictionary;
|
u8 *__afl_dictionary;
|
||||||
|
u8 *__afl_fuzz_ptr;
|
||||||
|
u32 __afl_fuzz_len;
|
||||||
|
|
||||||
u32 __afl_final_loc;
|
u32 __afl_final_loc;
|
||||||
u32 __afl_map_size = MAP_SIZE;
|
u32 __afl_map_size = MAP_SIZE;
|
||||||
@ -92,6 +94,8 @@ __thread u32 __afl_prev_ctx;
|
|||||||
__thread u32 __afl_cmp_counter;
|
__thread u32 __afl_cmp_counter;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int __afl_sharedmem_fuzzing __attribute__((weak));
|
||||||
|
|
||||||
struct cmp_map *__afl_cmp_map;
|
struct cmp_map *__afl_cmp_map;
|
||||||
|
|
||||||
/* Running in persistent mode? */
|
/* Running in persistent mode? */
|
||||||
@ -109,6 +113,59 @@ void send_forkserver_error(int error) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* SHM fuzzing setup. */
|
||||||
|
|
||||||
|
static void __afl_map_shm_fuzz() {
|
||||||
|
|
||||||
|
char *id_str = getenv(SHM_FUZZ_ENV_VAR);
|
||||||
|
|
||||||
|
if (id_str) {
|
||||||
|
|
||||||
|
#ifdef USEMMAP
|
||||||
|
const char * shm_file_path = id_str;
|
||||||
|
int shm_fd = -1;
|
||||||
|
unsigned char *shm_base = NULL;
|
||||||
|
|
||||||
|
/* create the shared memory segment as if it was a file */
|
||||||
|
shm_fd = shm_open(shm_file_path, O_RDWR, 0600);
|
||||||
|
if (shm_fd == -1) {
|
||||||
|
|
||||||
|
fprintf(stderr, "shm_open() failed for fuzz\n");
|
||||||
|
send_forkserver_error(FS_ERROR_SHM_OPEN);
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
__afl_fuzz_ptr = mmap(0, MAX_FILE, PROT_READ, MAP_SHARED, shm_fd, 0);
|
||||||
|
|
||||||
|
#else
|
||||||
|
u32 shm_id = atoi(id_str);
|
||||||
|
|
||||||
|
__afl_fuzz_ptr = shmat(shm_id, NULL, 0);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Whooooops. */
|
||||||
|
|
||||||
|
if (__afl_fuzz_ptr == (void *)-1) {
|
||||||
|
|
||||||
|
fprintf(stderr, "Error: could not access fuzzing shared memory\n");
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getenv("AFL_DEBUG"))
|
||||||
|
fprintf(stderr, "DEBUG: successfully got fuzzing shared memory\n");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
fprintf(stderr, "Error: variable for fuzzing shared memory is not set\n");
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* SHM setup. */
|
/* SHM setup. */
|
||||||
|
|
||||||
static void __afl_map_shm(void) {
|
static void __afl_map_shm(void) {
|
||||||
@ -310,17 +367,25 @@ static void __afl_start_snapshots(void) {
|
|||||||
assume we're not running in forkserver mode and just execute program. */
|
assume we're not running in forkserver mode and just execute program. */
|
||||||
|
|
||||||
status |= (FS_OPT_ENABLED | FS_OPT_SNAPSHOT);
|
status |= (FS_OPT_ENABLED | FS_OPT_SNAPSHOT);
|
||||||
|
if (__afl_sharedmem_fuzzing != 0) status |= FS_OPT_SHDMEM_FUZZ;
|
||||||
if (__afl_map_size <= FS_OPT_MAX_MAPSIZE)
|
if (__afl_map_size <= FS_OPT_MAX_MAPSIZE)
|
||||||
status |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE);
|
status |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE);
|
||||||
if (__afl_dictionary_len > 0 && __afl_dictionary) status |= FS_OPT_AUTODICT;
|
if (__afl_dictionary_len && __afl_dictionary) status |= FS_OPT_AUTODICT;
|
||||||
memcpy(tmp, &status, 4);
|
memcpy(tmp, &status, 4);
|
||||||
|
|
||||||
if (write(FORKSRV_FD + 1, tmp, 4) != 4) return;
|
if (write(FORKSRV_FD + 1, tmp, 4) != 4) return;
|
||||||
|
|
||||||
if (__afl_dictionary_len > 0 && __afl_dictionary) {
|
if (__afl_sharedmem_fuzzing || (__afl_dictionary_len && __afl_dictionary)) {
|
||||||
|
|
||||||
if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1);
|
if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1);
|
||||||
|
|
||||||
|
if ((was_killed & (0xffffffff & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ))) ==
|
||||||
|
(FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) {
|
||||||
|
|
||||||
|
__afl_map_shm_fuzz();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if ((was_killed & (FS_OPT_ENABLED | FS_OPT_AUTODICT)) ==
|
if ((was_killed & (FS_OPT_ENABLED | FS_OPT_AUTODICT)) ==
|
||||||
(FS_OPT_ENABLED | FS_OPT_AUTODICT)) {
|
(FS_OPT_ENABLED | FS_OPT_AUTODICT)) {
|
||||||
|
|
||||||
@ -357,7 +422,7 @@ static void __afl_start_snapshots(void) {
|
|||||||
|
|
||||||
// uh this forkserver master does not understand extended option passing
|
// uh this forkserver master does not understand extended option passing
|
||||||
// or does not want the dictionary
|
// or does not want the dictionary
|
||||||
already_read_first = 1;
|
if (!__afl_fuzz_ptr) already_read_first = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,6 +443,9 @@ static void __afl_start_snapshots(void) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__afl_fuzz_len = (was_killed >> 8);
|
||||||
|
was_killed = (was_killed & 0xff);
|
||||||
|
|
||||||
/* If we stopped the child in persistent mode, but there was a race
|
/* If we stopped the child in persistent mode, but there was a race
|
||||||
condition and afl-fuzz already issued SIGKILL, write off the old
|
condition and afl-fuzz already issued SIGKILL, write off the old
|
||||||
process. */
|
process. */
|
||||||
@ -473,7 +541,8 @@ static void __afl_start_forkserver(void) {
|
|||||||
|
|
||||||
if (__afl_map_size <= FS_OPT_MAX_MAPSIZE)
|
if (__afl_map_size <= FS_OPT_MAX_MAPSIZE)
|
||||||
status |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE);
|
status |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE);
|
||||||
if (__afl_dictionary_len > 0 && __afl_dictionary) status |= FS_OPT_AUTODICT;
|
if (__afl_dictionary_len && __afl_dictionary) status |= FS_OPT_AUTODICT;
|
||||||
|
if (__afl_sharedmem_fuzzing != 0) status |= FS_OPT_SHDMEM_FUZZ;
|
||||||
if (status) status |= (FS_OPT_ENABLED);
|
if (status) status |= (FS_OPT_ENABLED);
|
||||||
memcpy(tmp, &status, 4);
|
memcpy(tmp, &status, 4);
|
||||||
|
|
||||||
@ -482,10 +551,17 @@ static void __afl_start_forkserver(void) {
|
|||||||
|
|
||||||
if (write(FORKSRV_FD + 1, tmp, 4) != 4) return;
|
if (write(FORKSRV_FD + 1, tmp, 4) != 4) return;
|
||||||
|
|
||||||
if (__afl_dictionary_len > 0 && __afl_dictionary) {
|
if (__afl_sharedmem_fuzzing || (__afl_dictionary_len && __afl_dictionary)) {
|
||||||
|
|
||||||
if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1);
|
if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1);
|
||||||
|
|
||||||
|
if ((was_killed & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) ==
|
||||||
|
(FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) {
|
||||||
|
|
||||||
|
__afl_map_shm_fuzz();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if ((was_killed & (FS_OPT_ENABLED | FS_OPT_AUTODICT)) ==
|
if ((was_killed & (FS_OPT_ENABLED | FS_OPT_AUTODICT)) ==
|
||||||
(FS_OPT_ENABLED | FS_OPT_AUTODICT)) {
|
(FS_OPT_ENABLED | FS_OPT_AUTODICT)) {
|
||||||
|
|
||||||
@ -522,7 +598,7 @@ static void __afl_start_forkserver(void) {
|
|||||||
|
|
||||||
// uh this forkserver master does not understand extended option passing
|
// uh this forkserver master does not understand extended option passing
|
||||||
// or does not want the dictionary
|
// or does not want the dictionary
|
||||||
already_read_first = 1;
|
if (!__afl_fuzz_ptr) already_read_first = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,6 +620,9 @@ static void __afl_start_forkserver(void) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__afl_fuzz_len = (was_killed >> 8);
|
||||||
|
was_killed = (was_killed & 0xff);
|
||||||
|
|
||||||
/* If we stopped the child in persistent mode, but there was a race
|
/* If we stopped the child in persistent mode, but there was a race
|
||||||
condition and afl-fuzz already issued SIGKILL, write off the old
|
condition and afl-fuzz already issued SIGKILL, write off the old
|
||||||
process. */
|
process. */
|
||||||
|
@ -442,7 +442,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
|
|
||||||
if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) {
|
if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) {
|
||||||
|
|
||||||
if (!be_quiet && getenv("AFL_DEBUG")) {
|
if (getenv("AFL_DEBUG")) {
|
||||||
|
|
||||||
ACTF("Extended forkserver functions received (%08x).", status);
|
ACTF("Extended forkserver functions received (%08x).", status);
|
||||||
|
|
||||||
@ -455,6 +455,28 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((status & FS_OPT_SHDMEM_FUZZ) == FS_OPT_SHDMEM_FUZZ) {
|
||||||
|
|
||||||
|
if (fsrv->support_shdmen_fuzz) {
|
||||||
|
|
||||||
|
fsrv->use_shdmen_fuzz = 1;
|
||||||
|
if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); }
|
||||||
|
|
||||||
|
if ((status & FS_OPT_AUTODICT) == 0) {
|
||||||
|
|
||||||
|
u32 send_status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
|
||||||
|
if (write(fsrv->fsrv_ctl_fd, &send_status, 4) != 4) {
|
||||||
|
|
||||||
|
FATAL("Writing to forkserver failed.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if ((status & FS_OPT_MAPSIZE) == FS_OPT_MAPSIZE) {
|
if ((status & FS_OPT_MAPSIZE) == FS_OPT_MAPSIZE) {
|
||||||
|
|
||||||
u32 tmp_map_size = FS_OPT_GET_MAPSIZE(status);
|
u32 tmp_map_size = FS_OPT_GET_MAPSIZE(status);
|
||||||
@ -490,7 +512,10 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
if (fsrv->function_ptr == NULL || fsrv->function_opt == NULL) {
|
if (fsrv->function_ptr == NULL || fsrv->function_opt == NULL) {
|
||||||
|
|
||||||
// this is not afl-fuzz - we deny and return
|
// this is not afl-fuzz - we deny and return
|
||||||
status = (0xffffffff ^ (FS_OPT_ENABLED | FS_OPT_AUTODICT));
|
if (fsrv->use_shdmen_fuzz)
|
||||||
|
status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ);
|
||||||
|
else
|
||||||
|
status = (FS_OPT_ENABLED | FS_OPT_AUTODICT);
|
||||||
if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
|
if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
|
||||||
|
|
||||||
FATAL("Writing to forkserver failed.");
|
FATAL("Writing to forkserver failed.");
|
||||||
@ -749,39 +774,48 @@ static void afl_fsrv_kill(afl_forkserver_t *fsrv) {
|
|||||||
|
|
||||||
void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
|
void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
|
||||||
|
|
||||||
s32 fd = fsrv->out_fd;
|
if (fsrv->shdmem_fuzz) {
|
||||||
|
|
||||||
if (fsrv->out_file) {
|
memcpy(fsrv->shdmem_fuzz, buf, len);
|
||||||
|
fsrv->shdmem_fuzz_len = len;
|
||||||
|
|
||||||
if (fsrv->no_unlink) {
|
} else {
|
||||||
|
|
||||||
fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
s32 fd = fsrv->out_fd;
|
||||||
|
|
||||||
|
if (fsrv->out_file) {
|
||||||
|
|
||||||
|
if (fsrv->no_unlink) {
|
||||||
|
|
||||||
|
fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
unlink(fsrv->out_file); /* Ignore errors. */
|
||||||
|
fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd < 0) { PFATAL("Unable to create '%s'", fsrv->out_file); }
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
unlink(fsrv->out_file); /* Ignore errors. */
|
lseek(fd, 0, SEEK_SET);
|
||||||
fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fd < 0) { PFATAL("Unable to create '%s'", fsrv->out_file); }
|
ck_write(fd, buf, len, fsrv->out_file);
|
||||||
|
|
||||||
} else {
|
if (!fsrv->out_file) {
|
||||||
|
|
||||||
lseek(fd, 0, SEEK_SET);
|
if (ftruncate(fd, len)) { PFATAL("ftruncate() failed"); }
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
|
||||||
}
|
} else {
|
||||||
|
|
||||||
ck_write(fd, buf, len, fsrv->out_file);
|
close(fd);
|
||||||
|
|
||||||
if (!fsrv->out_file) {
|
}
|
||||||
|
|
||||||
if (ftruncate(fd, len)) { PFATAL("ftruncate() failed"); }
|
|
||||||
lseek(fd, 0, SEEK_SET);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -795,6 +829,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
|||||||
|
|
||||||
s32 res;
|
s32 res;
|
||||||
u32 exec_ms;
|
u32 exec_ms;
|
||||||
|
u32 write_value = fsrv->last_run_timed_out;
|
||||||
|
|
||||||
/* After this memset, fsrv->trace_bits[] are effectively volatile, so we
|
/* After this memset, fsrv->trace_bits[] are effectively volatile, so we
|
||||||
must prevent any earlier operations from venturing into that
|
must prevent any earlier operations from venturing into that
|
||||||
@ -804,10 +839,12 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
|||||||
|
|
||||||
MEM_BARRIER();
|
MEM_BARRIER();
|
||||||
|
|
||||||
|
if (fsrv->shdmem_fuzz_len) write_value += (fsrv->shdmem_fuzz_len << 8);
|
||||||
|
|
||||||
/* we have the fork server (or faux server) up and running
|
/* we have the fork server (or faux server) up and running
|
||||||
First, tell it if the previous run timed out. */
|
First, tell it if the previous run timed out. */
|
||||||
|
|
||||||
if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->last_run_timed_out, 4)) != 4) {
|
if ((res = write(fsrv->fsrv_ctl_fd, &write_value, 4)) != 4) {
|
||||||
|
|
||||||
if (*stop_soon_p) { return 0; }
|
if (*stop_soon_p) { return 0; }
|
||||||
RPFATAL(res, "Unable to request new process from fork server (OOM?)");
|
RPFATAL(res, "Unable to request new process from fork server (OOM?)");
|
||||||
|
@ -2153,6 +2153,30 @@ void check_binary(afl_state_t *afl, u8 *fname) {
|
|||||||
OKF(cPIN "Persistent mode binary detected.");
|
OKF(cPIN "Persistent mode binary detected.");
|
||||||
setenv(PERSIST_ENV_VAR, "1", 1);
|
setenv(PERSIST_ENV_VAR, "1", 1);
|
||||||
afl->persistent_mode = 1;
|
afl->persistent_mode = 1;
|
||||||
|
// do not fail if we can not get the fuzzing shared mem
|
||||||
|
if ((afl->shm_fuzz = calloc(1, sizeof(sharedmem_t)))) {
|
||||||
|
|
||||||
|
// we need to set the dumb mode to not overwrite the SHM_ENV_VAR
|
||||||
|
if ((afl->fsrv.shdmem_fuzz = afl_shm_init(afl->shm_fuzz, MAX_FILE, 1))) {
|
||||||
|
|
||||||
|
#ifdef USEMMAP
|
||||||
|
setenv(SHM_FUZZ_ENV_VAR, afl->shm_fuzz->g_shm_file_path, 1);
|
||||||
|
#else
|
||||||
|
u8 *shm_str;
|
||||||
|
shm_str = alloc_printf("%d", afl->shm_fuzz->shm_id);
|
||||||
|
setenv(SHM_FUZZ_ENV_VAR, shm_str, 1);
|
||||||
|
ck_free(shm_str);
|
||||||
|
#endif
|
||||||
|
afl->fsrv.support_shdmen_fuzz = 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
free(afl->shm_fuzz);
|
||||||
|
afl->shm_fuzz = NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
} else if (getenv("AFL_PERSISTENT")) {
|
} else if (getenv("AFL_PERSISTENT")) {
|
||||||
|
|
||||||
|
@ -231,6 +231,16 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
|
|||||||
afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon,
|
afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon,
|
||||||
afl->afl_env.afl_debug_child_output);
|
afl->afl_env.afl_debug_child_output);
|
||||||
|
|
||||||
|
if (afl->fsrv.support_shdmen_fuzz && !afl->fsrv.use_shdmen_fuzz) {
|
||||||
|
|
||||||
|
afl_shm_deinit(afl->shm_fuzz);
|
||||||
|
free(afl->shm_fuzz);
|
||||||
|
afl->shm_fuzz = NULL;
|
||||||
|
afl->fsrv.support_shdmen_fuzz = 0;
|
||||||
|
afl->fsrv.shdmem_fuzz = NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (q->exec_cksum) {
|
if (q->exec_cksum) {
|
||||||
|
@ -1379,6 +1379,14 @@ stop_fuzzing:
|
|||||||
destroy_extras(afl);
|
destroy_extras(afl);
|
||||||
destroy_custom_mutators(afl);
|
destroy_custom_mutators(afl);
|
||||||
afl_shm_deinit(&afl->shm);
|
afl_shm_deinit(&afl->shm);
|
||||||
|
|
||||||
|
if (afl->shm_fuzz) {
|
||||||
|
|
||||||
|
afl_shm_deinit(afl->shm_fuzz);
|
||||||
|
free(afl->shm_fuzz);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
afl_fsrv_deinit(&afl->fsrv);
|
afl_fsrv_deinit(&afl->fsrv);
|
||||||
if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); }
|
if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); }
|
||||||
ck_free(afl->fsrv.target_path);
|
ck_free(afl->fsrv.target_path);
|
||||||
|
Reference in New Issue
Block a user