diff options
Diffstat (limited to 'llvm_mode/afl-llvm-rt.o.c')
-rw-r--r-- | llvm_mode/afl-llvm-rt.o.c | 194 |
1 files changed, 160 insertions, 34 deletions
diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c index fcacc675..d00fd26f 100644 --- a/llvm_mode/afl-llvm-rt.o.c +++ b/llvm_mode/afl-llvm-rt.o.c @@ -35,6 +35,8 @@ #include <string.h> #include <assert.h> #include <stdint.h> +#include <stddef.h> +#include <limits.h> #include <errno.h> #include <sys/mman.h> @@ -42,6 +44,8 @@ #include <sys/wait.h> #include <sys/types.h> +#include "llvm/Config/llvm-config.h" + #ifdef __linux__ #include "snapshot-inl.h" #endif @@ -50,8 +54,6 @@ Basically, we need to make sure that the forkserver is initialized after the LLVM-generated runtime initialization pass, not before. */ -#define CONST_PRIO 5 - #ifndef MAP_FIXED_NOREPLACE #ifdef MAP_EXCL #define MAP_FIXED_NOREPLACE MAP_EXCL | MAP_FIXED @@ -60,6 +62,8 @@ #endif #endif +#define CTOR_PRIO 3 + #include <sys/mman.h> #include <fcntl.h> @@ -73,11 +77,7 @@ #define MAP_INITIAL_SIZE MAP_SIZE #endif -#ifdef AFL_REAL_LD -u8 __afl_area_initial[MAP_INITIAL_SIZE]; -#else -u8 __afl_area_initial[MAP_SIZE]; -#endif +u8 __afl_area_initial[MAP_INITIAL_SIZE]; u8 * __afl_area_ptr = __afl_area_initial; u8 * __afl_dictionary; u8 * __afl_fuzz_ptr; @@ -107,6 +107,10 @@ struct cmp_map *__afl_cmp_map; static u8 is_persistent; +/* Are we in sancov mode? */ + +static u8 _is_sancov; + /* Error reporting to forkserver controller */ void send_forkserver_error(int error) { @@ -183,14 +187,17 @@ static void __afl_map_shm_fuzz() { static void __afl_map_shm(void) { + // we we are not running in afl ensure the map exists + if (!__afl_area_ptr) { __afl_area_ptr = __afl_area_initial; } + char *id_str = getenv(SHM_ENV_VAR); if (__afl_final_loc) { if (__afl_final_loc % 8) __afl_final_loc = (((__afl_final_loc + 7) >> 3) << 3); - __afl_map_size = __afl_final_loc; + if (__afl_final_loc > MAP_SIZE) { char *ptr; @@ -200,10 +207,12 @@ static void __afl_map_shm(void) { if (__afl_final_loc > FS_OPT_MAX_MAPSIZE) { - fprintf(stderr, - "Error: AFL++ tools *require* to set AFL_MAP_SIZE to %u to " - "be able to run this instrumented program!\n", - __afl_final_loc); + if (!getenv("AFL_QUIET")) + fprintf(stderr, + "Error: AFL++ tools *require* to set AFL_MAP_SIZE to %u " + "to be able to run this instrumented program!\n", + __afl_final_loc); + if (id_str) { send_forkserver_error(FS_ERROR_MAP_SIZE); @@ -213,10 +222,11 @@ static void __afl_map_shm(void) { } else { - fprintf(stderr, - "Warning: AFL++ tools will need to set AFL_MAP_SIZE to %u to " - "be able to run this instrumented program!\n", - __afl_final_loc); + if (!getenv("AFL_QUIET")) + fprintf(stderr, + "Warning: AFL++ tools will need to set AFL_MAP_SIZE to %u " + "to be able to run this instrumented program!\n", + __afl_final_loc); } @@ -232,13 +242,25 @@ static void __afl_map_shm(void) { if (getenv("AFL_DEBUG")) fprintf(stderr, - "DEBUG: id_str %s, __afl_map_addr 0x%llx, MAP_SIZE %u, " - "__afl_final_loc %u, max_size_forkserver %u/0x%x\n", - id_str == NULL ? "<null>" : id_str, __afl_map_addr, MAP_SIZE, - __afl_final_loc, FS_OPT_MAX_MAPSIZE, FS_OPT_MAX_MAPSIZE); + "DEBUG: id_str %s, __afl_area_ptr %p, __afl_area_initial %p, " + "__afl_map_addr 0x%llx, MAP_SIZE %u, __afl_final_loc %u, " + "max_size_forkserver %u/0x%x\n", + id_str == NULL ? "<null>" : id_str, __afl_area_ptr, + __afl_area_initial, __afl_map_addr, MAP_SIZE, __afl_final_loc, + FS_OPT_MAX_MAPSIZE, FS_OPT_MAX_MAPSIZE); if (id_str) { + if (__afl_area_ptr && __afl_area_ptr != __afl_area_initial) { + + if (__afl_map_addr) + munmap((void *)__afl_map_addr, __afl_final_loc); + else + free(__afl_area_ptr); + __afl_area_ptr = __afl_area_initial; + + } + #ifdef USEMMAP const char * shm_file_path = id_str; int shm_fd = -1; @@ -307,11 +329,14 @@ static void __afl_map_shm(void) { __afl_area_ptr[0] = 1; - } else if (__afl_map_addr) { + } else if ((!__afl_area_ptr || __afl_area_ptr == __afl_area_initial) && + + __afl_map_addr) { __afl_area_ptr = mmap((void *)__afl_map_addr, __afl_map_size, PROT_READ | PROT_WRITE, MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0); + if (__afl_area_ptr == MAP_FAILED) { fprintf(stderr, "can not aquire mmap for address %p\n", @@ -320,14 +345,25 @@ static void __afl_map_shm(void) { } + } else if (_is_sancov && __afl_area_ptr != __afl_area_initial) { + + free(__afl_area_ptr); + __afl_area_ptr = NULL; + if (__afl_final_loc > MAP_INITIAL_SIZE) + __afl_area_ptr = malloc(__afl_final_loc); + if (!__afl_area_ptr) __afl_area_ptr = __afl_area_initial; + } id_str = getenv(CMPLOG_SHM_ENV_VAR); - if (getenv("AFL_DEBUG")) + if (getenv("AFL_DEBUG")) { + fprintf(stderr, "DEBUG: cmplog id_str %s\n", id_str == NULL ? "<null>" : id_str); + } + if (id_str) { #ifdef USEMMAP @@ -399,9 +435,12 @@ static void __afl_start_snapshots(void) { if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1); - if (getenv("AFL_DEBUG")) + if (getenv("AFL_DEBUG")) { + fprintf(stderr, "target forkserver recv: %08x\n", was_killed); + } + if ((was_killed & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) == (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) { @@ -608,9 +647,12 @@ static void __afl_start_forkserver(void) { if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1); - if (getenv("AFL_DEBUG")) + if (getenv("AFL_DEBUG")) { + fprintf(stderr, "target forkserver recv: %08x\n", was_killed); + } + if ((was_killed & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) == (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) { @@ -828,9 +870,22 @@ void __afl_manual_init(void) { static u8 init_done; + if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) { + + init_done = 1; + is_persistent = 0; + __afl_sharedmem_fuzzing = 0; + if (__afl_area_ptr == NULL) __afl_area_ptr = __afl_area_initial; + + if (getenv("AFL_DEBUG")) + fprintf(stderr, + "DEBUG: disabled instrumentation because of " + "AFL_DISABLE_LLVM_INSTRUMENTATION\n"); + + } + if (!init_done) { - __afl_map_shm(); __afl_start_forkserver(); init_done = 1; @@ -838,11 +893,11 @@ void __afl_manual_init(void) { } -/* Proper initialization routine. */ +/* Initialization of the forkserver - latest possible */ -__attribute__((constructor(CONST_PRIO))) void __afl_auto_init(void) { +__attribute__((constructor())) void __afl_auto_init(void) { - is_persistent = !!getenv(PERSIST_ENV_VAR); + if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return; if (getenv(DEFER_ENV_VAR)) return; @@ -850,6 +905,57 @@ __attribute__((constructor(CONST_PRIO))) void __afl_auto_init(void) { } +/* Initialization of the shmem - earliest possible because of LTO fixed mem. */ + +__attribute__((constructor(CTOR_PRIO))) void __afl_auto_early(void) { + + is_persistent = !!getenv(PERSIST_ENV_VAR); + + if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return; + + __afl_map_shm(); + +} + +/* preset __afl_area_ptr #2 */ + +__attribute__((constructor(1))) void __afl_auto_second(void) { + + if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return; + u8 *ptr; + + if (__afl_final_loc) { + + if (__afl_area_ptr && __afl_area_ptr != __afl_area_initial) + free(__afl_area_ptr); + + if (__afl_map_addr) + ptr = (u8 *)mmap((void *)__afl_map_addr, __afl_final_loc, + PROT_READ | PROT_WRITE, + MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0); + else + ptr = (u8 *)malloc(__afl_final_loc); + + if (ptr && (ssize_t)ptr != -1) __afl_area_ptr = ptr; + + } + +} + +/* preset __afl_area_ptr #1 - at constructor level 0 global variables have + not been set */ + +__attribute__((constructor(0))) void __afl_auto_first(void) { + + if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return; + u8 *ptr; + + ptr = (u8 *)malloc(1024000); + + if (ptr && (ssize_t)ptr != -1) __afl_area_ptr = ptr; + +} + /* The following stuff deals with supporting -fsanitize-coverage=trace-pc-guard. It remains non-operational in the traditional, plugin-backed LLVM mode. For more info about 'trace-pc-guard', see llvm_mode/README.md. @@ -860,7 +966,7 @@ __attribute__((constructor(CONST_PRIO))) void __afl_auto_init(void) { void __sanitizer_cov_trace_pc_guard(uint32_t *guard) { // For stability analysis, if you want to know to which function unstable - // edge IDs belong to - uncomment, recompile+install llvm_mode, recompile + // edge IDs belong - uncomment, recompile+install llvm_mode, recompile // the target. libunwind and libbacktrace are better solutions. // Set AFL_DEBUG_CHILD_OUTPUT=1 and run afl-fuzz with 2>file to capture // the backtrace output @@ -892,8 +998,17 @@ void __sanitizer_cov_trace_pc_guard(uint32_t *guard) { */ +#if (LLVM_VERSION_MAJOR < 9) + __afl_area_ptr[*guard]++; +#else + + __afl_area_ptr[*guard] = + __afl_area_ptr[*guard] + 1 + (__afl_area_ptr[*guard] == 255 ? 1 : 0); + +#endif + } /* Init callback. Populates instrumentation IDs. Note that we're using @@ -905,6 +1020,15 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { u32 inst_ratio = 100; char *x; + _is_sancov = 1; + + if (getenv("AFL_DEBUG")) { + + fprintf(stderr, "Running __sanitizer_cov_trace_pc_guard_init: %p-%p\n", + start, stop); + + } + if (start == stop || *start) return; x = getenv("AFL_INST_RATIO"); @@ -940,7 +1064,7 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { void __cmplog_ins_hook1(uint8_t arg1, uint8_t arg2) { - if (!__afl_cmp_map) return; + if (unlikely(!__afl_cmp_map)) return; uintptr_t k = (uintptr_t)__builtin_return_address(0); k = (k >> 4) ^ (k << 8); @@ -963,7 +1087,7 @@ void __cmplog_ins_hook1(uint8_t arg1, uint8_t arg2) { void __cmplog_ins_hook2(uint16_t arg1, uint16_t arg2) { - if (!__afl_cmp_map) return; + if (unlikely(!__afl_cmp_map)) return; uintptr_t k = (uintptr_t)__builtin_return_address(0); k = (k >> 4) ^ (k << 8); @@ -984,7 +1108,7 @@ void __cmplog_ins_hook2(uint16_t arg1, uint16_t arg2) { void __cmplog_ins_hook4(uint32_t arg1, uint32_t arg2) { - if (!__afl_cmp_map) return; + if (unlikely(!__afl_cmp_map)) return; uintptr_t k = (uintptr_t)__builtin_return_address(0); k = (k >> 4) ^ (k << 8); @@ -1005,7 +1129,7 @@ void __cmplog_ins_hook4(uint32_t arg1, uint32_t arg2) { void __cmplog_ins_hook8(uint64_t arg1, uint64_t arg2) { - if (!__afl_cmp_map) return; + if (unlikely(!__afl_cmp_map)) return; uintptr_t k = (uintptr_t)__builtin_return_address(0); k = (k >> 4) ^ (k << 8); @@ -1056,6 +1180,8 @@ void __sanitizer_cov_trace_cmp8(uint64_t arg1, uint64_t arg2) void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) { + if (unlikely(!__afl_cmp_map)) return; + for (uint64_t i = 0; i < cases[0]; i++) { uintptr_t k = (uintptr_t)__builtin_return_address(0) + i; @@ -1093,7 +1219,7 @@ static int area_is_mapped(void *ptr, size_t len) { void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) { - if (!__afl_cmp_map) return; + if (unlikely(!__afl_cmp_map)) return; if (!area_is_mapped(ptr1, 32) || !area_is_mapped(ptr2, 32)) return; |