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
|
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"
|
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 if stdenv.hostPlatform.system == "i686-linux" then "qemu-i386"
|
||||||
else throw "afl: no support for ${stdenv.hostPlatform.system}!";
|
else throw "afl: no support for ${stdenv.hostPlatform.system}!";
|
||||||
in
|
afl = stdenv.mkDerivation rec {
|
||||||
|
name = "afl-${version}";
|
||||||
|
version = "2.52b";
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
src = fetchurl {
|
||||||
name = "afl-${version}";
|
url = "http://lcamtuf.coredump.cx/afl/releases/${name}.tgz";
|
||||||
version = "2.52b";
|
sha256 = "0ig0ij4n1pwry5dw1hk4q88801jzzy2cric6y2gd6560j55lnqa3";
|
||||||
|
};
|
||||||
|
enableParallelBuilding = true;
|
||||||
|
|
||||||
src = fetchurl {
|
# Note: libcgroup isn't needed for building, just for the afl-cgroup
|
||||||
url = "http://lcamtuf.coredump.cx/afl/releases/${name}.tgz";
|
# script.
|
||||||
sha256 = "0ig0ij4n1pwry5dw1hk4q88801jzzy2cric6y2gd6560j55lnqa3";
|
nativeBuildInputs = [ makeWrapper which ];
|
||||||
};
|
buildInputs = [ llvm ];
|
||||||
|
|
||||||
# Note: libcgroup isn't needed for building, just for the afl-cgroup
|
makeFlags = [ "PREFIX=$(out)" ];
|
||||||
# script.
|
postBuild = ''
|
||||||
buildInputs = [ makeWrapper llvm which ];
|
make -C llvm_mode $makeFlags -j$NIX_BUILD_CORES
|
||||||
|
|
||||||
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.
|
|
||||||
'';
|
'';
|
||||||
homepage = "http://lcamtuf.coredump.cx/afl/";
|
postInstall = ''
|
||||||
license = stdenv.lib.licenses.asl20;
|
# Install the custom QEMU emulator for binary blob fuzzing.
|
||||||
platforms = ["x86_64-linux" "i686-linux"];
|
cp ${afl-qemu}/bin/${qemu-exe-name} $out/bin/afl-qemu-trace
|
||||||
maintainers = [ stdenv.lib.maintainers.thoughtpolice ];
|
|
||||||
|
# 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
|
index d6b9dc1..ce7c493 100644
|
||||||
--- a/Makefile
|
--- a/Makefile
|
||||||
+++ b/Makefile
|
+++ b/Makefile
|
||||||
@@ -384,8 +384,7 @@ install-confdir:
|
@@ -601,7 +601,7 @@ install-localstatedir:
|
||||||
install-sysconfig: install-datadir install-confdir
|
endif
|
||||||
$(INSTALL_DATA) $(SRC_PATH)/sysconfigs/target/target-x86_64.conf "$(DESTDIR)$(qemu_confdir)"
|
|
||||||
|
|
||||||
-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
|
+install: all $(if $(BUILD_DOCS),install-doc) install-datadir
|
||||||
ifneq ($(TOOLS),)
|
ifneq ($(TOOLS),)
|
||||||
$(call install-prog,$(TOOLS),$(DESTDIR)$(bindir))
|
$(call install-prog,$(subst qemu-ga,qemu-ga$(EXESUF),$(TOOLS)),$(DESTDIR)$(bindir))
|
||||||
endif
|
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
|
, attr, libcap, vde2, texinfo, libuuid, flex, bison, lzo, snappy
|
||||||
, libaio, libcap_ng, gnutls, pixman, autoconf
|
, libaio, libcap_ng, gnutls, pixman, autoconf
|
||||||
, writeText
|
, writeText
|
||||||
@ -7,59 +7,65 @@
|
|||||||
with stdenv.lib;
|
with stdenv.lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
n = "qemu-2.3.0";
|
qemuName = "qemu-2.10.0";
|
||||||
|
aflName = afl.name;
|
||||||
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);
|
|
||||||
|
|
||||||
cpuTarget = if stdenv.hostPlatform.system == "x86_64-linux" then "x86_64-linux-user"
|
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 if stdenv.hostPlatform.system == "i686-linux" then "i386-linux-user"
|
||||||
else throw "afl: no support for ${stdenv.hostPlatform.system}!";
|
else throw "afl: no support for ${stdenv.hostPlatform.system}!";
|
||||||
in
|
in
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
name = "afl-${n}";
|
name = "afl-${qemuName}";
|
||||||
|
|
||||||
src = fetchurl {
|
srcs = [
|
||||||
url = "http://wiki.qemu.org/download/${n}.tar.bz2";
|
(fetchurl {
|
||||||
sha256 = "120m53c3p28qxmfzllicjzr8syjv6v4d9rsyrgkp7gnmcgvvgfmn";
|
url = "http://wiki.qemu.org/download/${qemuName}.tar.bz2";
|
||||||
};
|
sha256 = "0j3dfxzrzdp1w21k21fjvmakzc6lcha1rsclaicwqvbf63hkk7vy";
|
||||||
|
})
|
||||||
|
afl.src
|
||||||
|
];
|
||||||
|
|
||||||
buildInputs =
|
sourceRoot = qemuName;
|
||||||
[ python2 zlib pkgconfig glib pixman ncurses perl attr libcap
|
|
||||||
vde2 texinfo libuuid flex bison lzo snappy autoconf
|
postUnpack = ''
|
||||||
libcap_ng gnutls
|
cp ${aflName}/types.h $sourceRoot/afl-types.h
|
||||||
]
|
substitute ${aflName}/config.h $sourceRoot/afl-config.h \
|
||||||
++ optionals (hasSuffix "linux" stdenv.hostPlatform.system) [ libaio ];
|
--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;
|
enableParallelBuilding = true;
|
||||||
|
|
||||||
patches =
|
patches = [
|
||||||
[ ./qemu-patches/elfload.patch
|
# patches extracted from afl source
|
||||||
./qemu-patches/cpu-exec.patch
|
"../${aflName}/qemu_mode/patches/cpu-exec.diff"
|
||||||
./qemu-patches/no-etc-install.patch
|
"../${aflName}/qemu_mode/patches/elfload.diff"
|
||||||
./qemu-patches/translate-all.patch
|
"../${aflName}/qemu_mode/patches/syscall.diff"
|
||||||
./qemu-patches/syscall.patch
|
# nix-specific patches to make installation more well-behaved
|
||||||
./qemu-patches/qemu-2.3.0-glibc-2.26.patch
|
./qemu-patches/no-etc-install.patch
|
||||||
];
|
./qemu-patches/qemu-2.10.0-glibc-2.27.patch
|
||||||
|
];
|
||||||
preConfigure = ''
|
|
||||||
cp ${aflTypesFile} afl-types.h
|
|
||||||
cp ${aflConfigFile} afl-config.h
|
|
||||||
cp ${aflHeaderFile} afl-qemu-cpu-inl.h
|
|
||||||
'';
|
|
||||||
|
|
||||||
configureFlags =
|
configureFlags =
|
||||||
[ "--disable-system"
|
[ "--disable-system"
|
||||||
"--enable-linux-user"
|
"--enable-linux-user"
|
||||||
"--enable-guest-base"
|
|
||||||
"--disable-gtk"
|
"--disable-gtk"
|
||||||
"--disable-sdl"
|
"--disable-sdl"
|
||||||
"--disable-vnc"
|
"--disable-vnc"
|
||||||
"--target-list=${cpuTarget}"
|
"--target-list=${cpuTarget}"
|
||||||
|
"--enable-pie"
|
||||||
|
"--enable-kvm"
|
||||||
"--sysconfdir=/etc"
|
"--sysconfdir=/etc"
|
||||||
"--localstatedir=/var"
|
"--localstatedir=/var"
|
||||||
];
|
];
|
||||||
|
Loading…
Reference in New Issue
Block a user