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:
commit
9d8ccfe00f
@ -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
|
||||
|
@ -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 */
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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 */
|
@ -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));
|
@ -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) {
|
@ -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
|
||||
|
@ -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>
|
@ -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;
|
@ -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)
|
@ -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) \
|
@ -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"
|
||||
];
|
||||
|
Loading…
Reference in New Issue
Block a user