Merge pull request #842 from AFLplusplus/stable

3.12c release
This commit is contained in:
van Hauser 2021-03-24 11:25:33 +01:00 committed by GitHub
commit f0e08e6486
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 963 additions and 1026 deletions

View File

@ -3,8 +3,8 @@ name: CI
on: on:
push: push:
branches: [ stable, dev ] branches: [ stable, dev ]
# pull_request: pull_request:
# branches: [ stable, dev ] branches: [ stable, dev ]
jobs: jobs:
build: build:

View File

@ -3,8 +3,8 @@ name: "CodeQL"
on: on:
push: push:
branches: [ stable, dev ] branches: [ stable, dev ]
# pull_request: pull_request:
# branches: [ stable, dev ] branches: [ stable, dev ]
jobs: jobs:
analyze: analyze:

1
.gitignore vendored
View File

@ -65,7 +65,6 @@ qemu_mode/qemu-*
qemu_mode/qemuafl qemu_mode/qemuafl
unicorn_mode/samples/*/\.test-* unicorn_mode/samples/*/\.test-*
unicorn_mode/samples/*/output/ unicorn_mode/samples/*/output/
unicorn_mode/unicornafl
test/unittests/unit_maybe_alloc test/unittests/unit_maybe_alloc
test/unittests/unit_preallocable test/unittests/unit_preallocable
test/unittests/unit_list test/unittests/unit_list

View File

@ -558,6 +558,7 @@ clean:
-$(MAKE) -f GNUmakefile.gcc_plugin clean -$(MAKE) -f GNUmakefile.gcc_plugin clean
$(MAKE) -C utils/libdislocator clean $(MAKE) -C utils/libdislocator clean
$(MAKE) -C utils/libtokencap clean $(MAKE) -C utils/libtokencap clean
$(MAKE) -C utils/aflpp_driver clean
$(MAKE) -C utils/afl_network_proxy clean $(MAKE) -C utils/afl_network_proxy clean
$(MAKE) -C utils/socket_fuzzing clean $(MAKE) -C utils/socket_fuzzing clean
$(MAKE) -C utils/argv_fuzzing clean $(MAKE) -C utils/argv_fuzzing clean
@ -576,7 +577,11 @@ endif
deepclean: clean deepclean: clean
rm -rf unicorn_mode/unicornafl rm -rf unicorn_mode/unicornafl
rm -rf qemu_mode/qemuafl rm -rf qemu_mode/qemuafl
ifeq "$(IN_REPO)" "1"
# NEVER EVER ACTIVATE THAT!!!!! git reset --hard >/dev/null 2>&1 || true # NEVER EVER ACTIVATE THAT!!!!! git reset --hard >/dev/null 2>&1 || true
git checkout unicorn_mode/unicornafl
git checkout qemu_mode/qemuafl
endif
.PHONY: distrib .PHONY: distrib
distrib: all distrib: all

View File

@ -507,6 +507,8 @@ install: all
@echo .SH LICENSE >> ./$@ @echo .SH LICENSE >> ./$@
@echo Apache License Version 2.0, January 2004 >> ./$@ @echo Apache License Version 2.0, January 2004 >> ./$@
@ln -sf afl-cc.8 ./afl-c++.8 @ln -sf afl-cc.8 ./afl-c++.8
@ln -sf afl-cc.8 ./afl-clang-fast.8
@ln -sf afl-cc.8 ./afl-clang-fast++.8
ifneq "$(AFL_CLANG_FLTO)" "" ifneq "$(AFL_CLANG_FLTO)" ""
ifeq "$(LLVM_LTO)" "1" ifeq "$(LLVM_LTO)" "1"
@ln -sf afl-cc.8 ./afl-clang-lto.8 @ln -sf afl-cc.8 ./afl-clang-lto.8

View File

@ -2,9 +2,9 @@
<img align="right" src="https://raw.githubusercontent.com/andreafioraldi/AFLplusplus-website/master/static/logo_256x256.png" alt="AFL++ Logo"> <img align="right" src="https://raw.githubusercontent.com/andreafioraldi/AFLplusplus-website/master/static/logo_256x256.png" alt="AFL++ Logo">
Release Version: [3.11c](https://github.com/AFLplusplus/AFLplusplus/releases) Release Version: [3.12c](https://github.com/AFLplusplus/AFLplusplus/releases)
Github Version: 3.12a Github Version: 3.13a
Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
@ -175,7 +175,13 @@ If you want to build afl++ yourself you have many options.
The easiest choice is to build and install everything: The easiest choice is to build and install everything:
```shell ```shell
sudo apt install build-essential python3-dev automake flex bison libglib2.0-dev libpixman-1-dev python3-setuptools clang lld llvm llvm-dev libstdc++-dev sudo apt-get update
sudo apt-get install -y build-essential python3-dev automake git flex bison libglib2.0-dev libpixman-1-dev python3-setuptools
# try to install llvm 11 and install the distro default if that fails
sudo apt-get install -y lld-11 llvm-11 llvm-11-dev clang-11 || sudo apt-get install -y lld llvm llvm-dev clang
sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-dev
git clone https://github.com/AFLplusplus/AFLplusplus && cd AFLplusplus
cd AFLplusplus
make distrib make distrib
sudo make install sudo make install
``` ```
@ -1178,6 +1184,7 @@ without feedback, bug reports, or patches from:
Josephine Calliotte Konrad Welc Josephine Calliotte Konrad Welc
Thomas Rooijakkers David Carlier Thomas Rooijakkers David Carlier
Ruben ten Hove Joey Jiao Ruben ten Hove Joey Jiao
fuzzah
``` ```
Thank you! Thank you!

View File

@ -2,6 +2,7 @@
## Roadmap 3.00+ ## Roadmap 3.00+
- Update afl->pending_not_fuzzed for MOpt
- CPU affinity for many cores? There seems to be an issue > 96 cores - CPU affinity for many cores? There seems to be an issue > 96 cores
- afl-plot to support multiple plot_data - afl-plot to support multiple plot_data
- afl_custom_fuzz_splice_optin() - afl_custom_fuzz_splice_optin()

View File

@ -8,6 +8,29 @@
Want to stay in the loop on major new features? Join our mailing list by Want to stay in the loop on major new features? Join our mailing list by
sending a mail to <afl-users+subscribe@googlegroups.com>. sending a mail to <afl-users+subscribe@googlegroups.com>.
### Version ++3.12c (release)
- afl-fuzz:
- added AFL_TARGET_ENV variable to pass extra env vars to the target
(for things like LD_LIBRARY_PATH)
- fix map detection, AFL_MAP_SIZE not needed anymore for most cases
- fix counting favorites (just a display thing)
- afl-cc:
- fix cmplog rtn (rare crash and not being able to gather ptr data)
- fix our own PCGUARD implementation to compile with llvm 10.0.1
- link runtime not to shared libs
- ensure shared libraries are properly built and instrumented
- AFL_LLVM_INSTRUMENT_ALLOW/DENY were not implemented for LTO, added
- show correct LLVM PCGUARD NATIVE mode when auto switching to it
and keep fsanitize-coverage-*list=...
Short mnemnonic NATIVE is now also accepted.
- qemu_mode (thanks @realmadsci):
- move AFL_PRELOAD and AFL_USE_QASAN logic inside afl-qemu-trace
- add AFL_QEMU_CUSTOM_BIN
- unicorn_mode
- accidently removed the subfolder from github, re-added
- added DEFAULT_PERMISSION to config.h for all files created, default
to 0600
### Version ++3.11c (release) ### Version ++3.11c (release)
- afl-fuzz: - afl-fuzz:
- better auto detection of map size - better auto detection of map size
@ -38,7 +61,6 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- we no longer perform a "git drop" - we no longer perform a "git drop"
- afl-cmin: support filenames with spaces - afl-cmin: support filenames with spaces
### Version ++3.10c (release) ### Version ++3.10c (release)
- Mac OS ARM64 support - Mac OS ARM64 support
- Android support fixed and updated by Joey Jiaojg - thanks! - Android support fixed and updated by Joey Jiaojg - thanks!

View File

@ -393,6 +393,10 @@ checks or alter some of the more exotic semantics of the tool:
- In QEMU mode (-Q), `AFL_PATH` will be searched for afl-qemu-trace. - In QEMU mode (-Q), `AFL_PATH` will be searched for afl-qemu-trace.
- In QEMU mode (-Q), setting `AFL_QEMU_CUSTOM_BIN` cause afl-fuzz to skip
prepending `afl-qemu-trace` to your command line. Use this if you wish to use a
custom afl-qemu-trace or if you need to modify the afl-qemu-trace arguments.
- Setting `AFL_CYCLE_SCHEDULES` will switch to a different schedule everytime - Setting `AFL_CYCLE_SCHEDULES` will switch to a different schedule everytime
a cycle is finished. a cycle is finished.
@ -404,6 +408,12 @@ checks or alter some of the more exotic semantics of the tool:
without disrupting the afl-fuzz process itself. This is useful, among other without disrupting the afl-fuzz process itself. This is useful, among other
things, for bootstrapping libdislocator.so. things, for bootstrapping libdislocator.so.
- Setting `AFL_TARGET_ENV` causes AFL++ to set extra environment variables
for the target binary. Example: `AFL_TARGET_ENV="VAR1=1 VAR2='a b c'" afl-fuzz ... `
This exists mostly for things like `LD_LIBRARY_PATH` but it would theoretically
allow fuzzing of AFL++ itself (with 'target' AFL++ using some AFL_ vars that
would disrupt work of 'fuzzer' AFL++).
- Setting `AFL_NO_UI` inhibits the UI altogether, and just periodically prints - Setting `AFL_NO_UI` inhibits the UI altogether, and just periodically prints
some basic stats. This behavior is also automatically triggered when the some basic stats. This behavior is also automatically triggered when the
output from afl-fuzz is redirected to a file or to a pipe. output from afl-fuzz is redirected to a file or to a pipe.
@ -415,7 +425,8 @@ checks or alter some of the more exotic semantics of the tool:
no valid terminal was detected (for virtual consoles) no valid terminal was detected (for virtual consoles)
- If you are Jakub, you may need `AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES`. - If you are Jakub, you may need `AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES`.
Others need not apply. Others need not apply, unless they also want to disable the
`/proc/sys/kernel/core_pattern` check.
- Benchmarking only: `AFL_BENCH_JUST_ONE` causes the fuzzer to exit after - Benchmarking only: `AFL_BENCH_JUST_ONE` causes the fuzzer to exit after
processing the first queue entry; and `AFL_BENCH_UNTIL_CRASH` causes it to processing the first queue entry; and `AFL_BENCH_UNTIL_CRASH` causes it to

View File

@ -5,6 +5,43 @@
"__afl_auto_init"; "__afl_auto_init";
"__afl_area_initial"; "__afl_area_initial";
"__afl_prev_loc"; "__afl_prev_loc";
"__afl_prev_caller";
"__afl_prev_ctx";
"__afl_final_loc";
"__afl_map_addr";
"__afl_dictionary";
"__afl_dictionary_len";
"__afl_selective_coverage";
"__afl_selective_coverage_start_off";
"__afl_selective_coverage_temp";
"__afl_coverage_discard";
"__afl_coverage_skip";
"__afl_coverage_on";
"__afl_coverage_off";
"__afl_coverage_interesting";
"__afl_fuzz_len";
"__afl_fuzz_ptr";
"__sanitizer_cov_trace_pc_guard"; "__sanitizer_cov_trace_pc_guard";
"__sanitizer_cov_trace_pc_guard_init"; "__sanitizer_cov_trace_pc_guard_init";
"__cmplog_ins_hook1";
"__cmplog_ins_hook2";
"__cmplog_ins_hook4";
"__cmplog_ins_hookN";
"__cmplog_ins_hook16";
"__sanitizer_cov_trace_cmp1";
"__sanitizer_cov_trace_const_cmp1";
"__sanitizer_cov_trace_cmp2";
"__sanitizer_cov_trace_const_cmp2";
"__sanitizer_cov_trace_cmp4";
"__sanitizer_cov_trace_const_cmp4";
"__sanitizer_cov_trace_cmp8";
"__sanitizer_cov_trace_const_cmp8";
"__sanitizer_cov_trace_cmp16";
"__sanitizer_cov_trace_const_cmp16";
"__sanitizer_cov_trace_switch";
"__cmplog_rtn_hook";
"__cmplog_rtn_gcc_stdstring_cstring";
"__cmplog_rtn_gcc_stdstring_stdstring";
"__cmplog_rtn_llvm_stdstring_cstring";
"__cmplog_rtn_llvm_stdstring_stdstring";
}; };

View File

@ -390,7 +390,7 @@ typedef struct afl_env_vars {
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload,
*afl_max_det_extras, *afl_statsd_host, *afl_statsd_port, *afl_max_det_extras, *afl_statsd_host, *afl_statsd_port,
*afl_crash_exitcode, *afl_statsd_tags_flavor, *afl_testcache_size, *afl_crash_exitcode, *afl_statsd_tags_flavor, *afl_testcache_size,
*afl_testcache_entries, *afl_kill_signal; *afl_testcache_entries, *afl_kill_signal, *afl_target_env;
} afl_env_vars_t; } afl_env_vars_t;

View File

@ -48,7 +48,10 @@ void argv_cpy_free(char **argv);
char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv);
char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv);
char * get_afl_env(char *env); char * get_afl_env(char *env);
u8 * get_libqasan_path(u8 *own_loc);
/* Extract env vars from input string and set them using setenv()
For use with AFL_TARGET_ENV, ... */
bool extract_and_set_env(u8 *env_str);
extern u8 be_quiet; extern u8 be_quiet;
extern u8 *doc_path; /* path to documentation dir */ extern u8 *doc_path; /* path to documentation dir */
@ -58,6 +61,10 @@ extern u8 *doc_path; /* path to documentation dir */
u8 *find_binary(u8 *fname); u8 *find_binary(u8 *fname);
/* find an afl binary */
u8 *find_afl_binary(u8 *own_loc, u8 *fname);
/* Parses the kill signal environment variable, FATALs on error. /* Parses the kill signal environment variable, FATALs on error.
If the env is not set, sets the env to default_signal for the signal handlers If the env is not set, sets the env to default_signal for the signal handlers
and returns the default_signal. */ and returns the default_signal. */

View File

