Merge pull request #51398 from risicle/ris-afl-qemu-fix

afl-qemu: update to qemu 2.10.0, as specified by afl 2.52b
This commit is contained in:
Jörg Thalheim 2019-01-06 01:50:55 +01:00 committed by GitHub
commit 9d8ccfe00f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 137 additions and 1049 deletions

View File

@ -3,79 +3,73 @@
}:
let
afl-qemu = callPackage ./qemu.nix {};
afl-qemu = callPackage ./qemu.nix { inherit afl; };
qemu-exe-name = if stdenv.hostPlatform.system == "x86_64-linux" then "qemu-x86_64"
else if stdenv.hostPlatform.system == "i686-linux" then "qemu-i386"
else throw "afl: no support for ${stdenv.hostPlatform.system}!";
in
afl = stdenv.mkDerivation rec {
name = "afl-${version}";
version = "2.52b";
stdenv.mkDerivation rec {
name = "afl-${version}";
version = "2.52b";
src = fetchurl {
url = "http://lcamtuf.coredump.cx/afl/releases/${name}.tgz";
sha256 = "0ig0ij4n1pwry5dw1hk4q88801jzzy2cric6y2gd6560j55lnqa3";
};
enableParallelBuilding = true;
src = fetchurl {
url = "http://lcamtuf.coredump.cx/afl/releases/${name}.tgz";
sha256 = "0ig0ij4n1pwry5dw1hk4q88801jzzy2cric6y2gd6560j55lnqa3";
};
# Note: libcgroup isn't needed for building, just for the afl-cgroup
# script.
nativeBuildInputs = [ makeWrapper which ];
buildInputs = [ llvm ];
# Note: libcgroup isn't needed for building, just for the afl-cgroup
# script.
buildInputs = [ makeWrapper llvm which ];
buildPhase = ''
make PREFIX=$out
cd llvm_mode
make PREFIX=$out
cd ..
'';
installPhase = ''
# Do the normal installation
make install PREFIX=$out
# Install the custom QEMU emulator for binary blob fuzzing.
cp ${afl-qemu}/bin/${qemu-exe-name} $out/bin/afl-qemu-trace
# Install the cgroups wrapper for asan-based fuzzing.
cp experimental/asan_cgroups/limit_memory.sh $out/bin/afl-cgroup
chmod +x $out/bin/afl-cgroup
substituteInPlace $out/bin/afl-cgroup \
--replace "cgcreate" "${libcgroup}/bin/cgcreate" \
--replace "cgexec" "${libcgroup}/bin/cgexec" \
--replace "cgdelete" "${libcgroup}/bin/cgdelete"
# Patch shebangs before wrapping
patchShebangs $out/bin
# Wrap afl-clang-fast(++) with a *different* AFL_PATH, because it
# has totally different semantics in that case(?) - and also set a
# proper AFL_CC and AFL_CXX so we don't pick up the wrong one out
# of $PATH.
for x in $out/bin/afl-clang-fast $out/bin/afl-clang-fast++; do
wrapProgram $x \
--prefix AFL_PATH : "$out/lib/afl" \
--run 'export AFL_CC=''${AFL_CC:-${clang}/bin/clang} AFL_CXX=''${AFL_CXX:-${clang}/bin/clang++}'
done
'';
passthru = {
qemu = afl-qemu;
};
meta = {
description = "Powerful fuzzer via genetic algorithms and instrumentation";
longDescription = ''
American fuzzy lop is a fuzzer that employs a novel type of
compile-time instrumentation and genetic algorithms to
automatically discover clean, interesting test cases that
trigger new internal states in the targeted binary. This
substantially improves the functional coverage for the fuzzed
code. The compact synthesized corpora produced by the tool are
also useful for seeding other, more labor or resource-intensive
testing regimes down the road.
makeFlags = [ "PREFIX=$(out)" ];
postBuild = ''
make -C llvm_mode $makeFlags -j$NIX_BUILD_CORES
'';
homepage = "http://lcamtuf.coredump.cx/afl/";
license = stdenv.lib.licenses.asl20;
platforms = ["x86_64-linux" "i686-linux"];
maintainers = [ stdenv.lib.maintainers.thoughtpolice ];
postInstall = ''
# Install the custom QEMU emulator for binary blob fuzzing.
cp ${afl-qemu}/bin/${qemu-exe-name} $out/bin/afl-qemu-trace
# Install the cgroups wrapper for asan-based fuzzing.
cp experimental/asan_cgroups/limit_memory.sh $out/bin/afl-cgroup
chmod +x $out/bin/afl-cgroup
substituteInPlace $out/bin/afl-cgroup \
--replace "cgcreate" "${libcgroup}/bin/cgcreate" \
--replace "cgexec" "${libcgroup}/bin/cgexec" \
--replace "cgdelete" "${libcgroup}/bin/cgdelete"
# Patch shebangs before wrapping
patchShebangs $out/bin
# Wrap afl-clang-fast(++) with a *different* AFL_PATH, because it
# has totally different semantics in that case(?) - and also set a
# proper AFL_CC and AFL_CXX so we don't pick up the wrong one out
# of $PATH.
for x in $out/bin/afl-clang-fast $out/bin/afl-clang-fast++; do
wrapProgram $x \
--prefix AFL_PATH : "$out/lib/afl" \
--run 'export AFL_CC=''${AFL_CC:-${clang}/bin/clang} AFL_CXX=''${AFL_CXX:-${clang}/bin/clang++}'
done
'';
passthru.qemu = afl-qemu;
meta = {
description = "Powerful fuzzer via genetic algorithms and instrumentation";
longDescription = ''
American fuzzy lop is a fuzzer that employs a novel type of
compile-time instrumentation and genetic algorithms to
automatically discover clean, interesting test cases that
trigger new internal states in the targeted binary. This
substantially improves the functional coverage for the fuzzed
code. The compact synthesized corpora produced by the tool are
also useful for seeding other, more labor or resource-intensive
testing regimes down the road.
'';
homepage = "http://lcamtuf.coredump.cx/afl/";
license = stdenv.lib.licenses.asl20;
platforms = ["x86_64-linux" "i686-linux"];
maintainers = [ stdenv.lib.maintainers.thoughtpolice ];
};
};
}
in afl

View File

@ -1,335 +0,0 @@
/*
american fuzzy lop - vaguely configurable bits
----------------------------------------------
Written and maintained by Michal Zalewski <lcamtuf@google.com>
Copyright 2013, 2014, 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
*/
#ifndef _HAVE_CONFIG_H
#define _HAVE_CONFIG_H
#include "afl-types.h"
/******************************************************
* *
* Settings that may be of interest to power users: *
* *
******************************************************/
/* Comment out to disable terminal colors: */
#define USE_COLOR
/* Comment out to disable fancy ANSI boxes and use poor man's 7-bit UI: */
#define FANCY_BOXES
/* Default timeout for fuzzed code (milliseconds): */
#define EXEC_TIMEOUT 1000
/* Timeout rounding factor when auto-scaling (milliseconds): */
#define EXEC_TM_ROUND 20
/* Default memory limit for child process (MB): */
#ifndef __x86_64__
# define MEM_LIMIT 25
#else
# define MEM_LIMIT 50
#endif /* ^!__x86_64__ */
/* Default memory limit when running in QEMU mode (MB): */
#define MEM_LIMIT_QEMU 200
/* Number of calibration cycles per every new test case (and for test
cases that show variable behavior): */
#define CAL_CYCLES 10
#define CAL_CYCLES_LONG 40
/* The same, but when AFL_NO_VAR_CHECK is set in the environment: */
#define CAL_CYCLES_NO_VAR 4
/* Number of subsequent hangs before abandoning an input file: */
#define HANG_LIMIT 250
/* Maximum number of unique hangs or crashes to record: */
#define KEEP_UNIQUE_HANG 500
#define KEEP_UNIQUE_CRASH 5000
/* Baseline number of random tweaks during a single 'havoc' stage: */
#define HAVOC_CYCLES 5000
/* Maximum multiplier for the above (should be a power of two, beware
of 32-bit int overflows): */
#define HAVOC_MAX_MULT 16
/* Absolute minimum number of havoc cycles (after all adjustments): */
#define HAVOC_MIN 10
/* Maximum stacking for havoc-stage tweaks. The actual value is calculated
like this:
n = random between 1 and HAVOC_STACK_POW2
stacking = 2^n
In other words, the default (n = 7) produces 2, 4, 8, 16, 32, 64, or
128 stacked tweaks: */
#define HAVOC_STACK_POW2 7
/* Caps on block sizes for cloning and deletion operations. Each of these
ranges has a 33% probability of getting picked, except for the first
two cycles where smaller blocks are favored: */
#define HAVOC_BLK_SMALL 32
#define HAVOC_BLK_MEDIUM 128
#define HAVOC_BLK_LARGE 1500
/* Probabilities of skipping non-favored entries in the queue, expressed as
percentages: */
#define SKIP_TO_NEW_PROB 99 /* ...when there are new, pending favorites */
#define SKIP_NFAV_OLD_PROB 95 /* ...no new favs, cur entry already fuzzed */
#define SKIP_NFAV_NEW_PROB 75 /* ...no new favs, cur entry not fuzzed yet */
/* Splicing cycle count: */
#define SPLICE_CYCLES 20
/* Nominal per-splice havoc cycle length: */
#define SPLICE_HAVOC 500
/* Maximum offset for integer addition / subtraction stages: */
#define ARITH_MAX 35
/* Limits for the test case trimmer. The absolute minimum chunk size; and
the starting and ending divisors for chopping up the input file: */
#define TRIM_MIN_BYTES 4
#define TRIM_START_STEPS 16
#define TRIM_END_STEPS 1024
/* Maximum size of input file, in bytes (keep under 100MB): */
#define MAX_FILE (1 * 1024 * 1024)
/* The same, for the test case minimizer: */
#define TMIN_MAX_FILE (10 * 1024 * 1024)
/* Block normalization steps for afl-tmin: */
#define TMIN_SET_MIN_SIZE 4
#define TMIN_SET_STEPS 128
/* Maximum dictionary token size (-x), in bytes: */
#define MAX_DICT_FILE 128
/* Length limits for auto-detected dictionary tokens: */
#define MIN_AUTO_EXTRA 3
#define MAX_AUTO_EXTRA 32
/* Maximum number of user-specified dictionary tokens to use in deterministic
steps; past this point, the "extras/user" step will be still carried out,
but with proportionally lower odds: */
#define MAX_DET_EXTRAS 200
/* Maximum number of auto-extracted dictionary tokens to actually use in fuzzing
(first value), and to keep in memory as candidates. The latter should be much
higher than the former. */
#define USE_AUTO_EXTRAS 50
#define MAX_AUTO_EXTRAS (USE_AUTO_EXTRAS * 10)
/* Scaling factor for the effector map used to skip some of the more
expensive deterministic steps. The actual divisor is set to
2^EFF_MAP_SCALE2 bytes: */
#define EFF_MAP_SCALE2 3
/* Minimum input file length at which the effector logic kicks in: */
#define EFF_MIN_LEN 128
/* Maximum effector density past which everything is just fuzzed
unconditionally (%): */
#define EFF_MAX_PERC 90
/* UI refresh frequency (Hz): */
#define UI_TARGET_HZ 5
/* Fuzzer stats file and plot update intervals (sec): */
#define STATS_UPDATE_SEC 60
#define PLOT_UPDATE_SEC 5
/* Smoothing divisor for CPU load and exec speed stats (1 - no smoothing). */
#define AVG_SMOOTHING 16
/* Sync interval (every n havoc cycles): */
#define SYNC_INTERVAL 5
/* Output directory reuse grace period (minutes): */
#define OUTPUT_GRACE 25
/* Uncomment to use simple file names (id_NNNNNN): */
// #define SIMPLE_FILES
/* List of interesting values to use in fuzzing. */
#define INTERESTING_8 \
-128, /* Overflow signed 8-bit when decremented */ \
-1, /* */ \
0, /* */ \
1, /* */ \
16, /* One-off with common buffer size */ \
32, /* One-off with common buffer size */ \
64, /* One-off with common buffer size */ \
100, /* One-off with common buffer size */ \
127 /* Overflow signed 8-bit when incremented */
#define INTERESTING_16 \
-32768, /* Overflow signed 16-bit when decremented */ \
-129, /* Overflow signed 8-bit */ \
128, /* Overflow signed 8-bit */ \
255, /* Overflow unsig 8-bit when incremented */ \
256, /* Overflow unsig 8-bit */ \
512, /* One-off with common buffer size */ \
1000, /* One-off with common buffer size */ \
1024, /* One-off with common buffer size */ \
4096, /* One-off with common buffer size */ \
32767 /* Overflow signed 16-bit when incremented */
#define INTERESTING_32 \
-2147483648LL, /* Overflow signed 32-bit when decremented */ \
-100663046, /* Large negative number (endian-agnostic) */ \
-32769, /* Overflow signed 16-bit */ \
32768, /* Overflow signed 16-bit */ \
65535, /* Overflow unsig 16-bit when incremented */ \
65536, /* Overflow unsig 16 bit */ \
100663045, /* Large positive number (endian-agnostic) */ \
2147483647 /* Overflow signed 32-bit when incremented */
/***********************************************************
* *
* Really exotic stuff you probably don't want to touch: *
* *
***********************************************************/
/* Call count interval between reseeding the libc PRNG from /dev/urandom: */
#define RESEED_RNG 10000
/* Maximum line length passed from GCC to 'as' and used for parsing
configuration files: */
#define MAX_LINE 8192
/* Environment variable used to pass SHM ID to the called program. */
#define SHM_ENV_VAR "__AFL_SHM_ID"
/* Other less interesting, internal-only variables. */
#define CLANG_ENV_VAR "__AFL_CLANG_MODE"
#define AS_LOOP_ENV_VAR "__AFL_AS_LOOPCHECK"
/* Distinctive bitmap signature used to indicate failed execution: */
#define EXEC_FAIL_SIG 0xfee1dead
/* Distinctive exit code used to indicate MSAN trip condition: */
#define MSAN_ERROR 86
/* Designated file descriptors for forkserver commands (the application will
use FORKSRV_FD and FORKSRV_FD + 1): */
#define FORKSRV_FD 198
/* Fork server init timeout multiplier: we'll wait the user-selected
timeout plus this much for the fork server to spin up. */
#define FORK_WAIT_MULT 10
/* Calibration timeout adjustments, to be a bit more generous when resuming
fuzzing sessions or trying to calibrate already-added internal finds.
The first value is a percentage, the other is in milliseconds: */
#define CAL_TMOUT_PERC 125
#define CAL_TMOUT_ADD 50
/* Number of chances to calibrate a case before giving up: */
#define CAL_CHANCES 3
/* Map size for the traced binary (2^MAP_SIZE_POW2). Must be greater than
2; you probably want to keep it under 18 or so for performance reasons
(adjusting AFL_INST_RATIO when compiling is probably a better way to solve
problems with complex programs). You need to recompile the target binary
after changing this - otherwise, SEGVs may ensue. */
#define MAP_SIZE_POW2 16
#define MAP_SIZE (1 << MAP_SIZE_POW2)
/* Maximum allocator request size (keep well under INT_MAX): */
#define MAX_ALLOC 0x40000000
/* A made-up hashing seed: */
#define HASH_CONST 0xa5b35705
/* Constants for afl-gotcpu to control busy loop timing: */
#define CTEST_TARGET_MS 5000
#define CTEST_BUSY_CYCLES (10 * 1000 * 1000)
/* Uncomment this to use inferior block-coverage-based instrumentation. Note
that you need to recompile the target binary for this to have any effect: */
// #define COVERAGE_ONLY
/* Uncomment this to ignore hit counts and output just one bit per tuple.
As with the previous setting, you will need to recompile the target
binary: */
// #define SKIP_COUNTS
/* Uncomment this to use instrumentation data to record newly discovered paths,
but do not use them as seeds for fuzzing. This is useful for conveniently
measuring coverage that could be attained by a "dumb" fuzzing algorithm: */
// #define IGNORE_FINDS
#endif /* ! _HAVE_CONFIG_H */

View File

@ -1,296 +0,0 @@
/*
american fuzzy lop - high-performance binary-only instrumentation
-----------------------------------------------------------------
Written by Andrew Griffiths <agriffiths@google.com> and
Michal Zalewski <lcamtuf@google.com>
Idea & design very much by Andrew Griffiths.
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 code is a shim patched into the separately-distributed source
code of QEMU 2.2.0. It leverages the built-in QEMU tracing functionality
to implement AFL-style instrumentation and to take care of the remaining
parts of the AFL fork server logic.
The resulting QEMU binary is essentially a standalone instrumentation
tool; for an example of how to leverage it for other purposes, you can
have a look at afl-showmap.c.
*/
#include <sys/shm.h>
#include "afl-config.h"
/***************************
* VARIOUS AUXILIARY STUFF *
***************************/
/* A snippet patched into tb_find_slow to inform the parent process that
we have hit a new block that hasn't been translated yet, and to tell
it to translate within its own context, too (this avoids translation
overhead in the next forked-off copy). */
#define AFL_QEMU_CPU_SNIPPET1 do { \
afl_request_tsl(pc, cs_base, flags); \
} while (0)
/* This snippet kicks in when the instruction pointer is positioned at
_start and does the usual forkserver stuff, not very different from
regular instrumentation injected via afl-as.h. */
#define AFL_QEMU_CPU_SNIPPET2 do { \
if(tb->pc == afl_entry_point) { \
afl_setup(); \
afl_forkserver(env); \
} \
afl_maybe_log(tb->pc); \
} while (0)
/* We use one additional file descriptor to relay "needs translation"
messages between the child and the fork server. */
#define TSL_FD (FORKSRV_FD - 1)
/* This is equivalent to afl-as.h: */
static unsigned char *afl_area_ptr;
/* Exported variables populated by the code patched into elfload.c: */
abi_ulong afl_entry_point, /* ELF entry point (_start) */
afl_start_code, /* .text start pointer */
afl_end_code; /* .text end pointer */
/* Set in the child process in forkserver mode: */
static unsigned char afl_fork_child;
unsigned int afl_forksrv_pid;
/* Instrumentation ratio: */
static unsigned int afl_inst_rms = MAP_SIZE;
/* Function declarations. */
static void afl_setup(void);
static void afl_forkserver(CPUArchState*);
static inline void afl_maybe_log(abi_ulong);
static void afl_wait_tsl(CPUArchState*, int);
static void afl_request_tsl(target_ulong, target_ulong, uint64_t);
static TranslationBlock *tb_find_slow(CPUArchState*, target_ulong,
target_ulong, uint64_t);
/* Data structure passed around by the translate handlers: */
struct afl_tsl {
target_ulong pc;
target_ulong cs_base;
uint64_t flags;
};
/*************************
* ACTUAL IMPLEMENTATION *
*************************/
/* Set up SHM region and initialize other stuff. */
static void afl_setup(void) {
char *id_str = getenv(SHM_ENV_VAR),
*inst_r = getenv("AFL_INST_RATIO");
int shm_id;
if (inst_r) {
unsigned int r;
r = atoi(inst_r);
if (r > 100) r = 100;
if (!r) r = 1;
afl_inst_rms = MAP_SIZE * r / 100;
}
if (id_str) {
shm_id = atoi(id_str);
afl_area_ptr = shmat(shm_id, NULL, 0);
if (afl_area_ptr == (void*)-1) exit(1);
/* With AFL_INST_RATIO set to a low value, we want to touch the bitmap
so that the parent doesn't give up on us. */
if (inst_r) afl_area_ptr[0] = 1;
}
if (getenv("AFL_INST_LIBS")) {
afl_start_code = 0;
afl_end_code = (abi_ulong)-1;
}
}
/* Fork server logic, invoked once we hit _start. */
static void afl_forkserver(CPUArchState *env) {
static unsigned char tmp[4];
if (!afl_area_ptr) return;
/* Tell the parent that we're alive. If the parent doesn't want
to talk, assume that we're not running in forkserver mode. */
if (write(FORKSRV_FD + 1, tmp, 4) != 4) return;
afl_forksrv_pid = getpid();
/* All right, let's await orders... */
while (1) {
pid_t child_pid;
int status, t_fd[2];
/* Whoops, parent dead? */
if (read(FORKSRV_FD, tmp, 4) != 4) exit(2);
/* Establish a channel with child to grab translation commands. We'll
read from t_fd[0], child will write to TSL_FD. */
if (pipe(t_fd) || dup2(t_fd[1], TSL_FD) < 0) exit(3);
close(t_fd[1]);
child_pid = fork();
if (child_pid < 0) exit(4);
if (!child_pid) {
/* Child process. Close descriptors and run free. */
afl_fork_child = 1;
close(FORKSRV_FD);
close(FORKSRV_FD + 1);
close(t_fd[0]);
return;
}
/* Parent. */
close(TSL_FD);
if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) exit(5);
/* Collect translation requests until child dies and closes the pipe. */
afl_wait_tsl(env, t_fd[0]);
/* Get and relay exit status to parent. */
if (waitpid(child_pid, &status, WUNTRACED) < 0) exit(6);
if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(7);
}
}
/* The equivalent of the tuple logging routine from afl-as.h. */
static inline void afl_maybe_log(abi_ulong cur_loc) {
static abi_ulong prev_loc;
/* Optimize for cur_loc > afl_end_code, which is the most likely case on
Linux systems. */
if (cur_loc > afl_end_code || cur_loc < afl_start_code || !afl_area_ptr)
return;
/* Looks like QEMU always maps to fixed locations, so we can skip this:
cur_loc -= afl_start_code; */
/* Instruction addresses may be aligned. Let's mangle the value to get
something quasi-uniform. */
cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
cur_loc &= MAP_SIZE - 1;
/* Implement probabilistic instrumentation by looking at scrambled block
address. This keeps the instrumented locations stable across runs. */
if (cur_loc >= afl_inst_rms) return;
afl_area_ptr[cur_loc ^ prev_loc]++;
prev_loc = cur_loc >> 1;
}
/* This code is invoked whenever QEMU decides that it doesn't have a
translation of a particular block and needs to compute it. When this happens,
we tell the parent to mirror the operation, so that the next fork() has a
cached copy. */
static void afl_request_tsl(target_ulong pc, target_ulong cb, uint64_t flags) {
struct afl_tsl t;
if (!afl_fork_child) return;
t.pc = pc;
t.cs_base = cb;
t.flags = flags;
if (write(TSL_FD, &t, sizeof(struct afl_tsl)) != sizeof(struct afl_tsl))
return;
}
/* This is the other side of the same channel. Since timeouts are handled by
afl-fuzz simply killing the child, we can just wait until the pipe breaks. */
static void afl_wait_tsl(CPUArchState *env, int fd) {
struct afl_tsl t;
while (1) {
/* Broken pipe means it's time to return to the fork server routine. */
if (read(fd, &t, sizeof(struct afl_tsl)) != sizeof(struct afl_tsl))
break;
tb_find_slow(env, t.pc, t.cs_base, t.flags);
}
close(fd);
}

