about summary refs log tree commit diff
diff options
context:
space:
mode:
authorHeiko Eißfeldt <heikoi@hexco.de>2019-06-30 10:06:20 +0200
committerHeiko Eißfeldt <heikoi@hexco.de>2019-06-30 10:37:14 +0200
commitd9ff84e39ecad47deec8808ea127fd90d9f5e8ef (patch)
tree410806806488ae623f0544044336a2a6f5f4c632
parentc083fd895c67bcf2abd1574e50fe0859361066ea (diff)
downloadafl++-d9ff84e39ecad47deec8808ea127fd90d9f5e8ef.tar.gz
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.
-rw-r--r--Makefile23
-rw-r--r--afl-analyze.c40
-rw-r--r--afl-as.h46
-rw-r--r--afl-fuzz.c57
-rw-r--r--afl-showmap.c41
-rw-r--r--afl-tmin.c45
-rw-r--r--llvm_mode/Makefile2
-rw-r--r--llvm_mode/afl-llvm-rt.o.c27
-rw-r--r--sharedmem.c139
-rw-r--r--sharedmem.h6
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