@ -26,7 +26,7 @@
/* Version string: */ /* Version string: */
// c = release, a = volatile github dev, e = experimental branch // c = release, a = volatile github dev, e = experimental branch
#define VERSION "++3.11c" #define VERSION "++3.12c"
/****************************************************** /******************************************************
* * * *
@ -34,6 +34,18 @@
* * * *
******************************************************/ ******************************************************/
/* Default shared memory map size. Most targets just need a coverage map
between 20-250kb. Plus there is an auto-detection feature in afl-fuzz.
However if a target has problematic constructors and init arrays then
this can fail. Hence afl-fuzz deploys a larger default map. The largest
map seen so far is the xlsx fuzzer for libreoffice which is 5MB.
At runtime this value can be overriden via AFL_MAP_SIZE.
Default: 8MB (defined in bytes) */
#define DEFAULT_SHMEM_SIZE (8 * 1024 * 1024)
/* Default file permission umode when creating files (default: 0600) */
#define DEFAULT_PERMISSION 0600
/* CMPLOG/REDQUEEN TUNING /* CMPLOG/REDQUEEN TUNING
* *
* Here you can modify tuning and solving options for CMPLOG. * Here you can modify tuning and solving options for CMPLOG.

View File

@ -42,6 +42,7 @@ static char *afl_environment_variables[] = {
"AFL_DEBUG_CHILD", "AFL_DEBUG_CHILD",
"AFL_DEBUG_GDB", "AFL_DEBUG_GDB",
"AFL_DISABLE_TRIM", "AFL_DISABLE_TRIM",
"AFL_DISABLE_LLVM_INSTRUMENTATION",
"AFL_DONT_OPTIMIZE", "AFL_DONT_OPTIMIZE",
"AFL_DRIVER_STDERR_DUPLICATE_FILENAME", "AFL_DRIVER_STDERR_DUPLICATE_FILENAME",
"AFL_DUMB_FORKSRV", "AFL_DUMB_FORKSRV",
@ -50,6 +51,7 @@ static char *afl_environment_variables[] = {
"AFL_FAST_CAL", "AFL_FAST_CAL",
"AFL_FORCE_UI", "AFL_FORCE_UI",
"AFL_FUZZER_ARGS", // oss-fuzz "AFL_FUZZER_ARGS", // oss-fuzz
"AFL_GDB",
"AFL_GCC_ALLOWLIST", "AFL_GCC_ALLOWLIST",
"AFL_GCC_DENYLIST", "AFL_GCC_DENYLIST",
"AFL_GCC_BLOCKLIST", "AFL_GCC_BLOCKLIST",
@ -129,7 +131,9 @@ static char *afl_environment_variables[] = {
"AFL_PATH", "AFL_PATH",
"AFL_PERFORMANCE_FILE", "AFL_PERFORMANCE_FILE",
"AFL_PRELOAD", "AFL_PRELOAD",
"AFL_TARGET_ENV",
"AFL_PYTHON_MODULE", "AFL_PYTHON_MODULE",
"AFL_QEMU_CUSTOM_BIN",
"AFL_QEMU_COMPCOV", "AFL_QEMU_COMPCOV",
"AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_COMPCOV_DEBUG",
"AFL_QEMU_DEBUG_MAPS", "AFL_QEMU_DEBUG_MAPS",

View File

@ -113,7 +113,7 @@ cmake \
-DLLVM_LINK_LLVM_DYLIB="ON" \ -DLLVM_LINK_LLVM_DYLIB="ON" \
-DLLVM_TARGETS_TO_BUILD="host" \ -DLLVM_TARGETS_TO_BUILD="host" \
../llvm/ ../llvm/
cmake --build . --parallel cmake --build . -j4
export PATH="$(pwd)/bin:$PATH" export PATH="$(pwd)/bin:$PATH"
export LLVM_CONFIG="$(pwd)/bin/llvm-config" export LLVM_CONFIG="$(pwd)/bin/llvm-config"
export LD_LIBRARY_PATH="$(llvm-config --libdir)${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" export LD_LIBRARY_PATH="$(llvm-config --libdir)${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"

View File

@ -507,6 +507,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
Zero = ConstantInt::get(Int8Tyi, 0); Zero = ConstantInt::get(Int8Tyi, 0);
One = ConstantInt::get(Int8Tyi, 1); One = ConstantInt::get(Int8Tyi, 1);
initInstrumentList();
scanForDangerousFunctions(&M); scanForDangerousFunctions(&M);
Mo = &M; Mo = &M;
@ -1229,7 +1230,7 @@ void ModuleSanitizerCoverage::instrumentFunction(
// afl++ START // afl++ START
if (!F.size()) return; if (!F.size()) return;
if (isIgnoreFunction(&F)) return; if (!isInInstrumentList(&F)) return;
// afl++ END // afl++ END
if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge)
@ -1291,10 +1292,17 @@ GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection(
*CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage, *CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage,
Constant::getNullValue(ArrayTy), "__sancov_gen_"); Constant::getNullValue(ArrayTy), "__sancov_gen_");
#if LLVM_VERSION_MAJOR > 12
if (TargetTriple.supportsCOMDAT() &&
(TargetTriple.isOSBinFormatELF() || !F.isInterposable()))
if (auto Comdat = getOrCreateFunctionComdat(F, TargetTriple))
Array->setComdat(Comdat);
#else
if (TargetTriple.supportsCOMDAT() && !F.isInterposable()) if (TargetTriple.supportsCOMDAT() && !F.isInterposable())
if (auto Comdat = if (auto Comdat =
GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId)) GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId))
Array->setComdat(Comdat); Array->setComdat(Comdat);
#endif
Array->setSection(getSectionName(Section)); Array->setSection(getSectionName(Section));
Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize())); Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize()));
GlobalsToAppendToUsed.push_back(Array); GlobalsToAppendToUsed.push_back(Array);

View File

@ -10,6 +10,7 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/EHPersonalities.h"
@ -34,11 +35,11 @@
#include "llvm/InitializePasses.h" #include "llvm/InitializePasses.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SpecialCaseList.h" #include "llvm/Support/SpecialCaseList.h"
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0) #if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
#include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/VirtualFileSystem.h"
#endif #endif
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/ModuleUtils.h" #include "llvm/Transforms/Utils/ModuleUtils.h"
@ -47,65 +48,6 @@
#include "debug.h" #include "debug.h"
#include "afl-llvm-common.h" #include "afl-llvm-common.h"
namespace llvm {
/// This is the ModuleSanitizerCoverage pass used in the new pass manager. The
/// pass instruments functions for coverage, adds initialization calls to the
/// module for trace PC guards and 8bit counters if they are requested, and
/// appends globals to llvm.compiler.used.
class ModuleSanitizerCoveragePass
: public PassInfoMixin<ModuleSanitizerCoveragePass> {
public:
explicit ModuleSanitizerCoveragePass(
SanitizerCoverageOptions Options = SanitizerCoverageOptions(),
const std::vector<std::string> &AllowlistFiles =
std::vector<std::string>(),
const std::vector<std::string> &BlocklistFiles =
std::vector<std::string>())
: Options(Options) {
if (AllowlistFiles.size() > 0)
Allowlist = SpecialCaseList::createOrDie(AllowlistFiles
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
,
*vfs::getRealFileSystem()
#endif
);
if (BlocklistFiles.size() > 0)
Blocklist = SpecialCaseList::createOrDie(BlocklistFiles
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
,
*vfs::getRealFileSystem()
#endif
);
}
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
static bool isRequired() {
return true;
}
private:
SanitizerCoverageOptions Options;
std::unique_ptr<SpecialCaseList> Allowlist;
std::unique_ptr<SpecialCaseList> Blocklist;
};
// Insert SanitizerCoverage instrumentation.
ModulePass *createModuleSanitizerCoverageLegacyPassPass(
const SanitizerCoverageOptions &Options = SanitizerCoverageOptions(),
const std::vector<std::string> &AllowlistFiles = std::vector<std::string>(),
const std::vector<std::string> &BlocklistFiles =
std::vector<std::string>());
} // namespace llvm
using namespace llvm; using namespace llvm;
#define DEBUG_TYPE "sancov" #define DEBUG_TYPE "sancov"
@ -156,96 +98,8 @@ static const char *const SanCovLowestStackName = "__sancov_lowest_stack";
static char *skip_nozero; static char *skip_nozero;
/*
static cl::opt<int> ClCoverageLevel(
"sanitizer-coverage-level",
cl::desc("Sanitizer Coverage. 0: none, 1: entry block, 2: all blocks, "
"3: all blocks and critical edges"),
cl::Hidden, cl::init(3));
static cl::opt<bool> ClTracePC("sanitizer-coverage-trace-pc",
cl::desc("Experimental pc tracing"), cl::Hidden,
cl::init(false));
static cl::opt<bool> ClTracePCGuard("sanitizer-coverage-trace-pc-guard",
cl::desc("pc tracing with a guard"),
cl::Hidden, cl::init(true));
// If true, we create a global variable that contains PCs of all instrumented
// BBs, put this global into a named section, and pass this section's bounds
// to __sanitizer_cov_pcs_init.
// This way the coverage instrumentation does not need to acquire the PCs
// at run-time. Works with trace-pc-guard, inline-8bit-counters, and
// inline-bool-flag.
static cl::opt<bool> ClCreatePCTable("sanitizer-coverage-pc-table",
cl::desc("create a static PC table"),
cl::Hidden, cl::init(false));
static cl::opt<bool> ClInline8bitCounters(
"sanitizer-coverage-inline-8bit-counters",
cl::desc("increments 8-bit counter for every edge"), cl::Hidden,
cl::init(false));
static cl::opt<bool> ClInlineBoolFlag(
"sanitizer-coverage-inline-bool-flag",
cl::desc("sets a boolean flag for every edge"), cl::Hidden,
cl::init(false));
static cl::opt<bool> ClCMPTracing(
"sanitizer-coverage-trace-compares",
cl::desc("Tracing of CMP and similar instructions"), cl::Hidden,
cl::init(false));
static cl::opt<bool> ClDIVTracing("sanitizer-coverage-trace-divs",
cl::desc("Tracing of DIV instructions"),
cl::Hidden, cl::init(false));
static cl::opt<bool> ClGEPTracing("sanitizer-coverage-trace-geps",
cl::desc("Tracing of GEP instructions"),
cl::Hidden, cl::init(false));
static cl::opt<bool> ClPruneBlocks(
"sanitizer-coverage-prune-blocks",
cl::desc("Reduce the number of instrumented blocks"), cl::Hidden,
cl::init(true));
static cl::opt<bool> ClStackDepth("sanitizer-coverage-stack-depth",
cl::desc("max stack depth tracing"),
cl::Hidden, cl::init(false));
*/
namespace { namespace {
/*
SanitizerCoverageOptions getOptions(int LegacyCoverageLevel) {
SanitizerCoverageOptions Res;
switch (LegacyCoverageLevel) {
case 0:
Res.CoverageType = SanitizerCoverageOptions::SCK_None;
break;
case 1:
Res.CoverageType = SanitizerCoverageOptions::SCK_Function;
break;
case 2:
Res.CoverageType = SanitizerCoverageOptions::SCK_BB;
break;
case 3:
Res.CoverageType = SanitizerCoverageOptions::SCK_Edge;
break;
case 4:
Res.CoverageType = SanitizerCoverageOptions::SCK_Edge;
Res.IndirectCalls = true;
break;
}
return Res;
}
*/
SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) { SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) {
// Sets CoverageType and IndirectCalls. // Sets CoverageType and IndirectCalls.
@ -281,12 +135,14 @@ class ModuleSanitizerCoverage {
public: public:
ModuleSanitizerCoverage( ModuleSanitizerCoverage(
const SanitizerCoverageOptions &Options = SanitizerCoverageOptions(), const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()
const SpecialCaseList * Allowlist = nullptr, #if LLVM_MAJOR > 10
const SpecialCaseList * Blocklist = nullptr) ,
: Options(OverrideFromCL(Options)), const SpecialCaseList *Allowlist = nullptr,
Allowlist(Allowlist), const SpecialCaseList *Blocklist = nullptr
Blocklist(Blocklist) { #endif
)
: Options(OverrideFromCL(Options)) {
} }
@ -356,9 +212,6 @@ class ModuleSanitizerCoverage {
SanitizerCoverageOptions Options; SanitizerCoverageOptions Options;
const SpecialCaseList *Allowlist;
const SpecialCaseList *Blocklist;
uint32_t instr = 0; uint32_t instr = 0;
GlobalVariable *AFLMapPtr = NULL; GlobalVariable *AFLMapPtr = NULL;
ConstantInt * One = NULL; ConstantInt * One = NULL;
@ -370,27 +223,17 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass {
public: public:
ModuleSanitizerCoverageLegacyPass( ModuleSanitizerCoverageLegacyPass(
const SanitizerCoverageOptions &Options = SanitizerCoverageOptions(), const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()
#if LLVM_VERSION_MAJOR > 10
,
const std::vector<std::string> &AllowlistFiles = const std::vector<std::string> &AllowlistFiles =
std::vector<std::string>(), std::vector<std::string>(),
const std::vector<std::string> &BlocklistFiles = const std::vector<std::string> &BlocklistFiles =
std::vector<std::string>()) std::vector<std::string>()
#endif
)
: ModulePass(ID), Options(Options) { : ModulePass(ID), Options(Options) {
if (AllowlistFiles.size() > 0)
Allowlist = SpecialCaseList::createOrDie(AllowlistFiles
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
,
*vfs::getRealFileSystem()
#endif
);
if (BlocklistFiles.size() > 0)
Blocklist = SpecialCaseList::createOrDie(BlocklistFiles
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
,
*vfs::getRealFileSystem()
#endif
);
initializeModuleSanitizerCoverageLegacyPassPass( initializeModuleSanitizerCoverageLegacyPassPass(
*PassRegistry::getPassRegistry()); *PassRegistry::getPassRegistry());
@ -398,8 +241,12 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass {
bool runOnModule(Module &M) override { bool runOnModule(Module &M) override {
ModuleSanitizerCoverage ModuleSancov(Options, Allowlist.get(), ModuleSanitizerCoverage ModuleSancov(Options
Blocklist.get()); #if LLVM_MAJOR > 10
,
Allowlist.get(), Blocklist.get()
#endif
);
auto DTCallback = [this](Function &F) -> const DominatorTree * { auto DTCallback = [this](Function &F) -> const DominatorTree * {
return &this->getAnalysis<DominatorTreeWrapperPass>(F).getDomTree(); return &this->getAnalysis<DominatorTreeWrapperPass>(F).getDomTree();
@ -444,8 +291,12 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass {
PreservedAnalyses ModuleSanitizerCoveragePass::run(Module & M, PreservedAnalyses ModuleSanitizerCoveragePass::run(Module & M,
ModuleAnalysisManager &MAM) { ModuleAnalysisManager &MAM) {
ModuleSanitizerCoverage ModuleSancov(Options, Allowlist.get(), ModuleSanitizerCoverage ModuleSancov(Options
Blocklist.get()); #if LLVM_MAJOR > 10
,
Allowlist.get(), Blocklist.get()
#endif
);
auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
auto DTCallback = [&FAM](Function &F) -> const DominatorTree * { auto DTCallback = [&FAM](Function &F) -> const DominatorTree * {
@ -564,12 +415,6 @@ bool ModuleSanitizerCoverage::instrumentModule(
} }
if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) return false; if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) return false;
if (Allowlist &&
!Allowlist->inSection("coverage", "src", M.getSourceFileName()))
return false;
if (Blocklist &&
Blocklist->inSection("coverage", "src", M.getSourceFileName()))
return false;
C = &(M.getContext()); C = &(M.getContext());
DL = &M.getDataLayout(); DL = &M.getDataLayout();
CurModule = &M; CurModule = &M;
@ -842,9 +687,6 @@ void ModuleSanitizerCoverage::instrumentFunction(
if (F.hasPersonalityFn() && if (F.hasPersonalityFn() &&
isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
return; return;
if (Allowlist && !Allowlist->inSection("coverage", "fun", F.getName()))
return;
if (Blocklist && Blocklist->inSection("coverage", "fun", F.getName())) return;
if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge)
SplitAllCriticalEdges( SplitAllCriticalEdges(
F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests()); F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests());
@ -915,10 +757,18 @@ GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection(
*CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage, *CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage,
Constant::getNullValue(ArrayTy), "__sancov_gen_"); Constant::getNullValue(ArrayTy), "__sancov_gen_");
#if LLVM_VERSION_MAJOR > 12
if (TargetTriple.supportsCOMDAT() &&
(TargetTriple.isOSBinFormatELF() || !F.isInterposable()))
if (auto Comdat = getOrCreateFunctionComdat(F, TargetTriple))
Array->setComdat(Comdat);
#else
if (TargetTriple.supportsCOMDAT() && !F.isInterposable()) if (TargetTriple.supportsCOMDAT() && !F.isInterposable())
if (auto Comdat = if (auto Comdat =
GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId)) GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId))
Array->setComdat(Comdat); Array->setComdat(Comdat);
#endif
Array->setSection(getSectionName(Section)); Array->setSection(getSectionName(Section));
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0) #if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize())); Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize()));
@ -1354,12 +1204,20 @@ INITIALIZE_PASS_END(ModuleSanitizerCoverageLegacyPass, "sancov",
false) false)
ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass( ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass(
const SanitizerCoverageOptions &Options, const SanitizerCoverageOptions &Options
#if LLVM_MAJOR > 10
,
const std::vector<std::string> &AllowlistFiles, const std::vector<std::string> &AllowlistFiles,
const std::vector<std::string> &BlocklistFiles) { const std::vector<std::string> &BlocklistFiles
#endif
) {
return new ModuleSanitizerCoverageLegacyPass(Options, AllowlistFiles, return new ModuleSanitizerCoverageLegacyPass(Options
BlocklistFiles); #if LLVM_MAJOR > 10
,
AllowlistFiles, BlocklistFiles
#endif
);
} }

View File

@ -204,7 +204,7 @@ static void __afl_map_shm_fuzz() {
int shm_fd = -1; int shm_fd = -1;
/* create the shared memory segment as if it was a file */ /* create the shared memory segment as if it was a file */
shm_fd = shm_open(shm_file_path, O_RDWR, 0600); shm_fd = shm_open(shm_file_path, O_RDWR, DEFAULT_PERMISSION);
if (shm_fd == -1) { if (shm_fd == -1) {
fprintf(stderr, "shm_open() failed for fuzz\n"); fprintf(stderr, "shm_open() failed for fuzz\n");
@ -353,7 +353,7 @@ static void __afl_map_shm(void) {
unsigned char *shm_base = NULL; unsigned char *shm_base = NULL;
/* create the shared memory segment as if it was a file */ /* create the shared memory segment as if it was a file */
shm_fd = shm_open(shm_file_path, O_RDWR, 0600); shm_fd = shm_open(shm_file_path, O_RDWR, DEFAULT_PERMISSION);
if (shm_fd == -1) { if (shm_fd == -1) {
fprintf(stderr, "shm_open() failed\n"); fprintf(stderr, "shm_open() failed\n");
@ -528,7 +528,7 @@ static void __afl_map_shm(void) {
struct cmp_map *shm_base = NULL; struct cmp_map *shm_base = NULL;
/* create the shared memory segment as if it was a file */ /* create the shared memory segment as if it was a file */
shm_fd = shm_open(shm_file_path, O_RDWR, 0600); shm_fd = shm_open(shm_file_path, O_RDWR, DEFAULT_PERMISSION);
if (shm_fd == -1) { if (shm_fd == -1) {
perror("shm_open() failed\n"); perror("shm_open() failed\n");
@ -729,7 +729,7 @@ static void __afl_start_snapshots(void) {
static uint32_t counter = 0; static uint32_t counter = 0;
char fn[32]; char fn[32];
sprintf(fn, "%09u:forkserver", counter); sprintf(fn, "%09u:forkserver", counter);
s32 fd_doc = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); s32 fd_doc = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION);
if (fd_doc >= 0) { if (fd_doc >= 0) {
if (write(fd_doc, __afl_fuzz_ptr, *__afl_fuzz_len) != *__afl_fuzz_len) { if (write(fd_doc, __afl_fuzz_ptr, *__afl_fuzz_len) != *__afl_fuzz_len) {
@ -960,7 +960,7 @@ static void __afl_start_forkserver(void) {
static uint32_t counter = 0; static uint32_t counter = 0;
char fn[32]; char fn[32];
sprintf(fn, "%09u:forkserver", counter); sprintf(fn, "%09u:forkserver", counter);
s32 fd_doc = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); s32 fd_doc = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION);
if (fd_doc >= 0) { if (fd_doc >= 0) {
if (write(fd_doc, __afl_fuzz_ptr, *__afl_fuzz_len) != *__afl_fuzz_len) { if (write(fd_doc, __afl_fuzz_ptr, *__afl_fuzz_len) != *__afl_fuzz_len) {
@ -1676,6 +1676,12 @@ void __sanitizer_cov_trace_cmp16(uint128_t arg1, uint128_t arg2) {
} }
void __sanitizer_cov_trace_const_cmp16(uint128_t arg1, uint128_t arg2) {
__cmplog_ins_hook16(arg1, arg2, 0);
}
#endif #endif
void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) { void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) {
@ -1730,29 +1736,30 @@ __attribute__((weak)) void *__asan_region_is_poisoned(void *beg, size_t size) {
// to avoid to call it on .text addresses // to avoid to call it on .text addresses
static int area_is_valid(void *ptr, size_t len) { static int area_is_valid(void *ptr, size_t len) {
if (unlikely(__asan_region_is_poisoned(ptr, len))) { return 0; } if (unlikely(!ptr || __asan_region_is_poisoned(ptr, len))) { return 0; }
long r = syscall(__afl_dummy_fd[1], SYS_write, ptr, len); long r = syscall(SYS_write, __afl_dummy_fd[1], ptr, len);
if (unlikely(r <= 0 || r > len)) { // fail - maybe hitting asan boundary? if (r <= 0 || r > len) return 0;
char *p = (char *)ptr; // even if the write succeed this can be a false positive if we cross
long page_size = sysconf(_SC_PAGE_SIZE); // a page boundary. who knows why.
char *page = (char *)((uintptr_t)p & ~(page_size - 1)) + page_size;
if (page < p + len) { return 0; } // no isnt, return fail
len -= (p + len - page);
r = syscall(__afl_dummy_fd[1], SYS_write, p, len);
} char *p = (char *)ptr;
long page_size = sysconf(_SC_PAGE_SIZE);
char *page = (char *)((uintptr_t)p & ~(page_size - 1)) + page_size;
// partial writes - we return what was written. if (page > p + len) {
if (likely(r >= 0 && r <= len)) {
// no, not crossing a page boundary
return (int)r; return (int)r;
} else { } else {
return 0; // yes it crosses a boundary, hence we can only return the length of
// rest of the first page, we cannot detect if the next page is valid
// or not, neither by SYS_write nor msync() :-(
return (int)(page - p);
} }
@ -1773,12 +1780,14 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
*/ */
if (unlikely(!__afl_cmp_map)) return; if (unlikely(!__afl_cmp_map)) return;
// fprintf(stderr, "RTN1 %p %p\n", ptr1, ptr2);
int l1, l2; int l1, l2;
if ((l1 = area_is_valid(ptr1, 32)) <= 0 || if ((l1 = area_is_valid(ptr1, 32)) <= 0 ||
(l2 = area_is_valid(ptr2, 32)) <= 0) (l2 = area_is_valid(ptr2, 32)) <= 0)
return; return;
int len = MIN(l1, l2); int len = MIN(l1, l2);
// fprintf(stderr, "RTN2 %u\n", len);
uintptr_t k = (uintptr_t)__builtin_return_address(0); uintptr_t k = (uintptr_t)__builtin_return_address(0);
k = (k >> 4) ^ (k << 8); k = (k >> 4) ^ (k << 8);
k &= CMP_MAP_W - 1; k &= CMP_MAP_W - 1;
@ -1809,6 +1818,7 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
ptr1, len); ptr1, len);
__builtin_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v1, __builtin_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v1,
ptr2, len); ptr2, len);
// fprintf(stderr, "RTN3\n");
} }

View File

@ -60,7 +60,7 @@ bool isIgnoreFunction(const llvm::Function *F) {
"asan.", "asan.",
"llvm.", "llvm.",
"sancov.", "sancov.",
"__ubsan_", "__ubsan",
"ign.", "ign.",
"__afl", "__afl",
"_fini", "_fini",
@ -69,13 +69,16 @@ bool isIgnoreFunction(const llvm::Function *F) {
"__msan", "__msan",
"__cmplog", "__cmplog",
"__sancov", "__sancov",
"__san",
"__cxx_", "__cxx_",
"__decide_deferred",
"_GLOBAL", "_GLOBAL",
"_ZZN6__asan",
"_ZZN6__lsan",
"msan.", "msan.",
"LLVMFuzzerM", "LLVMFuzzerM",
"LLVMFuzzerC", "LLVMFuzzerC",
"LLVMFuzzerI", "LLVMFuzzerI",
"__decide_deferred",
"maybe_duplicate_stderr", "maybe_duplicate_stderr",
"discard_output", "discard_output",
"close_stdout", "close_stdout",
@ -91,6 +94,20 @@ bool isIgnoreFunction(const llvm::Function *F) {
} }
static const char *ignoreSubstringList[] = {
"__asan", "__msan", "__ubsan", "__lsan",
"__san", "__sanitize", "__cxx", "_GLOBAL__",
"DebugCounter", "DwarfDebug", "DebugLoc"
};
for (auto const &ignoreListFunc : ignoreSubstringList) {
if (F->getName().contains(ignoreListFunc)) { return true; }
}
return false; return false;
} }

View File

@ -1 +1 @@
d1ca56b84e ddc4a9748d

View File

@ -51,6 +51,7 @@ ssize_t write(int fd, const void *buf, size_t count) {
void *rtv = __builtin_return_address(0); void *rtv = __builtin_return_address(0);
QASAN_DEBUG("%14p: write(%d, %p, %zu)\n", rtv, fd, buf, count); QASAN_DEBUG("%14p: write(%d, %p, %zu)\n", rtv, fd, buf, count);
QASAN_LOAD(buf, count);
ssize_t r = __lq_libc_write(fd, buf, count); ssize_t r = __lq_libc_write(fd, buf, count);
QASAN_DEBUG("\t\t = %zd\n", r); QASAN_DEBUG("\t\t = %zd\n", r);
@ -63,6 +64,7 @@ ssize_t read(int fd, void *buf, size_t count) {
void *rtv = __builtin_return_address(0); void *rtv = __builtin_return_address(0);
QASAN_DEBUG("%14p: read(%d, %p, %zu)\n", rtv, fd, buf, count); QASAN_DEBUG("%14p: read(%d, %p, %zu)\n", rtv, fd, buf, count);
QASAN_STORE(buf, count);
ssize_t r = __lq_libc_read(fd, buf, count); ssize_t r = __lq_libc_read(fd, buf, count);
QASAN_DEBUG("\t\t = %zd\n", r); QASAN_DEBUG("\t\t = %zd\n", r);

View File

@ -159,6 +159,9 @@ size_t __libqasan_malloc_usable_size(void *ptr) {
char *p = ptr; char *p = ptr;
p -= sizeof(struct chunk_begin); p -= sizeof(struct chunk_begin);
// Validate that the chunk marker is readable (a crude check
// to verify that ptr is a valid malloc region before we dereference it)
QASAN_LOAD(p, sizeof(struct chunk_begin) - REDZONE_SIZE);
return ((struct chunk_begin *)p)->requested_size; return ((struct chunk_begin *)p)->requested_size;
} }
@ -225,6 +228,9 @@ void __libqasan_free(void *ptr) {
struct chunk_begin *p = ptr; struct chunk_begin *p = ptr;
p -= 1; p -= 1;
// Validate that the chunk marker is readable (a crude check
// to verify that ptr is a valid malloc region before we dereference it)
QASAN_LOAD(p, sizeof(struct chunk_begin) - REDZONE_SIZE);
size_t n = p->requested_size; size_t n = p->requested_size;
QASAN_STORE(ptr, n); QASAN_STORE(ptr, n);

@ -1 +1 @@
Subproject commit d1ca56b84e78f821406eef28d836918edfc8d610 Subproject commit 0fb212daab492411b3e323bc18a3074c1aecfd37

View File

@ -212,7 +212,7 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
unlink(path); /* Ignore errors */ unlink(path); /* Ignore errors */
ret = open(path, O_RDWR | O_CREAT | O_EXCL, 0600); ret = open(path, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (ret < 0) { PFATAL("Unable to create '%s'", path); } if (ret < 0) { PFATAL("Unable to create '%s'", path); }
@ -822,38 +822,7 @@ static void set_up_environment(void) {
if (qemu_mode) { if (qemu_mode) {
u8 *qemu_preload = getenv("QEMU_SET_ENV"); /* afl-qemu-trace takes care of converting AFL_PRELOAD. */
u8 *afl_preload = getenv("AFL_PRELOAD");
u8 *buf;
s32 i, afl_preload_size = strlen(afl_preload);
for (i = 0; i < afl_preload_size; ++i) {
if (afl_preload[i] == ',') {
PFATAL(
"Comma (',') is not allowed in AFL_PRELOAD when -Q is "
"specified!");
}
}
if (qemu_preload) {
buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
qemu_preload, afl_preload, afl_preload);
} else {
buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
afl_preload, afl_preload);
}
setenv("QEMU_SET_ENV", buf, 1);
ck_free(buf);
} else { } else {
@ -1079,31 +1048,6 @@ int main(int argc, char **argv_orig, char **envp) {
if (optind == argc || !in_file) { usage(argv[0]); } if (optind == argc || !in_file) { usage(argv[0]); }
if (qemu_mode && getenv("AFL_USE_QASAN")) {
u8 *preload = getenv("AFL_PRELOAD");
u8 *libqasan = get_libqasan_path(argv_orig[0]);
if (!preload) {
setenv("AFL_PRELOAD", libqasan, 0);
} else {
u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2);
strcpy(result, libqasan);
strcat(result, " ");
strcat(result, preload);
setenv("AFL_PRELOAD", result, 1);
ck_free(result);
}
ck_free(libqasan);
}
map_size = get_map_size(); map_size = get_map_size();
use_hex_offsets = !!get_afl_env("AFL_ANALYZE_HEX"); use_hex_offsets = !!get_afl_env("AFL_ANALYZE_HEX");

View File

@ -280,7 +280,7 @@ static void add_instrumentation(void) {
} }
outfd = open(modified_file, O_WRONLY | O_EXCL | O_CREAT, 0600); outfd = open(modified_file, O_WRONLY | O_EXCL | O_CREAT, DEFAULT_PERMISSION);
if (outfd < 0) { PFATAL("Unable to write to '%s'", modified_file); } if (outfd < 0) { PFATAL("Unable to write to '%s'", modified_file); }

View File

@ -590,6 +590,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0) #if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
#ifdef __ANDROID__ #ifdef __ANDROID__
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
instrument_mode != INSTRUMENT_LLVMNATIVE;
#else #else
if (have_instr_list) { if (have_instr_list) {
@ -599,6 +600,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
"-fsanitize-coverage-allow/denylist, you can use " "-fsanitize-coverage-allow/denylist, you can use "
"AFL_LLVM_ALLOWLIST/AFL_LLMV_DENYLIST instead.\n"); "AFL_LLVM_ALLOWLIST/AFL_LLMV_DENYLIST instead.\n");
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
instrument_mode = INSTRUMENT_LLVMNATIVE;
} else { } else {
@ -618,6 +620,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
"Using unoptimized trace-pc-guard, upgrade to llvm 10.0.1+ for " "Using unoptimized trace-pc-guard, upgrade to llvm 10.0.1+ for "
"enhanced version.\n"); "enhanced version.\n");
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
instrument_mode = INSTRUMENT_LLVMNATIVE;
#else #else
FATAL("pcguard instrumentation requires llvm 4.0.1+"); FATAL("pcguard instrumentation requires llvm 4.0.1+");
#endif #endif
@ -682,19 +685,49 @@ static void edit_params(u32 argc, char **argv, char **envp) {
/* Detect stray -v calls from ./configure scripts. */ /* Detect stray -v calls from ./configure scripts. */
u8 skip_next = 0;
while (--argc) { while (--argc) {
u8 *cur = *(++argv); u8 *cur = *(++argv);
if (skip_next) {
skip_next = 0;
continue;
}
if (!strncmp(cur, "--afl", 5)) continue; if (!strncmp(cur, "--afl", 5)) continue;
if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue; if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue;
if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue; if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue;
if (!strncmp(cur, "-fno-unroll", 11)) continue; if (!strncmp(cur, "-fno-unroll", 11)) continue;
if (strstr(cur, "afl-compiler-rt") || strstr(cur, "afl-llvm-rt")) continue; if (strstr(cur, "afl-compiler-rt") || strstr(cur, "afl-llvm-rt")) continue;
if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined")) if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined") ||
!strcmp(cur, "--no-undefined")) {
continue; continue;
if (!strncmp(cur, "-fsanitize=fuzzer-", strlen("-fsanitize=fuzzer-")) ||
!strncmp(cur, "-fsanitize-coverage", strlen("-fsanitize-coverage"))) { }
if (!strcmp(cur, "-z")) {
u8 *param = *(argv + 1);
if (!strcmp(param, "defs")) {
skip_next = 1;
continue;
}
}
if ((!strncmp(cur, "-fsanitize=fuzzer-", strlen("-fsanitize=fuzzer-")) ||
!strncmp(cur, "-fsanitize-coverage", strlen("-fsanitize-coverage"))) &&
(strncmp(cur, "sanitize-coverage-allow",
strlen("sanitize-coverage-allow")) &&
strncmp(cur, "sanitize-coverage-deny",
strlen("sanitize-coverage-deny")) &&
instrument_mode != INSTRUMENT_LLVMNATIVE)) {
if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); } if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); }
continue; continue;
@ -962,18 +995,24 @@ static void edit_params(u32 argc, char **argv, char **envp) {
switch (bit_mode) { switch (bit_mode) {
case 0: case 0:
cc_params[cc_par_cnt++] = if (!shared_linking)
alloc_printf("%s/afl-compiler-rt.o", obj_path); cc_params[cc_par_cnt++] =
alloc_printf("%s/afl-compiler-rt.o", obj_path);
if (lto_mode) if (lto_mode)
cc_params[cc_par_cnt++] = cc_params[cc_par_cnt++] =
alloc_printf("%s/afl-llvm-rt-lto.o", obj_path); alloc_printf("%s/afl-llvm-rt-lto.o", obj_path);
break; break;
case 32: case 32:
cc_params[cc_par_cnt++] = if (!shared_linking) {
alloc_printf("%s/afl-compiler-rt-32.o", obj_path);
if (access(cc_params[cc_par_cnt - 1], R_OK)) cc_params[cc_par_cnt++] =
FATAL("-m32 is not supported by your compiler"); alloc_printf("%s/afl-compiler-rt-32.o", obj_path);
if (access(cc_params[cc_par_cnt - 1], R_OK))
FATAL("-m32 is not supported by your compiler");
}
if (lto_mode) { if (lto_mode) {
cc_params[cc_par_cnt++] = cc_params[cc_par_cnt++] =
@ -986,10 +1025,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
break; break;
case 64: case 64:
cc_params[cc_par_cnt++] = if (!shared_linking) {
alloc_printf("%s/afl-compiler-rt-64.o", obj_path);
if (access(cc_params[cc_par_cnt - 1], R_OK)) cc_params[cc_par_cnt++] =
FATAL("-m64 is not supported by your compiler"); alloc_printf("%s/afl-compiler-rt-64.o", obj_path);
if (access(cc_params[cc_par_cnt - 1], R_OK))
FATAL("-m64 is not supported by your compiler");
}
if (lto_mode) { if (lto_mode) {
cc_params[cc_par_cnt++] = cc_params[cc_par_cnt++] =
@ -1009,12 +1053,12 @@ static void edit_params(u32 argc, char **argv, char **envp) {
alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path); alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path);
#endif #endif
#if defined(USEMMAP) && !defined(__HAIKU__)
cc_params[cc_par_cnt++] = "-lrt";
#endif
} }
#if defined(USEMMAP) && !defined(__HAIKU__)
cc_params[cc_par_cnt++] = "-lrt";
#endif
#endif #endif
cc_params[cc_par_cnt] = NULL; cc_params[cc_par_cnt] = NULL;
@ -1220,6 +1264,7 @@ int main(int argc, char **argv, char **envp) {
} else if (strcasecmp(ptr, "LLVMNATIVE") == 0 || } else if (strcasecmp(ptr, "LLVMNATIVE") == 0 ||
strcasecmp(ptr, "NATIVE") == 0 ||
strcasecmp(ptr, "LLVM-NATIVE") == 0) { strcasecmp(ptr, "LLVM-NATIVE") == 0) {
compiler_mode = LLVM; compiler_mode = LLVM;
@ -1632,8 +1677,8 @@ int main(int argc, char **argv, char **envp) {
"of afl-cc.\n\n"); "of afl-cc.\n\n");
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0) #if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
#define NATIVE_MSG \ #define NATIVE_MSG \
" NATIVE: use llvm's native PCGUARD instrumentation (less " \ " LLVM-NATIVE: use llvm's native PCGUARD instrumentation (less " \
"performant)\n" "performant)\n"
#else #else
#define NATIVE_MSG "" #define NATIVE_MSG ""

View File

@ -149,9 +149,14 @@ void argv_cpy_free(char **argv) {
char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
if (!unlikely(own_loc)) { FATAL("BUG: param own_loc is NULL"); } if (unlikely(getenv("AFL_QEMU_CUSTOM_BIN"))) {
u8 *tmp, *cp = NULL, *rsl, *own_copy; WARNF(
"AFL_QEMU_CUSTOM_BIN is enabled. "
"You must run your target under afl-qemu-trace on your own!");
return argv;
}
char **new_argv = ck_alloc(sizeof(char *) * (argc + 4)); char **new_argv = ck_alloc(sizeof(char *) * (argc + 4));
if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); } if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); }
@ -164,70 +169,8 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
/* Now we need to actually find the QEMU binary to put in argv[0]. */ /* Now we need to actually find the QEMU binary to put in argv[0]. */
tmp = getenv("AFL_PATH"); *target_path_p = new_argv[0] = find_afl_binary(own_loc, "afl-qemu-trace");
return new_argv;
if (tmp) {
cp = alloc_printf("%s/afl-qemu-trace", tmp);
if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); }
*target_path_p = new_argv[0] = cp;
return new_argv;
}
own_copy = ck_strdup(own_loc);
rsl = strrchr(own_copy, '/');
if (rsl) {
*rsl = 0;
cp = alloc_printf("%s/afl-qemu-trace", own_copy);
ck_free(own_copy);
if (!access(cp, X_OK)) {
*target_path_p = new_argv[0] = cp;
return new_argv;
}
} else {
ck_free(own_copy);
}
if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) {
if (cp) { ck_free(cp); }
*target_path_p = new_argv[0] = ck_strdup(BIN_PATH "/afl-qemu-trace");
return new_argv;
}
SAYF("\n" cLRD "[-] " cRST
"Oops, unable to find the 'afl-qemu-trace' binary. The binary must be "
"built\n"
" separately by following the instructions in "
"qemu_mode/README.md. "
"If you\n"
" already have the binary installed, you may need to specify "
"AFL_PATH in the\n"
" environment.\n\n"
" Of course, even without QEMU, afl-fuzz can still work with "
"binaries that are\n"
" instrumented at compile time with afl-gcc. It is also possible to "
"use it as a\n"
" traditional non-instrumented fuzzer by specifying '-n' in the "
"command "
"line.\n");
FATAL("Failed to locate 'afl-qemu-trace'.");
} }
@ -235,10 +178,6 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
if (!unlikely(own_loc)) { FATAL("BUG: param own_loc is NULL"); }
u8 *tmp, *cp = NULL, *rsl, *own_copy;
char **new_argv = ck_alloc(sizeof(char *) * (argc + 3)); char **new_argv = ck_alloc(sizeof(char *) * (argc + 3));
if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); } if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); }
@ -249,152 +188,10 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
/* Now we need to actually find the QEMU binary to put in argv[0]. */ /* Now we need to actually find the QEMU binary to put in argv[0]. */
tmp = getenv("AFL_PATH"); u8 *tmp = find_afl_binary(own_loc, "afl-qemu-trace");
ck_free(tmp);
if (tmp) { *target_path_p = new_argv[0] = find_afl_binary(own_loc, "afl-wine-trace");
return new_argv;
cp = alloc_printf("%s/afl-qemu-trace", tmp);
if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); }
ck_free(cp);
cp = alloc_printf("%s/afl-wine-trace", tmp);
if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); }
*target_path_p = new_argv[0] = cp;
return new_argv;
}
own_copy = ck_strdup(own_loc);
rsl = strrchr(own_copy, '/');
if (rsl) {
*rsl = 0;
cp = alloc_printf("%s/afl-qemu-trace", own_copy);
if (cp && !access(cp, X_OK)) {
ck_free(cp);
cp = alloc_printf("%s/afl-wine-trace", own_copy);
if (!access(cp, X_OK)) {
*target_path_p = new_argv[0] = cp;
return new_argv;
}
}
ck_free(own_copy);
} else {
ck_free(own_copy);
}
u8 *ncp = BIN_PATH "/afl-qemu-trace";
if (!access(ncp, X_OK)) {
ncp = BIN_PATH "/afl-wine-trace";
if (!access(ncp, X_OK)) {
*target_path_p = new_argv[0] = ck_strdup(ncp);
return new_argv;
}
}
SAYF("\n" cLRD "[-] " cRST
"Oops, unable to find the '%s' binary. The binary must be "
"built\n"
" separately by following the instructions in "
"qemu_mode/README.md. "
"If you\n"
" already have the binary installed, you may need to specify "
"AFL_PATH in the\n"
" environment.\n\n"
" Of course, even without QEMU, afl-fuzz can still work with "
"binaries that are\n"
" instrumented at compile time with afl-gcc. It is also possible to "
"use it as a\n"
" traditional non-instrumented fuzzer by specifying '-n' in the "
"command "
"line.\n",
ncp);
FATAL("Failed to locate '%s'.", ncp);
}
/* Get libqasan path. */
u8 *get_libqasan_path(u8 *own_loc) {
if (!unlikely(own_loc)) { FATAL("BUG: param own_loc is NULL"); }
u8 *tmp, *cp = NULL, *rsl, *own_copy;
tmp = getenv("AFL_PATH");
if (tmp) {
cp = alloc_printf("%s/libqasan.so", tmp);
if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); }
return cp;
}
own_copy = ck_strdup(own_loc);
rsl = strrchr(own_copy, '/');
if (rsl) {
*rsl = 0;
cp = alloc_printf("%s/libqasan.so", own_copy);
ck_free(own_copy);
if (!access(cp, X_OK)) { return cp; }
} else {
ck_free(own_copy);
}
if (!access(AFL_PATH "/libqasan.so", X_OK)) {
if (cp) { ck_free(cp); }
return ck_strdup(AFL_PATH "/libqasan.so");
}
SAYF("\n" cLRD "[-] " cRST
"Oops, unable to find the 'libqasan.so' binary. The binary must be "
"built\n"
" separately by following the instructions in "
"qemu_mode/libqasan/README.md. "
"If you\n"
" already have the binary installed, you may need to specify "
"AFL_PATH in the\n"
" environment.\n");
FATAL("Failed to locate 'libqasan.so'.");
} }
@ -488,6 +285,70 @@ u8 *find_binary(u8 *fname) {
} }
u8 *find_afl_binary(u8 *own_loc, u8 *fname) {
u8 *afl_path = NULL, *target_path, *own_copy;
if ((afl_path = getenv("AFL_PATH"))) {
target_path = alloc_printf("%s/%s", afl_path, fname);
if (!access(target_path, X_OK)) {
return target_path;
} else {
ck_free(target_path);
}
}
if (own_loc) {
own_copy = ck_strdup(own_loc);
u8 *rsl = strrchr(own_copy, '/');
if (rsl) {
*rsl = 0;
target_path = alloc_printf("%s/%s", own_copy, fname);
ck_free(own_copy);
if (!access(target_path, X_OK)) {
return target_path;
} else {
ck_free(target_path);
}
} else {
ck_free(own_copy);
}
}
target_path = alloc_printf("%s/%s", BIN_PATH, fname);
if (!access(target_path, X_OK)) {
return target_path;
} else {
ck_free(target_path);
}
return find_binary(fname);
}
/* Parses the kill signal environment variable, FATALs on error. /* Parses the kill signal environment variable, FATALs on error.
If the env is not set, sets the env to default_signal for the signal handlers If the env is not set, sets the env to default_signal for the signal handlers
and returns the default_signal. */ and returns the default_signal. */
@ -757,6 +618,98 @@ char *get_afl_env(char *env) {
} }
bool extract_and_set_env(u8 *env_str) {
if (!env_str) { return false; }
bool ret = false; // return false by default
u8 *p = ck_strdup(env_str);
u8 *end = p + strlen((char *)p);
u8 *rest = p;
u8 closing_sym = ' ';
u8 c;
size_t num_pairs = 0;
while (rest < end) {
while (*rest == ' ') {
rest++;
}
if (rest + 1 >= end) break;
u8 *key = rest;
// env variable names may not start with numbers or '='
if (*key == '=' || (*key >= '0' && *key <= '9')) { goto free_and_return; }
while (rest < end && *rest != '=' && *rest != ' ') {
c = *rest;
// lowercase is bad but we may still allow it
if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') &&
(c < '0' || c > '9') && c != '_') {
goto free_and_return;
}
rest++;
}
if (*rest != '=') { goto free_and_return; }
*rest = '\0'; // done with variable name
rest += 1;
if (rest >= end || *rest == ' ') { goto free_and_return; }
u8 *val = rest;
if (*val == '\'' || *val == '"') {
closing_sym = *val;
val += 1;
rest += 1;
if (rest >= end) { goto free_and_return; }
} else {
closing_sym = ' ';
}
while (rest < end && *rest != closing_sym) {
rest++;
}
if (closing_sym != ' ' && *rest != closing_sym) { goto free_and_return; }
*rest = '\0'; // done with variable value
rest += 1;
if (rest < end && *rest != ' ') { goto free_and_return; }
num_pairs++;
setenv(key, val, 1);
}
if (num_pairs) { ret = true; }
free_and_return:
ck_free(p);
return ret;
}
/* Read mask bitmap from file. This is for the -B option. */ /* Read mask bitmap from file. This is for the -B option. */
void read_bitmap(u8 *fname, u8 *map, size_t len) { void read_bitmap(u8 *fname, u8 *map, size_t len) {
@ -1123,7 +1076,7 @@ u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) {
/* Reads the map size from ENV */ /* Reads the map size from ENV */
u32 get_map_size(void) { u32 get_map_size(void) {
uint32_t map_size = 8000000; // a very large default map uint32_t map_size = DEFAULT_SHMEM_SIZE;
char * ptr; char * ptr;
if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) { if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) {
@ -1151,7 +1104,7 @@ FILE *create_ffile(u8 *fn) {
s32 fd; s32 fd;
FILE *f; FILE *f;
fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION);
if (fd < 0) { PFATAL("Unable to create '%s'", fn); } if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
@ -1169,7 +1122,7 @@ s32 create_file(u8 *fn) {
s32 fd; s32 fd;
fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION);
if (fd < 0) { PFATAL("Unable to create '%s'", fn); } if (fd < 0) { PFATAL("Unable to create '%s'", fn); }

View File

@ -809,7 +809,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
"have a\n" "have a\n"
" restrictive memory limit configured, this is expected; please " " restrictive memory limit configured, this is expected; please "
"read\n" "read\n"
" %s/notes_for_asan.md for help.\n", " %s/notes_for_asan.md for help and run with '-m 0'.\n",
doc_path); doc_path);
} else if (!fsrv->mem_limit) { } else if (!fsrv->mem_limit) {
@ -817,18 +817,21 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
SAYF("\n" cLRD "[-] " cRST SAYF("\n" cLRD "[-] " cRST
"Whoops, the target binary crashed suddenly, " "Whoops, the target binary crashed suddenly, "
"before receiving any input\n" "before receiving any input\n"
" from the fuzzer! There are several probable explanations:\n\n" " from the fuzzer! You can try the following:\n\n"
" - The target binary requires a large map and crashes before " " - The target binary crashes because necessary runtime "
"reporting.\n" "conditions it needs\n"
" Set a high value (e.g. AFL_MAP_SIZE=8000000) or use " " are not met. Try to:\n"
"AFL_DEBUG=1 to see the\n" " 1. Run again with AFL_DEBUG=1 set and check the output of "
" message from the target binary\n\n" "the target\n"
" binary for clues.\n"
" 2. Run again with AFL_DEBUG=1 and 'ulimit -c unlimited' and "
"analyze the\n"
" generated core dump.\n\n"
" - The binary is just buggy and explodes entirely on its own. " " - Possibly the target requires a huge coverage map and has "
"If so, you\n" "CTORS.\n"
" need to fix the underlying problem or find a better " " Retry with setting AFL_MAP_SIZE=10000000.\n\n"
"replacement.\n\n"
MSG_FORK_ON_APPLE MSG_FORK_ON_APPLE
@ -844,13 +847,17 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
SAYF("\n" cLRD "[-] " cRST SAYF("\n" cLRD "[-] " cRST
"Whoops, the target binary crashed suddenly, " "Whoops, the target binary crashed suddenly, "
"before receiving any input\n" "before receiving any input\n"
" from the fuzzer! There are several probable explanations:\n\n" " from the fuzzer! You can try the following:\n\n"
" - The target binary requires a large map and crashes before " " - The target binary crashes because necessary runtime "
"reporting.\n" "conditions it needs\n"
" Set a high value (e.g. AFL_MAP_SIZE=8000000) or use " " are not met. Try to:\n"
"AFL_DEBUG=1 to see the\n" " 1. Run again with AFL_DEBUG=1 set and check the output of "
" message from the target binary\n\n" "the target\n"
" binary for clues.\n"
" 2. Run again with AFL_DEBUG=1 and 'ulimit -c unlimited' and "
"analyze the\n"
" generated core dump.\n\n"
" - The current memory limit (%s) is too restrictive, causing " " - The current memory limit (%s) is too restrictive, causing "
"the\n" "the\n"
@ -868,13 +875,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
" estimate the required amount of virtual memory for the " " estimate the required amount of virtual memory for the "
"binary.\n\n" "binary.\n\n"
" - The binary is just buggy and explodes entirely on its own. "
"If so, you\n"
" need to fix the underlying problem or find a better "
"replacement.\n\n"
MSG_FORK_ON_APPLE MSG_FORK_ON_APPLE
" - Possibly the target requires a huge coverage map and has "
"CTORS.\n"
" Retry with setting AFL_MAP_SIZE=10000000.\n\n"
" - Less likely, there is a horrible bug in the fuzzer. If other " " - Less likely, there is a horrible bug in the fuzzer. If other "
"options\n" "options\n"
" fail, poke <afl-users@googlegroups.com> for troubleshooting " " fail, poke <afl-users@googlegroups.com> for troubleshooting "
@ -903,7 +909,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
"with ASAN and\n" "with ASAN and\n"
" you have a restrictive memory limit configured, this is " " you have a restrictive memory limit configured, this is "
"expected; please\n" "expected; please\n"
" read %s/notes_for_asan.md for help.\n", " read %s/notes_for_asan.md for help and run with '-m 0'.\n",
doc_path); doc_path);
} else if (!fsrv->mem_limit) { } else if (!fsrv->mem_limit) {
@ -911,10 +917,22 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
SAYF("\n" cLRD "[-] " cRST SAYF("\n" cLRD "[-] " cRST
"Hmm, looks like the target binary terminated before we could complete" "Hmm, looks like the target binary terminated before we could complete"
" a\n" " a\n"
"handshake with the injected code.\n" "handshake with the injected code. You can try the following:\n\n"
"Most likely the target has a huge coverage map, retry with setting"
" the\n" " - The target binary crashes because necessary runtime conditions "
"environment variable AFL_MAP_SIZE=8000000\n" "it needs\n"
" are not met. Try to:\n"
" 1. Run again with AFL_DEBUG=1 set and check the output of the "
"target\n"
" binary for clues.\n"
" 2. Run again with AFL_DEBUG=1 and 'ulimit -c unlimited' and "
"analyze the\n"
" generated core dump.\n\n"
" - Possibly the target requires a huge coverage map and has "
"CTORS.\n"
" Retry with setting AFL_MAP_SIZE=10000000.\n\n"
"Otherwise there is a horrible bug in the fuzzer.\n" "Otherwise there is a horrible bug in the fuzzer.\n"
"Poke <afl-users@googlegroups.com> for troubleshooting tips.\n"); "Poke <afl-users@googlegroups.com> for troubleshooting tips.\n");
@ -926,14 +944,23 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
"\n" cLRD "[-] " cRST "\n" cLRD "[-] " cRST
"Hmm, looks like the target binary terminated " "Hmm, looks like the target binary terminated "
"before we could complete a\n" "before we could complete a\n"
" handshake with the injected code. There are %s probable " " handshake with the injected code. You can try the following:\n\n"
"explanations:\n\n"
"%s" "%s"
" - Most likely the target has a huge coverage map, retry with " " - The target binary crashes because necessary runtime conditions "
"setting the\n" "it needs\n"
" environment variable AFL_MAP_SIZE=8000000\n\n" " are not met. Try to:\n"
" 1. Run again with AFL_DEBUG=1 set and check the output of the "
"target\n"
" binary for clues.\n"
" 2. Run again with AFL_DEBUG=1 and 'ulimit -c unlimited' and "
"analyze the\n"
" generated core dump.\n\n"
" - Possibly the target requires a huge coverage map and has "
"CTORS.\n"
" Retry with setting AFL_MAP_SIZE=10000000.\n\n"
" - The current memory limit (%s) is too restrictive, causing an " " - The current memory limit (%s) is too restrictive, causing an "
"OOM\n" "OOM\n"
@ -958,7 +985,6 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
"options\n" "options\n"
" fail, poke <afl-users@googlegroups.com> for troubleshooting " " fail, poke <afl-users@googlegroups.com> for troubleshooting "
"tips.\n", "tips.\n",
getenv(DEFER_ENV_VAR) ? "three" : "two",
getenv(DEFER_ENV_VAR) getenv(DEFER_ENV_VAR)
? " - You are using deferred forkserver, but __AFL_INIT() is " ? " - You are using deferred forkserver, but __AFL_INIT() is "
"never\n" "never\n"
@ -1038,12 +1064,14 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
if (unlikely(fsrv->no_unlink)) { if (unlikely(fsrv->no_unlink)) {
fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_TRUNC, 0600); fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_TRUNC,
DEFAULT_PERMISSION);
} else { } else {
unlink(fsrv->out_file); /* Ignore errors. */ unlink(fsrv->out_file); /* Ignore errors. */
fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_EXCL, 0600); fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_EXCL,
DEFAULT_PERMISSION);
} }