View File

@ -1,79 +0,0 @@
/*
american fuzzy lop - type definitions and minor macros
------------------------------------------------------
Written and maintained by Michal Zalewski <lcamtuf@google.com>
Copyright 2013, 2014, 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
*/
#ifndef _HAVE_TYPES_H
#define _HAVE_TYPES_H
#include <stdint.h>
#include <stdlib.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
/*
Ugh. There is an unintended compiler / glibc #include glitch caused by
combining the u64 type an %llu in format strings, necessitating a workaround.
In essence, the compiler is always looking for 'unsigned long long' for %llu.
On 32-bit systems, the u64 type (aliased to uint64_t) is expanded to
'unsigned long long' in <bits/types.h>, so everything checks out.
But on 64-bit systems, it is #ifdef'ed in the same file as 'unsigned long'.
Now, it only happens in circumstances where the type happens to have the
expected bit width, *but* the compiler does not know that... and complains
about 'unsigned long' being unsafe to pass to %llu.
*/
#ifdef __x86_64__
typedef unsigned long long u64;
#else
typedef uint64_t u64;
#endif /* ^sizeof(...) */
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
#ifndef MIN
# define MIN(_a,_b) ((_a) > (_b) ? (_b) : (_a))
# define MAX(_a,_b) ((_a) > (_b) ? (_a) : (_b))
#endif /* !MIN */
#define SWAP16(_x) ({ \
u16 _ret = (_x); \
(u16)((_ret << 8) | (_ret >> 8)); \
})
#define SWAP32(_x) ({ \
u32 _ret = (_x); \
(u32)((_ret << 24) | (_ret >> 24) | \
((_ret << 8) & 0x00FF0000) | \
((_ret >> 8) & 0x0000FF00)); \
})
#define R(x) (random() % (x))
#define STRINGIFY_INTERNAL(x) #x
#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
#define MEM_BARRIER() \
asm volatile("" ::: "memory")
#endif /* ! _HAVE_TYPES_H */

