diff options
-rw-r--r-- | Makefile | 23 | ||||
-rw-r--r-- | afl-analyze.c | 40 | ||||
-rw-r--r-- | afl-as.h | 46 | ||||
-rw-r--r-- | afl-fuzz.c | 57 | ||||
-rw-r--r-- | afl-showmap.c | 41 | ||||
-rw-r--r-- | afl-tmin.c | 45 | ||||
-rw-r--r-- | llvm_mode/Makefile | 2 | ||||
-rw-r--r-- | llvm_mode/afl-llvm-rt.o.c | 27 | ||||
-rw-r--r-- | sharedmem.c | 139 | ||||
-rw-r--r-- | sharedmem.h | 6 |
10 files changed, 262 insertions, 164 deletions
diff --git a/Makefile b/Makefile index 1d8d819f..4f85b53a 100644 --- a/Makefile +++ b/Makefile @@ -30,12 +30,12 @@ SH_PROGS = afl-plot afl-cmin afl-whatsup afl-system-config CFLAGS ?= -O3 -funroll-loops CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign \ -DAFL_PATH=\"$(HELPER_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\" \ - -DBIN_PATH=\"$(BIN_PATH)\" + -DBIN_PATH=\"$(BIN_PATH)\" -DUSEMMAP=1 PYTHON_INCLUDE ?= /usr/include/python2.7 ifneq "$(filter Linux GNU%,$(shell uname))" "" - LDFLAGS += -ldl + LDFLAGS += -ldl -lrt endif ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" "" @@ -92,17 +92,20 @@ afl-as: afl-as.c afl-as.h $(COMM_HDR) | test_x86 $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) ln -sf afl-as as -afl-fuzz: afl-fuzz.c $(COMM_HDR) | test_x86 - $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) $(PYFLAGS) +sharedmem.o : sharedmem.c + $(CC) $(CFLAGS) -c sharedmem.c -afl-showmap: afl-showmap.c $(COMM_HDR) | test_x86 - $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) +afl-fuzz: afl-fuzz.c sharedmem.o $(COMM_HDR) | test_x86 + $(CC) $(CFLAGS) $@.c sharedmem.o -o $@ $(LDFLAGS) $(PYFLAGS) -afl-tmin: afl-tmin.c $(COMM_HDR) | test_x86 - $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) +afl-showmap: afl-showmap.c sharedmem.o $(COMM_HDR) | test_x86 + $(CC) $(CFLAGS) $@.c sharedmem.o -o $@ $(LDFLAGS) -afl-analyze: afl-analyze.c $(COMM_HDR) | test_x86 - $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) +afl-tmin: afl-tmin.c sharedmem.o $(COMM_HDR) | test_x86 + $(CC) $(CFLAGS) $@.c sharedmem.o -o $@ $(LDFLAGS) + +afl-analyze: afl-analyze.c sharedmem.o $(COMM_HDR) | test_x86 + $(CC) $(CFLAGS) $@.c sharedmem.o -o $@ $(LDFLAGS) afl-gotcpu: afl-gotcpu.c $(COMM_HDR) | test_x86 $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) diff --git a/afl-analyze.c b/afl-analyze.c index 44be73f9..834a0357 100644 --- a/afl-analyze.c +++ b/afl-analyze.c @@ -26,6 +26,7 @@ #include "debug.h" #include "alloc-inl.h" #include "hash.h" +#include "sharedmem.h" #include <stdio.h> #include <unistd.h> @@ -47,7 +48,7 @@ static s32 child_pid; /* PID of the tested program */ -static u8* trace_bits; /* SHM with instrumentation bitmap */ + u8* trace_bits; /* SHM with instrumentation bitmap */ static u8 *in_file, /* Analyzer input test case */ *prog_in, /* Targeted program input file */ @@ -64,8 +65,7 @@ static u32 in_len, /* Input data length */ static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */ -static s32 shm_id, /* ID of the SHM region */ - dev_null_fd = -1; /* FD to /dev/null */ +static s32 dev_null_fd = -1; /* FD to /dev/null */ static u8 edges_only, /* Ignore hit counts? */ use_hex_offsets, /* Show hex offsets? */ @@ -76,6 +76,7 @@ static volatile u8 child_timed_out; /* Child timed out? */ + /* Constants used for describing byte behavior. */ #define RESP_NONE 0x00 /* Changing byte is a no-op. */ @@ -141,37 +142,11 @@ static inline u8 anything_set(void) { } -/* Get rid of shared memory and temp files (atexit handler). */ +/* Get rid of temp files (atexit handler). */ -static void remove_shm(void) { +static void at_exit_handler(void) { unlink(prog_in); /* Ignore errors */ - shmctl(shm_id, IPC_RMID, NULL); - -} - - -/* Configure shared memory. */ - -static void setup_shm(void) { - - u8* shm_str; - - shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600); - - if (shm_id < 0) PFATAL("shmget() failed"); - - atexit(remove_shm); - - shm_str = alloc_printf("%d", shm_id); - - setenv(SHM_ENV_VAR, shm_str, 1); - - ck_free(shm_str); - - trace_bits = shmat(shm_id, NULL, 0); - - if (!trace_bits) PFATAL("shmat() failed"); } @@ -1036,7 +1011,8 @@ int main(int argc, char** argv) { use_hex_offsets = !!getenv("AFL_ANALYZE_HEX"); - setup_shm(); + setup_shm(0); + atexit(at_exit_handler); setup_signal_handlers(); set_up_environment(); diff --git a/afl-as.h b/afl-as.h index ebd57109..90944614 100644 --- a/afl-as.h +++ b/afl-as.h @@ -220,6 +220,29 @@ static const u8* main_payload_32 = " testl %eax, %eax\n" " je __afl_setup_abort\n" "\n" +#ifdef USEMMAP + " pushl $384 /* shm_open mode 0600 */\n" + " pushl $2 /* flags O_RDWR */\n" + " pushl %eax /* SHM file path */\n" + " call shm_open\n" + " addl $12, %esp\n" + "\n" + " cmpl $-1, %eax\n" + " je __afl_setup_abort\n" + "\n" + " pushl $0 /* mmap off */\n" + " pushl %eax /* shm fd */\n" + " pushl $1 /* mmap flags */\n" + " pushl $3 /* mmap prot */\n" + " pushl $"STRINGIFY(MAP_SIZE)" /* mmap len */\n" + " pushl $0 /* mmap addr */\n" + " call mmap\n" + " addl $12, %esp\n" + "\n" + " cmpl $-1, %eax\n" + " je __afl_setup_abort\n" + "\n" +#else " pushl %eax\n" " call atoi\n" " addl $4, %esp\n" @@ -233,6 +256,7 @@ static const u8* main_payload_32 = " cmpl $-1, %eax\n" " je __afl_setup_abort\n" "\n" +#endif " /* Store the address of the SHM region. */\n" "\n" " movl %eax, __afl_area_ptr\n" @@ -501,6 +525,27 @@ static const u8* main_payload_64 = " testq %rax, %rax\n" " je __afl_setup_abort\n" "\n" +#ifdef USEMMAP + " movl $384, %edx /* shm_open mode 0600 */\n" + " movl $2, %esi /* flags O_RDWR */\n" + " movq %rax, %rdi /* SHM file path */\n" + CALL_L64("shm_open") + "\n" + " cmpq $-1, %rax\n" + " je __afl_setup_abort\n" + "\n" + " movl $0, %r9d\n" + " movl %eax, %r8d\n" + " movl $1, %ecx\n" + " movl $3, %edx\n" + " movl $"STRINGIFY(MAP_SIZE)", %esi\n" + " movl $0, %edi\n" + CALL_L64("mmap") + "\n" + " cmpq $-1, %rax\n" + " je __afl_setup_abort\n" + "\n" +#else " movq %rax, %rdi\n" CALL_L64("atoi") "\n" @@ -512,6 +557,7 @@ static const u8* main_payload_64 = " cmpq $-1, %rax\n" " je __afl_setup_abort\n" "\n" +#endif " /* Store the address of the SHM region. */\n" "\n" " movq %rax, %rdx\n" diff --git a/afl-fuzz.c b/afl-fuzz.c index 6db99acf..af507c88 100644 --- a/afl-fuzz.c +++ b/afl-fuzz.c @@ -31,6 +31,7 @@ #include "debug.h" #include "alloc-inl.h" #include "hash.h" +#include "sharedmem.h" #include <stdio.h> #include <unistd.h> @@ -163,7 +164,7 @@ static s32 forksrv_pid, /* PID of the fork server */ child_pid = -1, /* PID of the fuzzed program */ out_dir_fd = -1; /* FD of the lock file */ -EXP_ST u8* trace_bits; /* SHM with instrumentation bitmap */ + u8* trace_bits; /* SHM with instrumentation bitmap */ EXP_ST u8 virgin_bits[MAP_SIZE], /* Regions yet untouched by fuzzing */ virgin_tmout[MAP_SIZE], /* Bits we haven't seen in tmouts */ @@ -171,8 +172,6 @@ EXP_ST u8 virgin_bits[MAP_SIZE], /* Regions yet untouched by fuzzing */ static u8 var_bytes[MAP_SIZE]; /* Bytes that appear to be variable */ -static s32 shm_id; /* ID of the SHM region */ - static volatile u8 stop_soon, /* Ctrl-C pressed? */ clear_screen = 1, /* Window resized? */ child_timed_out; /* Traced process timed out? */ @@ -1444,15 +1443,6 @@ static inline void classify_counts(u32* mem) { #endif /* ^__x86_64__ */ -/* Get rid of shared memory (atexit handler). */ - -static void remove_shm(void) { - - shmctl(shm_id, IPC_RMID, NULL); - -} - - /* Compact trace bytes into a smaller bitmap. We effectively just drop the count information here. This is called only sporadically, for some new paths. */ @@ -1606,40 +1596,6 @@ static void cull_queue(void) { } -/* Configure shared memory and virgin_bits. This is called at startup. */ - -EXP_ST void setup_shm(void) { - - u8* shm_str; - - if (!in_bitmap) memset(virgin_bits, 255, MAP_SIZE); - - memset(virgin_tmout, 255, MAP_SIZE); - memset(virgin_crash, 255, MAP_SIZE); - - shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600); - - if (shm_id < 0) PFATAL("shmget() failed"); - - atexit(remove_shm); - - shm_str = alloc_printf("%d", shm_id); - - /* If somebody is asking us to fuzz instrumented binaries in dumb mode, - we don't want them to detect instrumentation, since we won't be sending - fork server commands. This should be replaced with better auto-detection - later on, perhaps? */ - - if (!dumb_mode) setenv(SHM_ENV_VAR, shm_str, 1); - - ck_free(shm_str); - - trace_bits = shmat(shm_id, NULL, 0); - - if (!trace_bits) PFATAL("shmat() failed"); - -} - /* Load postprocessor, if available. */ @@ -7466,8 +7422,10 @@ EXP_ST void check_binary(u8* fname) { #else +#if !defined(__arm__) && !defined(__arm64__) if (f_data[0] != 0xCF || f_data[1] != 0xFA || f_data[2] != 0xED) FATAL("Program '%s' is not a 64-bit Mach-O binary", target_path); +#endif #endif /* ^!__APPLE__ */ @@ -8639,7 +8597,12 @@ int main(int argc, char** argv) { check_cpu_governor(); setup_post(); - setup_shm(); + setup_shm(dumb_mode); + + if (!in_bitmap) memset(virgin_bits, 255, MAP_SIZE); + memset(virgin_tmout, 255, MAP_SIZE); + memset(virgin_crash, 255, MAP_SIZE); + init_count_class16(); setup_dirs_fds(); diff --git a/afl-showmap.c b/afl-showmap.c index 316490d8..a5d7568a 100644 --- a/afl-showmap.c +++ b/afl-showmap.c @@ -28,6 +28,7 @@ #include "debug.h" #include "alloc-inl.h" #include "hash.h" +#include "sharedmem.h" #include <stdio.h> #include <unistd.h> @@ -48,7 +49,7 @@ static s32 child_pid; /* PID of the tested program */ -static u8* trace_bits; /* SHM with instrumentation bitmap */ + u8* trace_bits; /* SHM with instrumentation bitmap */ static u8 *out_file, /* Trace output file */ *doc_path, /* Path to docs */ @@ -59,8 +60,6 @@ static u32 exec_tmout; /* Exec timeout (ms) */ static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */ -static s32 shm_id; /* ID of the SHM region */ - static u8 quiet_mode, /* Hide non-essential messages? */ edges_only, /* Ignore hit counts? */ cmin_mode, /* Generate output in afl-cmin mode? */ @@ -72,6 +71,7 @@ static volatile u8 child_timed_out, /* Child timed out? */ child_crashed; /* Child crashed? */ + /* Classify tuple counts. Instead of mapping to individual bits, as in afl-fuzz.c, we map to more user-friendly numbers between 1 and 8. */ @@ -126,39 +126,6 @@ static void classify_counts(u8* mem, const u8* map) { } -/* Get rid of shared memory (atexit handler). */ - -static void remove_shm(void) { - - shmctl(shm_id, IPC_RMID, NULL); - -} - - -/* Configure shared memory. */ - -static void setup_shm(void) { - - u8* shm_str; - - shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600); - - if (shm_id < 0) PFATAL("shmget() failed"); - - atexit(remove_shm); - - shm_str = alloc_printf("%d", shm_id); - - setenv(SHM_ENV_VAR, shm_str, 1); - - ck_free(shm_str); - - trace_bits = shmat(shm_id, NULL, 0); - - if (!trace_bits) PFATAL("shmat() failed"); - -} - /* Write results. */ static u32 write_results(void) { @@ -741,7 +708,7 @@ int main(int argc, char** argv) { if (optind == argc || !out_file) usage(argv[0]); - setup_shm(); + setup_shm(0); setup_signal_handlers(); set_up_environment(); diff --git a/afl-tmin.c b/afl-tmin.c index a42be6e9..b9dbb2b5 100644 --- a/afl-tmin.c +++ b/afl-tmin.c @@ -26,6 +26,7 @@ #include "debug.h" #include "alloc-inl.h" #include "hash.h" +#include "sharedmem.h" #include <stdio.h> #include <unistd.h> @@ -50,8 +51,8 @@ static s32 forksrv_pid, /* PID of the fork server */ static s32 fsrv_ctl_fd, /* Fork server control pipe (write) */ fsrv_st_fd; /* Fork server status pipe (read) */ -static u8 *trace_bits, /* SHM with instrumentation bitmap */ - *mask_bitmap; /* Mask for trace bits (-B) */ + u8 *trace_bits; /* SHM with instrumentation bitmap */ +static u8 *mask_bitmap; /* Mask for trace bits (-B) */ static u8 *in_file, /* Minimizer input test case */ *out_file, /* Minimizer output file */ @@ -73,8 +74,7 @@ static u32 in_len, /* Input data length */ static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */ -static s32 shm_id, /* ID of the SHM region */ - dev_null_fd = -1; /* FD to /dev/null */ +static s32 dev_null_fd = -1; /* FD to /dev/null */ static u8 crash_mode, /* Crash-centric mode? */ exit_crash, /* Treat non-zero exit as crash? */ @@ -159,42 +159,12 @@ static inline u8 anything_set(void) { } +/* Get rid of temp files (atexit handler). */ -/* Get rid of shared memory and temp files (atexit handler). */ - -static void remove_shm(void) { - +static void at_exit_handler(void) { if (prog_in) unlink(prog_in); /* Ignore errors */ - shmctl(shm_id, IPC_RMID, NULL); - -} - - -/* Configure shared memory. */ - -static void setup_shm(void) { - - u8* shm_str; - - shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600); - - if (shm_id < 0) PFATAL("shmget() failed"); - - atexit(remove_shm); - - shm_str = alloc_printf("%d", shm_id); - - setenv(SHM_ENV_VAR, shm_str, 1); - - ck_free(shm_str); - - trace_bits = shmat(shm_id, NULL, 0); - - if (!trace_bits) PFATAL("shmat() failed"); - } - /* Read initial file. */ static void read_initial_file(void) { @@ -1245,7 +1215,8 @@ int main(int argc, char** argv) { if (optind == argc || !in_file || !out_file) usage(argv[0]); - setup_shm(); + setup_shm(0); + atexit(at_exit_handler); setup_signal_handlers(); set_up_environment(); diff --git a/llvm_mode/Makefile b/llvm_mode/Makefile index 6b277536..0cb2e1c5 100644 --- a/llvm_mode/Makefile +++ b/llvm_mode/Makefile @@ -33,7 +33,7 @@ endif CFLAGS ?= -O3 -funroll-loops CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign \ -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \ - -DVERSION=\"$(VERSION)\" + -DVERSION=\"$(VERSION)\" -DUSEMMAP=1 -lrt ifdef AFL_TRACE_PC CFLAGS += -DUSE_TRACE_PC=1 endif diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c index 342dcc90..debde204 100644 --- a/llvm_mode/afl-llvm-rt.o.c +++ b/llvm_mode/afl-llvm-rt.o.c @@ -44,6 +44,9 @@ # define CONST_PRIO 0 #endif /* ^USE_TRACE_PC */ +#include <sys/mman.h> +#include <fcntl.h> + /* Globals needed by the injected instrumentation. The __afl_area_initial region is used for instrumentation output before __afl_map_shm() has a chance to run. @@ -71,10 +74,34 @@ static void __afl_map_shm(void) { hacky .init code to work correctly in projects such as OpenSSL. */ 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) { + printf("shm_open() failed\n"); + exit(1); + } + + /* map the shared memory segment to the address space of the process */ + shm_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); + if (shm_base == MAP_FAILED) { + close(shm_fd); + shm_fd = -1; + printf("mmap() failed\n"); + exit(2); + } + + __afl_area_ptr = shm_base; +#else u32 shm_id = atoi(id_str); __afl_area_ptr = shmat(shm_id, NULL, 0); +#endif /* Whooooops. */ diff --git a/sharedmem.c b/sharedmem.c new file mode 100644 index 00000000..23cc8984 --- /dev/null +++ b/sharedmem.c @@ -0,0 +1,139 @@ +/* + + */ + +#define AFL_MAIN + +#include "config.h" +#include "types.h" +#include "debug.h" +#include "alloc-inl.h" +#include "hash.h" +#include "sharedmem.h" + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <errno.h> +#include <signal.h> +#include <dirent.h> +#include <fcntl.h> + +#include <sys/wait.h> +#include <sys/time.h> +#include <sys/shm.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/resource.h> + +#include <sys/mman.h> +#include <fcntl.h> + +extern unsigned char*trace_bits; + +#ifdef USEMMAP +/* ================ Proteas ================ */ +int g_shm_fd = -1; +unsigned char *g_shm_base = NULL; +char g_shm_file_path[L_tmpnam]; +/* ========================================= */ +#else +static s32 shm_id; /* ID of the SHM region */ +#endif + +/* Get rid of shared memory (atexit handler). */ + +void remove_shm(void) { +#ifdef USEMMAP + if (g_shm_base != NULL) { + munmap(g_shm_base, MAP_SIZE); + g_shm_base = NULL; + } + + if (g_shm_fd != -1) { + close(g_shm_fd); + g_shm_fd = -1; + } +#else + shmctl(shm_id, IPC_RMID, NULL); +#endif +} + + +/* Configure shared memory. */ + +void setup_shm(unsigned char dumb_mode) { +#ifdef USEMMAP + /* generate random file name for multi instance */ + memset(g_shm_file_path, 0x0, L_tmpnam); + + char *result = tmpnam(g_shm_file_path); + if (result == 0) + PFATAL("cannot generate filename for shared memory"); + + /* get rid of second slash in /tmp/blabla */ + g_shm_file_path[4] = '_'; + + /* create the shared memory segment as if it was a file */ + g_shm_fd = shm_open(g_shm_file_path, O_CREAT | O_RDWR | O_EXCL, 0600); + if (g_shm_fd == -1) { + PFATAL("shm_open() failed"); + } + + /* configure the size of the shared memory segment */ + if (ftruncate(g_shm_fd, MAP_SIZE)) { + PFATAL("setup_shm(): ftruncate() failed"); + } + + /* map the shared memory segment to the address space of the process */ + g_shm_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, g_shm_fd, 0); + if (g_shm_base == MAP_FAILED) { + close(g_shm_fd); + g_shm_fd = -1; + PFATAL("mmap() failed"); + } + + atexit(remove_shm); + + /* If somebody is asking us to fuzz instrumented binaries in dumb mode, + we don't want them to detect instrumentation, since we won't be sending + fork server commands. This should be replaced with better auto-detection + later on, perhaps? */ + + if (!dumb_mode) setenv(SHM_ENV_VAR, g_shm_file_path, 1); + + trace_bits = g_shm_base; + + if (!trace_bits) PFATAL("mmap() failed"); + +#else + u8* shm_str; + + shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600); + + if (shm_id < 0) PFATAL("shmget() failed"); + + atexit(remove_shm); + + shm_str = alloc_printf("%d", shm_id); + + setenv(SHM_ENV_VAR, shm_str, 1); + + /* If somebody is asking us to fuzz instrumented binaries in dumb mode, + we don't want them to detect instrumentation, since we won't be sending + fork server commands. This should be replaced with better auto-detection + later on, perhaps? */ + + if (!dumb_mode) setenv(SHM_ENV_VAR, shm_str, 1); + + ck_free(shm_str); + + trace_bits = shmat(shm_id, NULL, 0); + + if (!trace_bits) PFATAL("shmat() failed"); + +#endif +} + diff --git a/sharedmem.h b/sharedmem.h new file mode 100644 index 00000000..9300ccf1 --- /dev/null +++ b/sharedmem.h @@ -0,0 +1,6 @@ +#ifndef SHAREDMEM +#define SHAREDMEM + +void setup_shm(unsigned char dumb_mode); +void remove_shm(void); +#endif |