View File

@ -42,7 +42,7 @@ void write_bitmap(afl_state_t *afl) {
afl->bitmap_changed = 0; afl->bitmap_changed = 0;
snprintf(fname, PATH_MAX, "%s/fuzz_bitmap", afl->out_dir); snprintf(fname, PATH_MAX, "%s/fuzz_bitmap", afl->out_dir);
fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0600); fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION);
if (fd < 0) { PFATAL("Unable to open '%s'", fname); } if (fd < 0) { PFATAL("Unable to open '%s'", fname); }
@ -407,7 +407,7 @@ static void write_crash_readme(afl_state_t *afl) {
sprintf(fn, "%s/crashes/README.txt", afl->out_dir); sprintf(fn, "%s/crashes/README.txt", afl->out_dir);
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
/* Do not die on errors here - that would be impolite. */ /* Do not die on errors here - that would be impolite. */
@ -509,7 +509,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_paths); alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_paths);
#endif /* ^!SIMPLE_FILES */ #endif /* ^!SIMPLE_FILES */
fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600); fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); } if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); }
ck_write(fd, mem, len, queue_fn); ck_write(fd, mem, len, queue_fn);
close(fd); close(fd);
@ -783,7 +783,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
/* If we're here, we apparently want to save the crash or hang /* If we're here, we apparently want to save the crash or hang
test case, too. */ test case, too. */
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn); } if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn); }
ck_write(fd, mem, len, fn); ck_write(fd, mem, len, fn);
close(fd); close(fd);