View File

@ -1,33 +0,0 @@
--- qemu-2.3.0/cpu-exec.c.orig 2014-12-09 14:45:40.000000000 +0000
+++ qemu-2.3.0/cpu-exec.c 2015-02-20 22:07:02.966000000 +0000
@@ -28,6 +28,8 @@
#include "exec/memory-internal.h"
#include "qemu/rcu.h"
+#include "afl-qemu-cpu-inl.h"
+
/* -icount align implementation. */
typedef struct SyncClocks {
@@ -296,8 +298,11 @@
}
not_found:
/* if no translated code available, then translate it now */
+
tb = tb_gen_code(cpu, pc, cs_base, flags, 0);
+ AFL_QEMU_CPU_SNIPPET1;
+
found:
/* Move the last found TB to the head of the list */
if (likely(*ptb1)) {
@@ -492,6 +497,9 @@
next_tb = 0;
tcg_ctx.tb_ctx.tb_invalidated_flag = 0;
}
+
+ AFL_QEMU_CPU_SNIPPET2;
+
if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
qemu_log("Trace %p [" TARGET_FMT_lx "] %s\n",
tb->tc_ptr, tb->pc, lookup_symbol(tb->pc));

View File

@ -1,32 +0,0 @@
--- qemu-2.3.0/linux-user/elfload.c.orig 2014-12-09 14:45:42.000000000 +0000
+++ qemu-2.3.0/linux-user/elfload.c 2015-01-28 02:51:23.719000000 +0000
@@ -28,6 +28,8 @@
#define ELF_OSABI ELFOSABI_SYSV
+extern abi_ulong afl_entry_point, afl_start_code, afl_end_code;
+
/* from personality.h */
/*
@@ -1889,6 +1891,8 @@
info->brk = 0;
info->elf_flags = ehdr->e_flags;
+ if (!afl_entry_point) afl_entry_point = info->entry;
+
for (i = 0; i < ehdr->e_phnum; i++) {
struct elf_phdr *eppnt = phdr + i;
if (eppnt->p_type == PT_LOAD) {
@@ -1922,9 +1926,11 @@
if (elf_prot & PROT_EXEC) {
if (vaddr < info->start_code) {
info->start_code = vaddr;
+ if (!afl_start_code) afl_start_code = vaddr;
}
if (vaddr_ef > info->end_code) {
info->end_code = vaddr_ef;
+ if (!afl_end_code) afl_end_code = vaddr_ef;
}
}
if (elf_prot & PROT_WRITE) {

View File

@ -2,13 +2,12 @@ diff --git a/Makefile b/Makefile
index d6b9dc1..ce7c493 100644
--- a/Makefile
+++ b/Makefile
@@ -384,8 +384,7 @@ install-confdir:
install-sysconfig: install-datadir install-confdir
$(INSTALL_DATA) $(SRC_PATH)/sysconfigs/target/target-x86_64.conf "$(DESTDIR)$(qemu_confdir)"
@@ -601,7 +601,7 @@ install-localstatedir:
endif
-install: all $(if $(BUILD_DOCS),install-doc) install-sysconfig \
-install-datadir install-localstatedir
-install: all $(if $(BUILD_DOCS),install-doc) install-datadir install-localstatedir
+install: all $(if $(BUILD_DOCS),install-doc) install-datadir
ifneq ($(TOOLS),)
$(call install-prog,$(TOOLS),$(DESTDIR)$(bindir))
$(call install-prog,$(subst qemu-ga,qemu-ga$(EXESUF),$(TOOLS)),$(DESTDIR)$(bindir))
endif

View File

@ -0,0 +1,28 @@
A modified version of qemu commit 75e5b70e6b5dcc4f2219992d7cffa462aa406af0
diff --git a/configure b/configure
index 9c8aa5a..99ccc17 100755
--- a/configure
+++ b/configure
@@ -3855,7 +3855,7 @@ fi
# check if memfd is supported
memfd=no
cat > $TMPC << EOF
-#include <sys/memfd.h>
+#include <sys/mman.h>
int main(void)
{
diff --git a/util/memfd.c b/util/memfd.c
index 4571d1a..412e94a 100644
--- a/util/memfd.c
+++ b/util/memfd.c
@@ -31,9 +31,7 @@
#include "qemu/memfd.h"
-#ifdef CONFIG_MEMFD
-#include <sys/memfd.h>
-#elif defined CONFIG_LINUX
+#if defined CONFIG_LINUX && !defined CONFIG_MEMFD
#include <sys/syscall.h>
#include <asm/unistd.h>

View File

@ -1,121 +0,0 @@
diff --git a/user-exec.c b/user-exec.c
index 8f57e8a..957f9f7 100644
--- a/user-exec.c
+++ b/user-exec.c
@@ -57,7 +57,7 @@ static void exception_action(CPUState *cpu)
void cpu_resume_from_signal(CPUState *cpu, void *puc)
{
#ifdef __linux__
- struct ucontext *uc = puc;
+ ucontext_t *uc = puc;
#elif defined(__OpenBSD__)
struct sigcontext *uc = puc;
#endif
@@ -171,7 +171,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
#elif defined(__OpenBSD__)
struct sigcontext *uc = puc;
#else
- struct ucontext *uc = puc;
+ ucontext_t *uc = puc;
#endif
unsigned long pc;
int trapno;
@@ -226,7 +226,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
#elif defined(__OpenBSD__)
struct sigcontext *uc = puc;
#else
- struct ucontext *uc = puc;
+ ucontext_t *uc = puc;
#endif
pc = PC_sig(uc);
@@ -288,7 +288,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
#ifdef __APPLE__
#include <sys/ucontext.h>
-typedef struct ucontext SIGCONTEXT;
+typedef ucontext_t SIGCONTEXT;
/* All Registers access - only for local access */
#define REG_sig(reg_name, context) \
((context)->uc_mcontext->ss.reg_name)
@@ -331,7 +331,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
ucontext_t *uc = puc;
#else
- struct ucontext *uc = puc;
+ ucontext_t *uc = puc;
#endif
unsigned long pc;
int is_write;
@@ -358,7 +358,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
- struct ucontext *uc = puc;
+ ucontext_t *uc = puc;
uint32_t *pc = uc->uc_mcontext.sc_pc;
uint32_t insn = *pc;
int is_write = 0;
@@ -456,7 +456,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
#if defined(__NetBSD__)
ucontext_t *uc = puc;
#else
- struct ucontext *uc = puc;
+ ucontext_t *uc = puc;
#endif
unsigned long pc;
int is_write;
@@ -483,7 +483,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
{
siginfo_t *info = pinfo;
- struct ucontext *uc = puc;
+ ucontext_t *uc = puc;
uintptr_t pc = uc->uc_mcontext.pc;
uint32_t insn = *(uint32_t *)pc;
bool is_write;
@@ -512,7 +512,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
- struct ucontext *uc = puc;
+ ucontext_t *uc = puc;
unsigned long pc;
int is_write;
@@ -534,7 +534,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
{
siginfo_t *info = pinfo;
- struct ucontext *uc = puc;
+ ucontext_t *uc = puc;
unsigned long ip;
int is_write = 0;
@@ -565,7 +565,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
- struct ucontext *uc = puc;
+ ucontext_t *uc = puc;
unsigned long pc;
uint16_t *pinsn;
int is_write = 0;
@@ -618,7 +618,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
- struct ucontext *uc = puc;
+ ucontext_t *uc = puc;
greg_t pc = uc->uc_mcontext.pc;
int is_write;
@@ -634,7 +634,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
- struct ucontext *uc = puc;
+ ucontext_t *uc = puc;
unsigned long pc = uc->uc_mcontext.sc_iaoq[0];
uint32_t insn = *(uint32_t *)pc;
int is_write = 0;

View File

@ -1,25 +0,0 @@
--- qemu-2.3.0/linux-user/syscall.c.orig 2014-12-09 14:45:43.000000000 +0000
+++ qemu-2.3.0/linux-user/syscall.c 2015-03-27 06:33:00.736000000 +0000
@@ -227,7 +227,21 @@
_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
-_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
+
+extern unsigned int afl_forksrv_pid;
+
+static int sys_tgkill(int tgid, int pid, int sig) {
+
+ /* Workaround for -lpthread to make abort() work properly, without
+ killing the forkserver due to a prematurely cached PID. */
+
+ if (afl_forksrv_pid && afl_forksrv_pid == pid && sig == SIGABRT)
+ pid = tgid = getpid();
+
+ return syscall(__NR_sys_tgkill, pid, tgid, sig);
+
+}
+
#endif
#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
_syscall2(int,sys_tkill,int,tid,int,sig)

View File

@ -1,18 +0,0 @@
--- qemu-2.3.0/translate-all.c.orig 2014-12-09 14:45:46.000000000 +0000
+++ qemu-2.3.0/translate-all.c 2015-01-28 22:37:42.383000000 +0000
@@ -393,8 +393,13 @@
/* We can't use g_malloc because it may recurse into a locked mutex. */
# define ALLOC(P, SIZE) \
do { \
- P = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, \
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \
+ void* _tmp = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, \
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \
+ if (_tmp == (void*)-1) { \
+ qemu_log(">>> Out of memory for stack, bailing out. <<<\n"); \
+ exit(1); \
+ } \
+ (P) = _tmp; \
} while (0)
#else
# define ALLOC(P, SIZE) \

View File

@ -1,4 +1,4 @@
{ stdenv, fetchurl, python2, zlib, pkgconfig, glib, ncurses, perl
{ stdenv, fetchurl, afl, python2, zlib, pkgconfig, glib, ncurses, perl
, attr, libcap, vde2, texinfo, libuuid, flex, bison, lzo, snappy
, libaio, libcap_ng, gnutls, pixman, autoconf
, writeText
@ -7,59 +7,65 @@
with stdenv.lib;
let
n = "qemu-2.3.0";
aflHeaderFile = writeText "afl-qemu-cpu-inl.h"
(builtins.readFile ./qemu-patches/afl-qemu-cpu-inl.h);
aflConfigFile = writeText "afl-config.h"
(builtins.readFile ./qemu-patches/afl-config.h);
aflTypesFile = writeText "afl-types.h"
(builtins.readFile ./qemu-patches/afl-types.h);
qemuName = "qemu-2.10.0";
aflName = afl.name;
cpuTarget = if stdenv.hostPlatform.system == "x86_64-linux" then "x86_64-linux-user"
else if stdenv.hostPlatform.system == "i686-linux" then "i386-linux-user"
else throw "afl: no support for ${stdenv.hostPlatform.system}!";
in
stdenv.mkDerivation rec {
name = "afl-${n}";
name = "afl-${qemuName}";
src = fetchurl {
url = "http://wiki.qemu.org/download/${n}.tar.bz2";
sha256 = "120m53c3p28qxmfzllicjzr8syjv6v4d9rsyrgkp7gnmcgvvgfmn";
};
srcs = [
(fetchurl {
url = "http://wiki.qemu.org/download/${qemuName}.tar.bz2";
sha256 = "0j3dfxzrzdp1w21k21fjvmakzc6lcha1rsclaicwqvbf63hkk7vy";
})
afl.src
];
buildInputs =
[ python2 zlib pkgconfig glib pixman ncurses perl attr libcap
vde2 texinfo libuuid flex bison lzo snappy autoconf
libcap_ng gnutls
]
++ optionals (hasSuffix "linux" stdenv.hostPlatform.system) [ libaio ];
sourceRoot = qemuName;
postUnpack = ''
cp ${aflName}/types.h $sourceRoot/afl-types.h
substitute ${aflName}/config.h $sourceRoot/afl-config.h \
--replace "types.h" "afl-types.h"
substitute ${aflName}/qemu_mode/patches/afl-qemu-cpu-inl.h $sourceRoot/afl-qemu-cpu-inl.h \
--replace "../../config.h" "afl-config.h"
substituteInPlace ${aflName}/qemu_mode/patches/cpu-exec.diff \
--replace "../patches/afl-qemu-cpu-inl.h" "afl-qemu-cpu-inl.h"
'';
nativeBuildInputs = [
python2 perl pkgconfig flex bison autoconf texinfo
];
buildInputs = [
zlib glib pixman ncurses attr libcap
vde2 libuuid lzo snappy libcap_ng gnutls
] ++ optionals (stdenv.isLinux) [ libaio ];
enableParallelBuilding = true;
patches =
[ ./qemu-patches/elfload.patch
./qemu-patches/cpu-exec.patch
./qemu-patches/no-etc-install.patch
./qemu-patches/translate-all.patch
./qemu-patches/syscall.patch
./qemu-patches/qemu-2.3.0-glibc-2.26.patch
];
preConfigure = ''
cp ${aflTypesFile} afl-types.h
cp ${aflConfigFile} afl-config.h
cp ${aflHeaderFile} afl-qemu-cpu-inl.h
'';
patches = [
# patches extracted from afl source
"../${aflName}/qemu_mode/patches/cpu-exec.diff"
"../${aflName}/qemu_mode/patches/elfload.diff"
"../${aflName}/qemu_mode/patches/syscall.diff"
# nix-specific patches to make installation more well-behaved
./qemu-patches/no-etc-install.patch
./qemu-patches/qemu-2.10.0-glibc-2.27.patch
];
configureFlags =
[ "--disable-system"
"--enable-linux-user"
"--enable-guest-base"
"--disable-gtk"
"--disable-sdl"
"--disable-vnc"
"--target-list=${cpuTarget}"
"--enable-pie"
"--enable-kvm"
"--sysconfdir=/etc"
"--localstatedir=/var"
];