From d9ff84e39ecad47deec8808ea127fd90d9f5e8ef Mon Sep 17 00:00:00 2001 From: Heiko Eißfeldt Date: Sun, 30 Jun 2019 10:06:20 +0200 Subject: Refactor to use an alternative method for shared memory. If USEMMAP is defined, the shared memory segment is created/attached etc. now by shm_open() and mmap(). This API is hopefully more often available (at least for iOS). In order to reduce code duplication I have added new files sharedmem.[ch] which now encapsulate the shared memory method. This is based on the work of Proteas to support iOS fuzzing (thanks). https://github.com/Proteas/afl-ios/commit/866af8ad1cb230d5d753b546380a4af1e55d6946 Currently this is in an experimental status yet. Please report whether this variant works on 32 and 64 bit and on the supported platforms. This branch enables USEMMAP and has been tested on Linux. There is no auto detection for the mmap API yet. --- afl-fuzz.c | 57 ++++++++++----------------------------------------------- 1 file changed, 10 insertions(+), 47 deletions(-) (limited to 'afl-fuzz.c') 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 #include @@ -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(); -- cgit 1.4.1 From f45332e1ab1f7b82c38c6fcc3c451fca35d5a9ce Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 13 Jul 2019 08:09:19 +0200 Subject: portability fix: getcwd(NULL, 0) is a non-POSIX glibc extension. Refactor detect_file_args() in a separate file in order to avoid multiple copies. --- Makefile | 11 +++++---- afl-analyze.c | 45 ++--------------------------------- afl-common.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++ afl-common.h | 5 ++++ afl-fuzz.c | 76 ++++++++++++++++++----------------------------------------- afl-showmap.c | 47 ++---------------------------------- afl-tmin.c | 45 ++--------------------------------- 7 files changed, 110 insertions(+), 188 deletions(-) create mode 100644 afl-common.c create mode 100644 afl-common.h (limited to 'afl-fuzz.c') diff --git a/Makefile b/Makefile index cb3beb11..7c151f8b 100644 --- a/Makefile +++ b/Makefile @@ -131,20 +131,23 @@ afl-as: afl-as.c afl-as.h $(COMM_HDR) | test_x86 $(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) ln -sf afl-as as +afl-common.o : afl-common.c + $(CC) $(CFLAGS) -c afl-common.c + sharedmem.o : sharedmem.c $(CC) $(CFLAGS) -c sharedmem.c afl-fuzz: afl-fuzz.c sharedmem.o $(COMM_HDR) | test_x86 - $(CC) $(CFLAGS) $@.c sharedmem.o -o $@ $(LDFLAGS) $(PYFLAGS) + $(CC) $(CFLAGS) $@.c afl-common.o sharedmem.o -o $@ $(LDFLAGS) $(PYFLAGS) afl-showmap: afl-showmap.c sharedmem.o $(COMM_HDR) | test_x86 - $(CC) $(CFLAGS) $@.c sharedmem.o -o $@ $(LDFLAGS) + $(CC) $(CFLAGS) $@.c afl-common.o sharedmem.o -o $@ $(LDFLAGS) afl-tmin: afl-tmin.c sharedmem.o $(COMM_HDR) | test_x86 - $(CC) $(CFLAGS) $@.c sharedmem.o -o $@ $(LDFLAGS) + $(CC) $(CFLAGS) $@.c afl-common.o sharedmem.o -o $@ $(LDFLAGS) afl-analyze: afl-analyze.c sharedmem.o $(COMM_HDR) | test_x86 - $(CC) $(CFLAGS) $@.c sharedmem.o -o $@ $(LDFLAGS) + $(CC) $(CFLAGS) $@.c afl-common.o 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 834a0357..be470317 100644 --- a/afl-analyze.c +++ b/afl-analyze.c @@ -27,6 +27,7 @@ #include "alloc-inl.h" #include "hash.h" #include "sharedmem.h" +#include "afl-common.h" #include #include @@ -725,48 +726,6 @@ static void setup_signal_handlers(void) { } -/* Detect @@ in args. */ - -static void detect_file_args(char** argv) { - - u32 i = 0; - u8* cwd = getcwd(NULL, 0); - - if (!cwd) PFATAL("getcwd() failed"); - - while (argv[i]) { - - u8* aa_loc = strstr(argv[i], "@@"); - - if (aa_loc) { - - u8 *aa_subst, *n_arg; - - /* Be sure that we're always using fully-qualified paths. */ - - if (prog_in[0] == '/') aa_subst = prog_in; - else aa_subst = alloc_printf("%s/%s", cwd, prog_in); - - /* Construct a replacement argv value. */ - - *aa_loc = 0; - n_arg = alloc_printf("%s%s%s", argv[i], aa_subst, aa_loc + 2); - argv[i] = n_arg; - *aa_loc = '@'; - - if (prog_in[0] != '/') ck_free(aa_subst); - - } - - i++; - - } - - free(cwd); /* not tracked */ - -} - - /* Display usage hints. */ static void usage(u8* argv0) { @@ -1018,7 +977,7 @@ int main(int argc, char** argv) { set_up_environment(); find_binary(argv[optind]); - detect_file_args(argv + optind); + detect_file_args(argv + optind, prog_in); if (qemu_mode) use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind); diff --git a/afl-common.c b/afl-common.c new file mode 100644 index 00000000..ea3bfa6c --- /dev/null +++ b/afl-common.c @@ -0,0 +1,69 @@ +/* + gather some functions common to multiple executables + + detect_file_args + */ + +#include +#include +#include + +#include "debug.h" +#include "alloc-inl.h" + +/* Detect @@ in args. */ +#ifndef __glibc__ +#include +#endif +void detect_file_args(char** argv, u8* prog_in) { + + u32 i = 0; +#ifdef __glibc__ + u8* cwd = getcwd(NULL, 0); /* non portable glibc extension */ +#else + u8* cwd; + char *buf; + long size = pathconf(".", _PC_PATH_MAX); + if ((buf = (char *)malloc((size_t)size)) != NULL) { + cwd = getcwd(buf, (size_t)size); /* portable version */ + } else { + PFATAL("getcwd() failed"); + } +#endif + + if (!cwd) PFATAL("getcwd() failed"); + + while (argv[i]) { + + u8* aa_loc = strstr(argv[i], "@@"); + + if (aa_loc) { + + u8 *aa_subst, *n_arg; + + if (!prog_in) FATAL("@@ syntax is not supported by this tool."); + + /* Be sure that we're always using fully-qualified paths. */ + + if (prog_in[0] == '/') aa_subst = prog_in; + else aa_subst = alloc_printf("%s/%s", cwd, prog_in); + + /* Construct a replacement argv value. */ + + *aa_loc = 0; + n_arg = alloc_printf("%s%s%s", argv[i], aa_subst, aa_loc + 2); + argv[i] = n_arg; + *aa_loc = '@'; + + if (prog_in[0] != '/') ck_free(aa_subst); + + } + + i++; + + } + + free(cwd); /* not tracked */ + +} + diff --git a/afl-common.h b/afl-common.h new file mode 100644 index 00000000..07afb75d --- /dev/null +++ b/afl-common.h @@ -0,0 +1,5 @@ +#ifndef __AFLCOMMON_H +#define __AFLCOMMON_H + +void detect_file_args(char **argv, u8 *prog_in); +#endif diff --git a/afl-fuzz.c b/afl-fuzz.c index af507c88..2e4b28e0 100644 --- a/afl-fuzz.c +++ b/afl-fuzz.c @@ -32,6 +32,7 @@ #include "alloc-inl.h" #include "hash.h" #include "sharedmem.h" +#include "afl-common.h" #include #include @@ -8068,58 +8069,6 @@ static void check_asan_opts(void) { } -/* Detect @@ in args. */ - -EXP_ST void detect_file_args(char** argv) { - - u32 i = 0; - u8* cwd = getcwd(NULL, 0); - - if (!cwd) PFATAL("getcwd() failed"); - - while (argv[i]) { - - u8* aa_loc = strstr(argv[i], "@@"); - - if (aa_loc) { - - u8 *aa_subst, *n_arg; - - /* If we don't have a file name chosen yet, use a safe default. */ - - if (!out_file) { - if (file_extension) { - out_file = alloc_printf("%s/.cur_input.%s", out_dir, file_extension); - } else { - out_file = alloc_printf("%s/.cur_input", out_dir); - } - } - - /* Be sure that we're always using fully-qualified paths. */ - - if (out_file[0] == '/') aa_subst = out_file; - else aa_subst = alloc_printf("%s/%s", cwd, out_file); - - /* Construct a replacement argv value. */ - - *aa_loc = 0; - n_arg = alloc_printf("%s%s%s", argv[i], aa_subst, aa_loc + 2); - argv[i] = n_arg; - *aa_loc = '@'; - - if (out_file[0] != '/') ck_free(aa_subst); - - } - - i++; - - } - - free(cwd); /* not tracked */ - -} - - /* Set up signal handlers. More complicated that needs to be, because libc on Solaris doesn't resume interrupted reads(), sets SA_RESETHAND when you call siginterrupt(), and does other stupid things. */ @@ -8628,7 +8577,28 @@ int main(int argc, char** argv) { if (!timeout_given) find_timeout(); - detect_file_args(argv + optind + 1); + /* If we don't have a file name chosen yet, use a safe default. */ + + if (!out_file) { + u32 i = optind + 1; + while (argv[i]) { + + u8* aa_loc = strstr(argv[i], "@@"); + + if (aa_loc && !out_file) { + if (file_extension) { + out_file = alloc_printf("%s/.cur_input.%s", out_dir, file_extension); + } else { + out_file = alloc_printf("%s/.cur_input", out_dir); + } + detect_file_args(argv + optind + 1, out_file); + break; + } + + i++; + + } + } if (!out_file) setup_stdio_file(); diff --git a/afl-showmap.c b/afl-showmap.c index a5d7568a..1382e5f0 100644 --- a/afl-showmap.c +++ b/afl-showmap.c @@ -29,6 +29,7 @@ #include "alloc-inl.h" #include "hash.h" #include "sharedmem.h" +#include "afl-common.h" #include #include @@ -380,50 +381,6 @@ static void setup_signal_handlers(void) { } -/* Detect @@ in args. */ - -static void detect_file_args(char** argv) { - - u32 i = 0; - u8* cwd = getcwd(NULL, 0); - - if (!cwd) PFATAL("getcwd() failed"); - - while (argv[i]) { - - u8* aa_loc = strstr(argv[i], "@@"); - - if (aa_loc) { - - u8 *aa_subst, *n_arg; - - if (!at_file) FATAL("@@ syntax is not supported by this tool."); - - /* Be sure that we're always using fully-qualified paths. */ - - if (at_file[0] == '/') aa_subst = at_file; - else aa_subst = alloc_printf("%s/%s", cwd, at_file); - - /* Construct a replacement argv value. */ - - *aa_loc = 0; - n_arg = alloc_printf("%s%s%s", argv[i], aa_subst, aa_loc + 2); - argv[i] = n_arg; - *aa_loc = '@'; - - if (at_file[0] != '/') ck_free(aa_subst); - - } - - i++; - - } - - free(cwd); /* not tracked */ - -} - - /* Show banner. */ static void show_banner(void) { @@ -720,7 +677,7 @@ int main(int argc, char** argv) { ACTF("Executing '%s'...\n", target_path); } - detect_file_args(argv + optind); + detect_file_args(argv + optind, at_file); if (qemu_mode) use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind); diff --git a/afl-tmin.c b/afl-tmin.c index b9dbb2b5..d6fd27fc 100644 --- a/afl-tmin.c +++ b/afl-tmin.c @@ -27,6 +27,7 @@ #include "alloc-inl.h" #include "hash.h" #include "sharedmem.h" +#include "afl-common.h" #include #include @@ -881,48 +882,6 @@ static void setup_signal_handlers(void) { } -/* Detect @@ in args. */ - -static void detect_file_args(char** argv) { - - u32 i = 0; - u8* cwd = getcwd(NULL, 0); - - if (!cwd) PFATAL("getcwd() failed"); - - while (argv[i]) { - - u8* aa_loc = strstr(argv[i], "@@"); - - if (aa_loc) { - - u8 *aa_subst, *n_arg; - - /* Be sure that we're always using fully-qualified paths. */ - - if (prog_in[0] == '/') aa_subst = prog_in; - else aa_subst = alloc_printf("%s/%s", cwd, prog_in); - - /* Construct a replacement argv value. */ - - *aa_loc = 0; - n_arg = alloc_printf("%s%s%s", argv[i], aa_subst, aa_loc + 2); - argv[i] = n_arg; - *aa_loc = '@'; - - if (prog_in[0] != '/') ck_free(aa_subst); - - } - - i++; - - } - - free(cwd); /* not tracked */ - -} - - /* Display usage hints. */ static void usage(u8* argv0) { @@ -1222,7 +1181,7 @@ int main(int argc, char** argv) { set_up_environment(); find_binary(argv[optind]); - detect_file_args(argv + optind); + detect_file_args(argv + optind, prog_in); if (qemu_mode) use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind); -- cgit 1.4.1