View File

@ -731,7 +731,7 @@ void save_auto(afl_state_t *afl) {
alloc_printf("%s/queue/.state/auto_extras/auto_%06u", afl->out_dir, i); alloc_printf("%s/queue/.state/auto_extras/auto_%06u", afl->out_dir, i);
s32 fd; s32 fd;
fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION);
if (fd < 0) { PFATAL("Unable to create '%s'", fn); } if (fd < 0) { PFATAL("Unable to create '%s'", fn); }

View File

@ -152,7 +152,8 @@ void bind_to_free_cpu(afl_state_t *afl) {
do { do {
if ((lockfd = open(lockfile, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0) { if ((lockfd = open(lockfile, O_RDWR | O_CREAT | O_EXCL,
DEFAULT_PERMISSION)) < 0) {
if (first) { if (first) {
@ -1219,7 +1220,7 @@ static void link_or_copy(u8 *old_path, u8 *new_path) {
sfd = open(old_path, O_RDONLY); sfd = open(old_path, O_RDONLY);
if (sfd < 0) { PFATAL("Unable to open '%s'", old_path); } if (sfd < 0) { PFATAL("Unable to open '%s'", old_path); }
dfd = open(new_path, O_WRONLY | O_CREAT | O_EXCL, 0600); dfd = open(new_path, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (dfd < 0) { PFATAL("Unable to create '%s'", new_path); } if (dfd < 0) { PFATAL("Unable to create '%s'", new_path); }
tmp = ck_alloc(64 * 1024); tmp = ck_alloc(64 * 1024);
@ -1812,9 +1813,13 @@ static void handle_existing_out_dir(afl_state_t *afl) {
} }
fn = alloc_printf("%s/plot_data", afl->out_dir); if (!afl->in_place_resume) {
if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
ck_free(fn); fn = alloc_printf("%s/plot_data", afl->out_dir);
if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
ck_free(fn);
}
fn = alloc_printf("%s/cmdline", afl->out_dir); fn = alloc_printf("%s/cmdline", afl->out_dir);
if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; } if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
@ -2008,17 +2013,35 @@ void setup_dirs_fds(afl_state_t *afl) {
/* Gnuplot output file. */ /* Gnuplot output file. */
tmp = alloc_printf("%s/plot_data", afl->out_dir); tmp = alloc_printf("%s/plot_data", afl->out_dir);
int fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, 0600);
if (fd < 0) { PFATAL("Unable to create '%s'", tmp); }
ck_free(tmp);
afl->fsrv.plot_file = fdopen(fd, "w"); if (!afl->in_place_resume) {
if (!afl->fsrv.plot_file) { PFATAL("fdopen() failed"); }
int fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (fd < 0) { PFATAL("Unable to create '%s'", tmp); }
ck_free(tmp);
afl->fsrv.plot_file = fdopen(fd, "w");
if (!afl->fsrv.plot_file) { PFATAL("fdopen() failed"); }
fprintf(
afl->fsrv.plot_file,
"# unix_time, cycles_done, cur_path, paths_total, "
"pending_total, pending_favs, map_size, unique_crashes, "
"unique_hangs, max_depth, execs_per_sec, total_execs, edges_found\n");
} else {
int fd = open(tmp, O_WRONLY | O_CREAT, DEFAULT_PERMISSION);
if (fd < 0) { PFATAL("Unable to create '%s'", tmp); }
ck_free(tmp);
afl->fsrv.plot_file = fdopen(fd, "w");
if (!afl->fsrv.plot_file) { PFATAL("fdopen() failed"); }
fseek(afl->fsrv.plot_file, 0, SEEK_END);
}
fprintf(afl->fsrv.plot_file,
"# unix_time, cycles_done, cur_path, paths_total, "
"pending_total, pending_favs, map_size, unique_crashes, "
"unique_hangs, max_depth, execs_per_sec, total_execs, edges_found\n");
fflush(afl->fsrv.plot_file); fflush(afl->fsrv.plot_file);
/* ignore errors */ /* ignore errors */
@ -2035,7 +2058,7 @@ void setup_cmdline_file(afl_state_t *afl, char **argv) {
/* Store the command line to reproduce our findings */ /* Store the command line to reproduce our findings */
tmp = alloc_printf("%s/cmdline", afl->out_dir); tmp = alloc_printf("%s/cmdline", afl->out_dir);
fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, 0600); fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (fd < 0) { PFATAL("Unable to create '%s'", tmp); } if (fd < 0) { PFATAL("Unable to create '%s'", tmp); }
ck_free(tmp); ck_free(tmp);
@ -2070,7 +2093,8 @@ void setup_stdio_file(afl_state_t *afl) {
unlink(afl->fsrv.out_file); /* Ignore errors */ unlink(afl->fsrv.out_file); /* Ignore errors */
afl->fsrv.out_fd = open(afl->fsrv.out_file, O_RDWR | O_CREAT | O_EXCL, 0600); afl->fsrv.out_fd =
open(afl->fsrv.out_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (afl->fsrv.out_fd < 0) { if (afl->fsrv.out_fd < 0) {
@ -2592,6 +2616,7 @@ void check_binary(afl_state_t *afl, u8 *fname) {
} }
if (afl->afl_env.afl_skip_bin_check || afl->use_wine || afl->unicorn_mode || if (afl->afl_env.afl_skip_bin_check || afl->use_wine || afl->unicorn_mode ||
(afl->fsrv.qemu_mode && getenv("AFL_QEMU_CUSTOM_BIN")) ||
afl->non_instrumented_mode) { afl->non_instrumented_mode) {
return; return;

View File

@ -465,7 +465,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
unlink(q->fname); /* ignore errors */ unlink(q->fname); /* ignore errors */
fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, 0600); fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); } if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); }

View File

@ -5119,14 +5119,23 @@ pacemaker_fuzzing:
/* Update afl->pending_not_fuzzed count if we made it through the /* Update afl->pending_not_fuzzed count if we made it through the
calibration cycle and have not seen this entry before. */ calibration cycle and have not seen this entry before. */
/*
// TODO FIXME: I think we need this plus need an -L -1 check
if (!afl->stop_soon && !afl->queue_cur->cal_failed &&
(afl->queue_cur->was_fuzzed == 0 || afl->queue_cur->fuzz_level == 0)
&& !afl->queue_cur->disabled) {
// if (!afl->stop_soon && !afl->queue_cur->cal_failed && if (!afl->queue_cur->was_fuzzed) {
// !afl->queue_cur->was_fuzzed) {
// afl->queue_cur->was_fuzzed = 1; --afl->pending_not_fuzzed;
// --afl->pending_not_fuzzed; afl->queue_cur->was_fuzzed = 1;
// if (afl->queue_cur->favored) --afl->pending_favored; if (afl->queue_cur->favored) { --afl->pending_favored; }
// }
}
}
*/
orig_in = NULL; orig_in = NULL;

View File

@ -249,7 +249,7 @@ void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) {
snprintf(fn, PATH_MAX, "%s/queue/.state/deterministic_done/%s", afl->out_dir, snprintf(fn, PATH_MAX, "%s/queue/.state/deterministic_done/%s", afl->out_dir,
strrchr(q->fname, '/') + 1); strrchr(q->fname, '/') + 1);
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (fd < 0) { PFATAL("Unable to create '%s'", fn); } if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
close(fd); close(fd);
@ -272,7 +272,7 @@ void mark_as_variable(afl_state_t *afl, struct queue_entry *q) {
if (symlink(ldest, fn)) { if (symlink(ldest, fn)) {
s32 fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); s32 fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (fd < 0) { PFATAL("Unable to create '%s'", fn); } if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
close(fd); close(fd);
@ -300,7 +300,7 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
s32 fd; s32 fd;
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (fd < 0) { PFATAL("Unable to create '%s'", fn); } if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
close(fd); close(fd);
@ -680,13 +680,17 @@ void cull_queue(afl_state_t *afl) {
} }
afl->top_rated[i]->favored = 1; if (!afl->top_rated[i]->favored) {
++afl->queued_favored;
if (afl->top_rated[i]->fuzz_level == 0 || afl->top_rated[i]->favored = 1;
!afl->top_rated[i]->was_fuzzed) { ++afl->queued_favored;
++afl->pending_favored; if (afl->top_rated[i]->fuzz_level == 0 ||
!afl->top_rated[i]->was_fuzzed) {
++afl->pending_favored;
}
} }

View File

@ -83,7 +83,8 @@ write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
afl->document_counter++, afl->document_counter++,
describe_op(afl, 0, NAME_MAX - strlen("000000000:"))); describe_op(afl, 0, NAME_MAX - strlen("000000000:")));
if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0) { if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION)) >=
0) {
if (write(doc_fd, mem, len) != len) if (write(doc_fd, mem, len) != len)
PFATAL("write to mutation file failed: %s", fn); PFATAL("write to mutation file failed: %s", fn);
@ -247,12 +248,14 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at,
if (unlikely(afl->no_unlink)) { if (unlikely(afl->no_unlink)) {
fd = open(afl->fsrv.out_file, O_WRONLY | O_CREAT | O_TRUNC, 0600); fd = open(afl->fsrv.out_file, O_WRONLY | O_CREAT | O_TRUNC,
DEFAULT_PERMISSION);
} else { } else {
unlink(afl->fsrv.out_file); /* Ignore errors. */ unlink(afl->fsrv.out_file); /* Ignore errors. */
fd = open(afl->fsrv.out_file, O_WRONLY | O_CREAT | O_EXCL, 0600); fd = open(afl->fsrv.out_file, O_WRONLY | O_CREAT | O_EXCL,
DEFAULT_PERMISSION);
} }
@ -564,7 +567,8 @@ void sync_fuzzers(afl_state_t *afl) {
/* document the attempt to sync to this instance */ /* document the attempt to sync to this instance */
sprintf(qd_synced_path, "%s/.synced/%s.last", afl->out_dir, sd_ent->d_name); sprintf(qd_synced_path, "%s/.synced/%s.last", afl->out_dir, sd_ent->d_name);
id_fd = open(qd_synced_path, O_RDWR | O_CREAT | O_TRUNC, 0600); id_fd =
open(qd_synced_path, O_RDWR | O_CREAT | O_TRUNC, DEFAULT_PERMISSION);
if (id_fd >= 0) close(id_fd); if (id_fd >= 0) close(id_fd);
/* Skip anything that doesn't have a queue/ subdirectory. */ /* Skip anything that doesn't have a queue/ subdirectory. */
@ -587,7 +591,7 @@ void sync_fuzzers(afl_state_t *afl) {
sprintf(qd_synced_path, "%s/.synced/%s", afl->out_dir, sd_ent->d_name); sprintf(qd_synced_path, "%s/.synced/%s", afl->out_dir, sd_ent->d_name);
id_fd = open(qd_synced_path, O_RDWR | O_CREAT, 0600); id_fd = open(qd_synced_path, O_RDWR | O_CREAT, DEFAULT_PERMISSION);
if (id_fd < 0) { PFATAL("Unable to create '%s'", qd_synced_path); } if (id_fd < 0) { PFATAL("Unable to create '%s'", qd_synced_path); }
@ -851,7 +855,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
if (unlikely(afl->no_unlink)) { if (unlikely(afl->no_unlink)) {
fd = open(q->fname, O_WRONLY | O_CREAT | O_TRUNC, 0600); fd = open(q->fname, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION);
if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); } if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); }
@ -866,7 +870,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
} else { } else {
unlink(q->fname); /* ignore errors */ unlink(q->fname); /* ignore errors */
fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, 0600); fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); } if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); }

View File

@ -433,6 +433,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_kill_signal = afl->afl_env.afl_kill_signal =
(u8 *)get_afl_env(afl_environment_variables[i]); (u8 *)get_afl_env(afl_environment_variables[i]);
} else if (!strncmp(env, "AFL_TARGET_ENV",
afl_environment_variable_len)) {
afl->afl_env.afl_target_env =
(u8 *)get_afl_env(afl_environment_variables[i]);
} }
} else { } else {

View File

@ -391,10 +391,11 @@ void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
fprintf(afl->fsrv.plot_file, fprintf(afl->fsrv.plot_file,
"%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu, " "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu, "
"%u\n", "%u\n",
get_cur_time() / 1000, afl->queue_cycle - 1, afl->current_entry, (afl->prev_run_time + get_cur_time() - afl->start_time),
afl->queued_paths, afl->pending_not_fuzzed, afl->pending_favored, afl->queue_cycle - 1, afl->current_entry, afl->queued_paths,
bitmap_cvg, afl->unique_crashes, afl->unique_hangs, afl->max_depth, afl->pending_not_fuzzed, afl->pending_favored, bitmap_cvg,
eps, afl->plot_prev_ed, t_bytes); /* ignore errors */ afl->unique_crashes, afl->unique_hangs, afl->max_depth, eps,
afl->plot_prev_ed, t_bytes); /* ignore errors */
fflush(afl->fsrv.plot_file); fflush(afl->fsrv.plot_file);

View File

@ -223,6 +223,7 @@ static void usage(u8 *argv0, int more_help) {
"AFL_PYTHON_MODULE: mutate and trim inputs with the specified Python module\n" "AFL_PYTHON_MODULE: mutate and trim inputs with the specified Python module\n"
"AFL_QUIET: suppress forkserver status messages\n" "AFL_QUIET: suppress forkserver status messages\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
"AFL_TARGET_ENV: pass extra environment variables to target\n"
"AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n" "AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n"
"AFL_SKIP_BIN_CHECK: skip the check, if the target is an executable\n" "AFL_SKIP_BIN_CHECK: skip the check, if the target is an executable\n"
"AFL_SKIP_CPUFREQ: do not warn about variable cpu clocking\n" "AFL_SKIP_CPUFREQ: do not warn about variable cpu clocking\n"
@ -1022,32 +1023,6 @@ int main(int argc, char **argv_orig, char **envp) {
} }
if (afl->fsrv.qemu_mode && getenv("AFL_USE_QASAN")) {
u8 *preload = getenv("AFL_PRELOAD");
u8 *libqasan = get_libqasan_path(argv_orig[0]);
if (!preload) {
setenv("AFL_PRELOAD", libqasan, 0);
} else {
u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2);
strcpy(result, libqasan);
strcat(result, " ");
strcat(result, preload);
setenv("AFL_PRELOAD", result, 1);
ck_free(result);
}
afl->afl_env.afl_preload = (u8 *)getenv("AFL_PRELOAD");
ck_free(libqasan);
}
if (afl->fsrv.mem_limit && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260; if (afl->fsrv.mem_limit && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260;
OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" " OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" "
@ -1312,38 +1287,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->fsrv.qemu_mode) { if (afl->fsrv.qemu_mode) {
u8 *qemu_preload = getenv("QEMU_SET_ENV"); /* afl-qemu-trace takes care of converting AFL_PRELOAD. */
u8 *afl_preload = getenv("AFL_PRELOAD");
u8 *buf;
s32 j, afl_preload_size = strlen(afl_preload);
for (j = 0; j < afl_preload_size; ++j) {
if (afl_preload[j] == ',') {
PFATAL(
"Comma (',') is not allowed in AFL_PRELOAD when -Q is "
"specified!");
}
}
if (qemu_preload) {
buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
qemu_preload, afl_preload, afl_preload);
} else {
buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
afl_preload, afl_preload);
}
setenv("QEMU_SET_ENV", buf, 1);
ck_free(buf);
} else { } else {
@ -1360,6 +1304,13 @@ int main(int argc, char **argv_orig, char **envp) {
} }
if (afl->afl_env.afl_target_env &&
!extract_and_set_env(afl->afl_env.afl_target_env)) {
FATAL("Bad value of AFL_TARGET_ENV");
}
save_cmdline(afl, argc, argv); save_cmdline(afl, argc, argv);
fix_up_banner(afl, argv[optind]); fix_up_banner(afl, argv[optind]);
@ -1584,21 +1535,21 @@ int main(int argc, char **argv_orig, char **envp) {
if (!afl->non_instrumented_mode && !afl->fsrv.qemu_mode && if (!afl->non_instrumented_mode && !afl->fsrv.qemu_mode &&
!afl->unicorn_mode) { !afl->unicorn_mode) {
if (map_size <= 8000000 && !afl->non_instrumented_mode && if (map_size <= DEFAULT_SHMEM_SIZE && !afl->non_instrumented_mode &&
!afl->fsrv.qemu_mode && !afl->unicorn_mode) { !afl->fsrv.qemu_mode && !afl->unicorn_mode) {
afl->fsrv.map_size = 8000000; // dummy temporary value afl->fsrv.map_size = DEFAULT_SHMEM_SIZE; // dummy temporary value
setenv("AFL_MAP_SIZE", "8000000", 1); char vbuf[16];
snprintf(vbuf, sizeof(vbuf), "%u", DEFAULT_SHMEM_SIZE);
setenv("AFL_MAP_SIZE", vbuf, 1);
} }
u32 new_map_size = afl_fsrv_get_mapsize( u32 new_map_size = afl_fsrv_get_mapsize(
&afl->fsrv, afl->argv, &afl->stop_soon, afl->afl_env.afl_debug_child); &afl->fsrv, afl->argv, &afl->stop_soon, afl->afl_env.afl_debug_child);
// only reinitialize when it makes sense // only reinitialize if the map needs to be larger than what we have.
if ((map_size < new_map_size || if (map_size < new_map_size) {
(new_map_size != MAP_SIZE && new_map_size < map_size &&
map_size - new_map_size > MAP_SIZE))) {
OKF("Re-initializing maps to %u bytes", new_map_size); OKF("Re-initializing maps to %u bytes", new_map_size);
@ -1627,8 +1578,6 @@ int main(int argc, char **argv_orig, char **envp) {
} }
afl->fsrv.map_size = map_size;
} }
if (afl->cmplog_binary) { if (afl->cmplog_binary) {
@ -1641,11 +1590,15 @@ int main(int argc, char **argv_orig, char **envp) {
afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary; afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary;
afl->cmplog_fsrv.init_child_func = cmplog_exec_child; afl->cmplog_fsrv.init_child_func = cmplog_exec_child;
if (map_size <= 8000000 && !afl->non_instrumented_mode && if ((map_size <= DEFAULT_SHMEM_SIZE ||
!afl->fsrv.qemu_mode && !afl->unicorn_mode) { afl->cmplog_fsrv.map_size < map_size) &&
!afl->non_instrumented_mode && !afl->fsrv.qemu_mode &&
!afl->unicorn_mode) {
afl->cmplog_fsrv.map_size = 8000000; // dummy temporary value afl->cmplog_fsrv.map_size = MAX(map_size, (u32)DEFAULT_SHMEM_SIZE);
setenv("AFL_MAP_SIZE", "8000000", 1); char vbuf[16];
snprintf(vbuf, sizeof(vbuf), "%u", afl->cmplog_fsrv.map_size);
setenv("AFL_MAP_SIZE", vbuf, 1);
} }
@ -1686,10 +1639,6 @@ int main(int argc, char **argv_orig, char **envp) {
afl_fsrv_start(&afl->cmplog_fsrv, afl->argv, &afl->stop_soon, afl_fsrv_start(&afl->cmplog_fsrv, afl->argv, &afl->stop_soon,
afl->afl_env.afl_debug_child); afl->afl_env.afl_debug_child);
} else {
afl->cmplog_fsrv.map_size = new_map_size;
} }
OKF("Cmplog forkserver successfully started"); OKF("Cmplog forkserver successfully started");

View File

@ -162,8 +162,8 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size,
snprintf(shm->g_shm_file_path, L_tmpnam, "/afl_%d_%ld", getpid(), random()); snprintf(shm->g_shm_file_path, L_tmpnam, "/afl_%d_%ld", getpid(), random());
/* create the shared memory segment as if it was a file */ /* create the shared memory segment as if it was a file */
shm->g_shm_fd = shm->g_shm_fd = shm_open(shm->g_shm_file_path, O_CREAT | O_RDWR | O_EXCL,
shm_open(shm->g_shm_file_path, O_CREAT | O_RDWR | O_EXCL, 0600); DEFAULT_PERMISSION);
if (shm->g_shm_fd == -1) { PFATAL("shm_open() failed"); } if (shm->g_shm_fd == -1) { PFATAL("shm_open() failed"); }
/* configure the size of the shared memory segment */ /* configure the size of the shared memory segment */
@ -202,7 +202,8 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size,
/* create the shared memory segment as if it was a file */ /* create the shared memory segment as if it was a file */
shm->cmplog_g_shm_fd = shm->cmplog_g_shm_fd =
shm_open(shm->cmplog_g_shm_file_path, O_CREAT | O_RDWR | O_EXCL, 0600); shm_open(shm->cmplog_g_shm_file_path, O_CREAT | O_RDWR | O_EXCL,
DEFAULT_PERMISSION);
if (shm->cmplog_g_shm_fd == -1) { PFATAL("shm_open() failed"); } if (shm->cmplog_g_shm_fd == -1) { PFATAL("shm_open() failed"); }
/* configure the size of the shared memory segment */ /* configure the size of the shared memory segment */
@ -241,13 +242,14 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size,
#else #else
u8 *shm_str; u8 *shm_str;
shm->shm_id = shmget(IPC_PRIVATE, map_size, IPC_CREAT | IPC_EXCL | 0600); shm->shm_id =
shmget(IPC_PRIVATE, map_size, IPC_CREAT | IPC_EXCL | DEFAULT_PERMISSION);
if (shm->shm_id < 0) { PFATAL("shmget() failed"); } if (shm->shm_id < 0) { PFATAL("shmget() failed"); }
if (shm->cmplog_mode) { if (shm->cmplog_mode) {
shm->cmplog_shm_id = shmget(IPC_PRIVATE, sizeof(struct cmp_map), shm->cmplog_shm_id = shmget(IPC_PRIVATE, sizeof(struct cmp_map),
IPC_CREAT | IPC_EXCL | 0600); IPC_CREAT | IPC_EXCL | DEFAULT_PERMISSION);
if (shm->cmplog_shm_id < 0) { if (shm->cmplog_shm_id < 0) {

View File

@ -252,7 +252,7 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
} else { } else {
unlink(outfile); /* Ignore errors */ unlink(outfile); /* Ignore errors */
fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, 0600); fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (fd < 0) { PFATAL("Unable to create '%s'", outfile); } if (fd < 0) { PFATAL("Unable to create '%s'", outfile); }
} }
@ -599,38 +599,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
if (fsrv->qemu_mode) { if (fsrv->qemu_mode) {
u8 *qemu_preload = getenv("QEMU_SET_ENV"); /* afl-qemu-trace takes care of converting AFL_PRELOAD. */
u8 *afl_preload = getenv("AFL_PRELOAD");
u8 *buf;
s32 i, afl_preload_size = strlen(afl_preload);
for (i = 0; i < afl_preload_size; ++i) {
if (afl_preload[i] == ',') {
PFATAL(
"Comma (',') is not allowed in AFL_PRELOAD when -Q is "
"specified!");
}
}
if (qemu_preload) {
buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
qemu_preload, afl_preload, afl_preload);
} else {
buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
afl_preload, afl_preload);
}
setenv("QEMU_SET_ENV", buf, 1);
ck_free(buf);
} else { } else {
@ -946,31 +915,6 @@ int main(int argc, char **argv_orig, char **envp) {
if (optind == argc || !out_file) { usage(argv[0]); } if (optind == argc || !out_file) { usage(argv[0]); }
if (fsrv->qemu_mode && getenv("AFL_USE_QASAN")) {
u8 *preload = getenv("AFL_PRELOAD");
u8 *libqasan = get_libqasan_path(argv_orig[0]);
if (!preload) {
setenv("AFL_PRELOAD", libqasan, 0);
} else {
u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2);
strcpy(result, libqasan);
strcat(result, " ");
strcat(result, preload);
setenv("AFL_PRELOAD", result, 1);
ck_free(result);
}
ck_free(libqasan);
}
if (in_dir) { if (in_dir) {
if (!out_file && !collect_coverage) if (!out_file && !collect_coverage)
@ -1175,7 +1119,8 @@ int main(int argc, char **argv_orig, char **envp) {
unlink(stdin_file); unlink(stdin_file);
atexit(at_exit_handler); atexit(at_exit_handler);
fsrv->out_file = stdin_file; fsrv->out_file = stdin_file;
fsrv->out_fd = open(stdin_file, O_RDWR | O_CREAT | O_EXCL, 0600); fsrv->out_fd =
open(stdin_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", out_file); } if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", out_file); }
if (arg_offset && use_argv[arg_offset] != stdin_file) { if (arg_offset && use_argv[arg_offset] != stdin_file) {

View File

@ -244,7 +244,7 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
unlink(path); /* Ignore errors */ unlink(path); /* Ignore errors */
ret = open(path, O_RDWR | O_CREAT | O_EXCL, 0600); ret = open(path, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (ret < 0) { PFATAL("Unable to create '%s'", path); } if (ret < 0) { PFATAL("Unable to create '%s'", path); }
@ -666,7 +666,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
unlink(out_file); unlink(out_file);
fsrv->out_file = out_file; fsrv->out_file = out_file;
fsrv->out_fd = open(out_file, O_RDWR | O_CREAT | O_EXCL, 0600); fsrv->out_fd = open(out_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", out_file); } if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", out_file); }
@ -753,38 +753,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
if (fsrv->qemu_mode) { if (fsrv->qemu_mode) {
u8 *qemu_preload = getenv("QEMU_SET_ENV"); /* afl-qemu-trace takes care of converting AFL_PRELOAD. */
u8 *afl_preload = getenv("AFL_PRELOAD");
u8 *buf;
s32 i, afl_preload_size = strlen(afl_preload);
for (i = 0; i < afl_preload_size; ++i) {
if (afl_preload[i] == ',') {
PFATAL(
"Comma (',') is not allowed in AFL_PRELOAD when -Q is "
"specified!");
}
}
if (qemu_preload) {
buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
qemu_preload, afl_preload, afl_preload);
} else {
buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
afl_preload, afl_preload);
}
setenv("QEMU_SET_ENV", buf, 1);
ck_free(buf);
} else { } else {
@ -1079,31 +1048,6 @@ int main(int argc, char **argv_orig, char **envp) {
check_environment_vars(envp); check_environment_vars(envp);
setenv("AFL_NO_AUTODICT", "1", 1); setenv("AFL_NO_AUTODICT", "1", 1);
if (fsrv->qemu_mode && getenv("AFL_USE_QASAN")) {
u8 *preload = getenv("AFL_PRELOAD");
u8 *libqasan = get_libqasan_path(argv_orig[0]);
if (!preload) {
setenv("AFL_PRELOAD", libqasan, 0);
} else {
u8 *result = ck_alloc(strlen(libqasan) + strlen(preload) + 2);
strcpy(result, libqasan);
strcat(result, " ");
strcat(result, preload);
setenv("AFL_PRELOAD", result, 1);
ck_free(result);
}
ck_free(libqasan);
}
/* initialize cmplog_mode */ /* initialize cmplog_mode */
shm.cmplog_mode = 0; shm.cmplog_mode = 0;

View File

@ -18,6 +18,10 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#ifdef TEST_SHARED_OBJECT
#define main main_exported
#endif
int main(int argc, char **argv) { int main(int argc, char **argv) {
int fd = 0; int fd = 0;

23
test/test-dlopen.c Normal file
View File

@ -0,0 +1,23 @@
#include <stdio.h>
#include <errno.h>
#include <dlfcn.h>
#include <stdlib.h>
int main(int argc, char **argv) {
if (!getenv("TEST_DLOPEN_TARGET")) return 1;
void *lib = dlopen(getenv("TEST_DLOPEN_TARGET"), RTLD_LAZY);
if (!lib) {
perror(dlerror());
return 2;
}
int (*func)(int, char **) = dlsym(lib, "main_exported");
if (!func) return 3;
return func(argc, argv);
}

View File

@ -43,6 +43,48 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
$ECHO "$RED[!] llvm_mode failed" $ECHO "$RED[!] llvm_mode failed"
CODE=1 CODE=1
} }
../afl-clang-fast -DTEST_SHARED_OBJECT=1 -z defs -fPIC -shared -o test-instr.so ../test-instr.c > /dev/null 2>&1
test -e test-instr.so && {
$ECHO "$GREEN[+] llvm_mode shared object with -z defs compilation succeeded"
../afl-clang-fast -o test-dlopen.plain test-dlopen.c -ldl > /dev/null 2>&1
test -e test-dlopen.plain && {
$ECHO "$GREEN[+] llvm_mode test-dlopen compilation succeeded"
echo 0 | TEST_DLOPEN_TARGET=./test-instr.so AFL_QUIET=1 ./test-dlopen.plain > /dev/null 2>&1
if [ $? -ne 0 ]; then
$ECHO "$RED[!] llvm_mode test-dlopen exits with an error"
CODE=1
fi
echo 0 | TEST_DLOPEN_TARGET=./test-instr.so AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-dlopen.plain.0 -r -- ./test-dlopen.plain > /dev/null 2>&1
TEST_DLOPEN_TARGET=./test-instr.so AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-dlopen.plain.1 -r -- ./test-dlopen.plain < /dev/null > /dev/null 2>&1
test -e test-dlopen.plain.0 -a -e test-dlopen.plain.1 && {
diff test-dlopen.plain.0 test-dlopen.plain.1 > /dev/null 2>&1 && {
$ECHO "$RED[!] llvm_mode test-dlopen instrumentation should be different on different input but is not"
CODE=1
} || {
$ECHO "$GREEN[+] llvm_mode test-dlopen instrumentation present and working correctly"
TUPLES=`echo 0|TEST_DLOPEN_TARGET=./test-instr.so AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-dlopen.plain 2>&1 | grep Captur | awk '{print$3}'`
test "$TUPLES" -gt 3 -a "$TUPLES" -lt 12 && {
$ECHO "$GREEN[+] llvm_mode test-dlopen run reported $TUPLES instrumented locations which is fine"
} || {
$ECHO "$RED[!] llvm_mode test-dlopen instrumentation produces weird numbers: $TUPLES"
CODE=1
}
test "$TUPLES" -lt 3 && SKIP=1
true
}
} || {
$ECHO "$RED[!] llvm_mode test-dlopen instrumentation failed"
CODE=1
}
} || {
$ECHO "$RED[!] llvm_mode test-dlopen compilation failed"
CODE=1
}
rm -f test-dlopen.plain test-dlopen.plain.0 test-dlopen.plain.1 test-instr.so
} || {
$ECHO "$RED[!] llvm_mode shared object with -z defs compilation failed"
CODE=1
}
test -e test-compcov.harden && test_compcov_binary_functionality ./test-compcov.harden && { test -e test-compcov.harden && test_compcov_binary_functionality ./test-compcov.harden && {
grep -Eq$GREPAOPTION 'stack_chk_fail|fstack-protector-all|fortified' test-compcov.harden > /dev/null 2>&1 && { grep -Eq$GREPAOPTION 'stack_chk_fail|fstack-protector-all|fortified' test-compcov.harden > /dev/null 2>&1 && {
$ECHO "$GREEN[+] llvm_mode hardened mode succeeded and is working" $ECHO "$GREEN[+] llvm_mode hardened mode succeeded and is working"

View File

@ -1,45 +0,0 @@
# This is the Dockerfile for testing problems in Travis build
# configuration #1.
# This needs not to be rebuild everytime, most of the time it needs just to
# be build once and then started when debugging issues and execute:
# cd /AFLplusplus/
# git pull
# make distrib
#
FROM ubuntu:bionic
LABEL "about"="travis image 1"
RUN apt-get update && apt-get -y install \
automake \
bison \
build-essential \
clang \
flex \
git \
python3.7 python3.7-dev \
python3-setuptools \
libtool libtool-bin \
libglib2.0-dev \
python-setuptools \
wget \
ca-certificates \
libpixman-1-dev \
gcc-7 gcc-7-plugin-dev libc++-7-dev \
findutils \
libcmocka-dev \
joe nano vim locate \
&& rm -rf /var/lib/apt/lists/*
ENV AFL_NO_UI=1
ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1
ENV LLVM_CONFIG=llvm-config-6.0
RUN cd / && \
git clone https://github.com/AFLplusplus/AFLplusplus && \
cd AFLplusplus && \
git checkout dev && \
cd qemu_mode && wget http://download.qemu-project.org/qemu-3.1.1.tar.xz && \
cd ../unicorn_mode && git submodule init && git submodule update || true && \
cd /AFLplusplus && ASAN_BUILD=1 make source-only || true
WORKDIR /AFLplusplus
CMD ["/bin/bash"]

View File

@ -1,45 +0,0 @@
# This is the Dockerfile for testing problems in Travis build
# configuration #1.
# This needs not to be rebuild everytime, most of the time it needs just to
# be build once and then started when debugging issues and execute:
# cd /AFLplusplus/
# git pull
# make distrib
#
FROM ubuntu:focal
LABEL "about"="travis image 4"
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get -y install \
automake \
bison \
build-essential \
clang \
flex \
git \
python3 python3-dev \
python3-setuptools \
libtool libtool-bin \
libglib2.0-dev \
python-setuptools \
wget \
ca-certificates \
libpixman-1-dev \
gcc-9 gcc-9-plugin-dev libc++-9-dev \
findutils \
libcmocka-dev \
joe nano vim locate \
&& rm -rf /var/lib/apt/lists/*
ENV AFL_NO_UI=1
ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1
RUN cd / && \
git clone https://github.com/AFLplusplus/AFLplusplus && \
cd AFLplusplus && \
git checkout dev && \
cd qemu_mode && wget http://download.qemu-project.org/qemu-3.1.1.tar.xz && \
cd ../unicorn_mode && git submodule init && git submodule update || true && \
cd /AFLplusplus && ASAN_BUILD=1 make source-only || true
WORKDIR /AFLplusplus
CMD ["/bin/bash"]

View File

@ -1,49 +0,0 @@
# This is the Dockerfile for testing problems in Travis builds
# configuration #3.
# This needs not to be rebuild everytime, most of the time it needs just to
# be build once and then started when debugging issues and execute:
# cd /AFLplusplus/
# git pull
# make distrib
#
FROM ubuntu:trusty
LABEL "about"="travis image 3"
RUN apt-get update && apt-get -y install \
automake \
bison \
build-essential \
clang \
flex \
git \
python2.7 python2.7-dev \
python3-setuptools \
libtool \
libglib2.0-dev \
python-setuptools \
wget \
ca-certificates \
libpixman-1-dev \
gcc-4.8 gcc-4.8-plugin-dev \
libc++-dev \
findutils \
libcmocka-dev \
joe nano vim locate \
&& rm -rf /var/lib/apt/lists/*
ENV TERM linux
ENV DEBIAN_FRONTEND noninteractive
ENV LLVM_CONFIG=llvm-config-3.4
ENV AFL_NO_UI=1
ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1
RUN cd / && \
git clone https://github.com/AFLplusplus/AFLplusplus && \
cd AFLplusplus && \
git checkout dev && \
cd qemu_mode && wget http://download.qemu-project.org/qemu-3.1.1.tar.xz && \
cd ../unicorn_mode && git submodule init && git submodule update || true && \
cd /AFLplusplus && ASAN_BUILD=1 make source-only || true
WORKDIR /AFLplusplus
CMD ["/bin/bash"]

View File

@ -1,46 +0,0 @@
# This is the Dockerfile for testing problems in Travis builds
# configuration #2.
# This needs not to be rebuild everytime, most of the time it needs just to
# be build once and then started when debugging issues and execute:
# cd /AFLplusplus/
# git pull
# make distrib
#
FROM ubuntu:xenial
LABEL "about"="travis image 2"
RUN apt-get update && apt-get -y install \
automake \
bison \
build-essential \
clang-6.0 \
flex \
git \
python3 python3-dev \
python3-setuptools \
libtool libtool-bin \
libglib2.0-dev \
python-setuptools \
wget \
ca-certificates \
libpixman-1-dev \
gcc-5 gcc-5-plugin-dev \
libc++-dev \
findutils \
libcmocka-dev \
joe nano vim locate \
&& rm -rf /var/lib/apt/lists/*
ENV LLVM_CONFIG=llvm-config-6.0
ENV AFL_NO_UI=1
ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1
RUN cd / && \
git clone https://github.com/AFLplusplus/AFLplusplus && \
cd AFLplusplus && \
git checkout dev && \
cd qemu_mode && wget http://download.qemu-project.org/qemu-3.1.1.tar.xz && \
cd ../unicorn_mode && git submodule init && git submodule update || true && \
cd /AFLplusplus && ASAN_BUILD=1 make source-only || true
WORKDIR /AFLplusplus
CMD ["/bin/bash"]

View File

@ -0,0 +1,197 @@
# Copyright (c) 2021 Brandon Miller (zznop)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
"""IDA script for loading state that was dumped from a running process using unicorn AFL's GDB
plugin (unicorn_dumper_gdb.py). The dumper script can be found in the AFL++ repository at:
https://github.com/AFLplusplus/AFLplusplus/blob/stable/unicorn_mode/helper_scripts/unicorn_dumper_gdb.py
"""
import json
from pathlib import Path, PurePath
import zlib
import idaapi
import ida_bytes
import ida_kernwin
import ida_nalt
import ida_segment
class ContextLoaderError(Exception):
"""Base "catch all" exception for this script
"""
class ArchNotSupportedError(ContextLoaderError):
"""Exception raised if the input file CPU architecture isn't supported fully
"""
def parse_mapping_index(filepath: str):
"""Open and unmarshal the _index.json file
:param filepath: Path to the JSON file
:return: Dict representing index file contents
"""
if filepath is None:
raise ContextLoaderError('_index.json file was not selected')
try:
with open(filepath, 'rb') as _file:
return json.load(_file)
except Exception as ex:
raise ContextLoaderError('Failed to parse json file {}'.format(filepath)) from ex
def get_input_name():
"""Get the name of the input file
:retrun: Name of the input file
"""
input_filepath = ida_nalt.get_input_file_path()
return Path(input_filepath).name
def write_segment_bytes(start: int, filepath: str):
""""Read data from context file and write it to the IDA segment
:param start: Start address
:param filepath: Path to context file
"""
with open(filepath, 'rb') as _file:
data = _file.read()
decompressed_data = zlib.decompress(data)
ida_bytes.put_bytes(start, decompressed_data)
def create_segment(context_dir: str, segment: dict, is_be: bool):
"""Create segment in IDA and map in the data from the file
:param context_dir: Parent directory of the context files
:param segment: Segment information from _index.json
:param is_be: True if processor is big endian, otherwise False
"""
input_name = get_input_name()
if Path(segment['name']).name != input_name:
ida_seg = idaapi.segment_t()
ida_seg.start_ea = segment['start']
ida_seg.end_ea = segment['end']
ida_seg.bitness = 1 if is_be else 0
if segment['permissions']['r']:
ida_seg.perm |= ida_segment.SEGPERM_READ
if segment['permissions']['w']:
ida_seg.perm |= ida_segment.SEGPERM_WRITE
if segment['permissions']['x']:
ida_seg.perm |= ida_segment.SEGPERM_EXEC
idaapi.add_segm_ex(ida_seg, Path(segment['name']).name, 'CODE', idaapi.ADDSEG_OR_DIE)
else:
idaapi.add_segm_ex(ida_seg, Path(segment['name']).name, 'DATA', idaapi.ADDSEG_OR_DIE)
if segment['content_file']:
write_segment_bytes(segment['start'], PurePath(context_dir, segment['content_file']))
def create_segments(index: dict, context_dir: str):
"""Iterate segments in index JSON, create the segment in IDA, and map in the data from the file
:param index: _index.json JSON data
:param context_dir: Parent directory of the context files
"""
info = idaapi.get_inf_structure()
is_be = info.is_be()
for segment in index['segments']:
create_segment(context_dir, segment, is_be)
def rebase_program(index: dict):
"""Rebase the program to the offset specified in the context _index.json
:param index: _index.json JSON data
"""
input_name = get_input_name()
new_base = None
for segment in index['segments']:
if not segment['name']:
continue
segment_name = Path(segment['name']).name
if input_name == segment_name:
new_base = segment['start']
break
if not new_base:
raise ContextLoaderError('Input file is not in _index.json')
current_base = idaapi.get_imagebase()
ida_segment.rebase_program(new_base-current_base, 8)
def get_pc_by_arch(index: dict) -> int:
"""Queries the input file CPU architecture and attempts to lookup the address of the program
counter in the _index.json by register name
:param index: _index.json JSON data
:return: Program counter value or None
"""
progctr = None
info = idaapi.get_inf_structure()
if info.procname == 'metapc':
if info.is_64bit():
progctr = index['regs']['rax']
elif info.is_32bit():
progctr = index['regs']['eax']
return progctr
def write_reg_info(index: dict):
"""Write register info as line comment at instruction pointed to by the program counter and
change focus to that location
:param index: _index.json JSON data
"""
cmt = ''
for reg, val in index['regs'].items():
cmt += f"{reg.ljust(6)} : {hex(val)}\n"
progctr = get_pc_by_arch(index)
if progctr is None:
raise ArchNotSupportedError(
'Architecture not fully supported, skipping register status comment')
ida_bytes.set_cmt(progctr, cmt, 0)
ida_kernwin.jumpto(progctr)
def main(filepath):
"""Main - parse _index.json input and map context files into the database
:param filepath: Path to the _index.json file
"""
try:
index = parse_mapping_index(filepath)
context_dir = Path(filepath).parent
rebase_program(index)
create_segments(index, context_dir)
write_reg_info(index)
except ContextLoaderError as ex:
print(ex)
if __name__ == '__main__':
main(ida_kernwin.ask_file(1, '*.json', 'Import file name'))

@ -0,0 +1 @@
Subproject commit fb2fc9f25df32f17f6b6b859e4dbd70f9a857e0c

View File

@ -237,38 +237,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
if (fsrv->qemu_mode) { if (fsrv->qemu_mode) {
u8 *qemu_preload = getenv("QEMU_SET_ENV"); /* afl-qemu-trace takes care of converting AFL_PRELOAD. */
u8 *afl_preload = getenv("AFL_PRELOAD");
u8 *buf;
s32 i, afl_preload_size = strlen(afl_preload);
for (i = 0; i < afl_preload_size; ++i) {
if (afl_preload[i] == ',') {
PFATAL(
"Comma (',') is not allowed in AFL_PRELOAD when -Q is "
"specified!");
}
}
if (qemu_preload) {
buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
qemu_preload, afl_preload, afl_preload);
} else {
buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
afl_preload, afl_preload);
}
setenv("QEMU_SET_ENV", buf, 1);
afl_free(buf);
} else { } else {

View File

@ -187,6 +187,8 @@ static int ExecuteFilesOnyByOne(int argc, char **argv) {
} }
close(fd);
} }
free(buf); free(buf);
@ -208,6 +210,16 @@ int main(int argc, char **argv) {
"======================================================\n", "======================================================\n",
argv[0], argv[0]); argv[0], argv[0]);
if (getenv("AFL_GDB")) {
char cmd[64];
snprintf(cmd, sizeof(cmd), "cat /proc/%d/maps", getpid());
system(cmd);
fprintf(stderr, "DEBUG: aflpp_driver pid is %d\n", getpid());
sleep(1);
}
output_file = stderr; output_file = stderr;
maybe_duplicate_stderr(); maybe_duplicate_stderr();
maybe_close_fd_mask(); maybe_close_fd_mask();

View File

@ -60,12 +60,12 @@ if
fi fi
if [ ! -f "$BIN" -o ! -x "$BIN" ]; then if [ ! -f "$BIN" -o ! -x "$BIN" ]; then
echo "[-] Error: binary '$2' not found or is not executable." 1>&2 echo "[-] Error: binary '$BIN' not found or is not executable." 1>&2
exit 1 exit 1
fi fi
if [ ! -d "$DIR/queue" ]; then if [ ! -d "$DIR/queue" ]; then
echo "[-] Error: directory '$1' not found or not created by afl-fuzz." 1>&2 echo "[-] Error: directory '$DIR' not found or not created by afl-fuzz." 1>&2
exit 1 exit 1
fi fi

View File

@ -168,7 +168,7 @@ static void *__dislocator_alloc(size_t len) {
u8 * ret, *base; u8 * ret, *base;
size_t tlen; size_t tlen;
int flags, fd, sp; int flags, protflags, fd, sp;
if (total_mem + len > max_mem || total_mem + len < total_mem) { if (total_mem + len > max_mem || total_mem + len < total_mem) {
@ -191,8 +191,14 @@ static void *__dislocator_alloc(size_t len) {
base = NULL; base = NULL;
tlen = (1 + PG_COUNT(rlen + 8)) * PAGE_SIZE; tlen = (1 + PG_COUNT(rlen + 8)) * PAGE_SIZE;
protflags = PROT_READ | PROT_WRITE;
flags = MAP_PRIVATE | MAP_ANONYMOUS; flags = MAP_PRIVATE | MAP_ANONYMOUS;
fd = -1; fd = -1;
#if defined(PROT_MAX)
// apply when sysctl vm.imply_prot_max is set to 1
// no-op otherwise
protflags |= PROT_MAX(PROT_READ | PROT_WRITE);
#endif
#if defined(USEHUGEPAGE) #if defined(USEHUGEPAGE)
sp = (rlen >= SUPER_PAGE_SIZE && !(rlen % SUPER_PAGE_SIZE)); sp = (rlen >= SUPER_PAGE_SIZE && !(rlen % SUPER_PAGE_SIZE));
@ -215,7 +221,7 @@ static void *__dislocator_alloc(size_t len) {
(void)sp; (void)sp;
#endif #endif
ret = (u8 *)mmap(base, tlen, PROT_READ | PROT_WRITE, flags, fd, 0); ret = (u8 *)mmap(base, tlen, protflags, flags, fd, 0);
#if defined(USEHUGEPAGE) #if defined(USEHUGEPAGE)
/* We try one more time with regular call */ /* We try one more time with regular call */
if (ret == MAP_FAILED) { if (ret == MAP_FAILED) {
@ -229,7 +235,7 @@ static void *__dislocator_alloc(size_t len) {
#elif defined(__sun) #elif defined(__sun)
flags &= -MAP_ALIGN; flags &= -MAP_ALIGN;
#endif #endif
ret = (u8 *)mmap(NULL, tlen, PROT_READ | PROT_WRITE, flags, fd, 0); ret = (u8 *)mmap(NULL, tlen, protflags, flags, fd, 0);
} }