Compare commits

...

74 Commits
3.11c ... 3.12c

Author SHA1 Message Date
2dac4e785f Merge pull request #837 from AFLplusplus/dev
final pull to stable
2021-03-24 11:23:01 +01:00
2b3642aa39 v3.12c ready to go 2021-03-24 11:13:16 +01:00
d68bd656fe fix counting favorites 2021-03-24 11:12:44 +01:00
8bd5d7676e 3.12c 2021-03-24 11:12:44 +01:00
70c1de5d64 better forkserver error help and code format 2021-03-24 11:12:44 +01:00
2fef89950f v3.12c release 2021-03-24 11:12:44 +01:00
a908a98225 update qemuafl 2021-03-24 11:06:02 +01:00
82554677a8 update qemuafl 2021-03-24 11:00:13 +01:00
dfe6f7f8c9 make setting different file permissions easy via config.h 2021-03-23 20:21:08 +01:00
5fcd634f05 fixed tiny nitpicks 2021-03-23 18:47:07 +01:00
28f1e94ab9 fix our PCGUARD for llvm 10.0.1 2021-03-23 15:33:27 +01:00
e1d37a802b Merge pull request #836 from jtpereyda/doc-update-missing-crashes
add details to AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES doc
2021-03-22 21:44:12 +01:00
0f9dceff3d add details to AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES doc 2021-03-22 12:06:52 -07:00
8868648f76 fix LTO selective instrumentation 2021-03-22 10:45:39 +01:00
72a70423c2 show afl-cc NATIVE when auto used 2021-03-22 09:24:36 +01:00
84534ae2e8 format 2021-03-21 16:23:08 +01:00
687dd9cb67 add missing links for afl-clang-fast*.8 man pages 2021-03-20 13:15:56 +01:00
ede03a96ed IDA script for loading unicorn AFL context dumps (#812)
* IDA script for loading unicorn AFL context dumps

This script can be used to load context dumps into an IDA database for
analysis. It requires that you first open the main executable into IDA
directly. Then, you can run the script and select the _index.json file.
From there, the script will rebase the main executable and map in all
the other dumped vmem from the context dump directory

* Modified ida_context_loader.py header comment

No specifies the full URL for the unicon_dumper_gdb.py script
2021-03-20 09:36:25 +01:00
33dd2ce021 close fds when executing one by one. (#835)
* closes fd when executing one by one.

* clean aflpp_driver
2021-03-20 09:34:40 +01:00
bc0ff559f5 Merge pull request #824 from fuzzah/dev
add AFL_TARGET_ENV to afl-fuzz
2021-03-19 23:55:32 +01:00
090128b3f8 Merge branch 'dev' into dev 2021-03-19 23:54:36 +01:00
d7e121e2c9 add AFL_TARGET_ENV to afl-fuzz 2021-03-20 01:32:28 +03:00
749b03d812 Merge pull request #830 from richinseattle/dev
preserve plot_data for in-place resume
2021-03-19 23:26:34 +01:00
fc73a18e9a Merge pull request #834 from devnexen/libdislocator_fbsd_13_upd
libdislocator freebsd 13 update to amke it works
2021-03-19 23:23:25 +01:00
7e67a735e6 update plot_data timestamps to be relative 2021-03-19 14:25:55 -07:00
14e1b0ffba libdislocator freebsd 13 update to amke it works
with vm.imply_prot_max set.
2021-03-19 21:19:22 +00:00
e98cd00822 Merge pull request #831 from AFLplusplus/dev
Push to stable
2021-03-19 19:04:59 +01:00
2102264acf fix for new llvm 13 change 2021-03-19 16:06:06 +01:00
e73c7c59c1 refactor finding binaries 2021-03-19 14:55:25 +01:00
99525dee38 remove unneeded code 2021-03-19 10:57:18 +01:00
848ea17154 add header to PCGUARD 2021-03-19 10:42:23 +01:00
1cdf0a898c update test-dlopen tuples number 2021-03-19 09:58:27 +01:00
00913bce81 update dynamic list with cmplog 2021-03-19 09:56:00 +01:00
5be7d9c1cc fix dynamic list usage error in afl-cc 2021-03-19 09:44:04 +01:00
44347beff0 check test-dlopen return code 2021-03-18 21:44:20 +01:00
166c8f93b5 test-dlopen llvm test 2021-03-18 21:34:12 +01:00
9393452d1c The official casing is AFLplusplus 2021-03-18 18:42:33 +01:00
66fa76a061 typo 2021-03-18 16:41:02 +01:00
d2e7c4ec05 better installation example 2021-03-18 14:04:18 +01:00
10fb46301c afl-fuzz cleanup 2021-03-18 11:05:53 +01:00
c397becd81 Merge branch 'dev' of https://github.com/AFLplusplus/AFLplusplus into dev 2021-03-18 01:37:40 -07:00
62508c3b44 preserve plot_data for in-place resume 2021-03-18 01:34:05 -07:00
94312796f9 better map variability 2021-03-17 13:16:02 +01:00
adeeed9e43 fix dynamic list 2021-03-17 12:48:30 +01:00
513bd70384 shared linking fix 2021-03-17 12:44:07 +01:00
cdd30c766b fix m32/m64 2021-03-17 11:25:14 +01:00
5e2a5f1110 shmem map size in config.h 2021-03-17 10:27:23 +01:00
a7797f0cb9 fix is now closer to original statement 2021-03-17 08:04:29 +01:00
b715050de9 deepclean no longer removes submodules 2021-03-17 05:13:34 +01:00
da5a32792d bring back unicornafl 2021-03-17 04:56:24 +01:00
f36341b3b4 when you think you work on a debug branch but it is dev. git sucks so much ... 2021-03-17 02:00:14 +01:00
dda4757b35 debug 2021-03-17 01:40:27 +01:00
c6f1c56c15 fix 2021-03-17 01:27:01 +01:00
413807db01 lto test 2021-03-17 01:25:21 +01:00
f59ef29c26 fix attempt 2021-03-17 01:08:10 +01:00
65b90001f6 debug 2021-03-16 23:24:34 +01:00
6840e8fd2a fix two bugs in error message
$1 and $2 have been modified here by two previous shift commands.
2021-03-16 22:58:10 +01:00
7c2436c711 no runtime for shared linking 2021-03-16 19:34:34 +01:00
c2df65a0af Merge branch 'dev' of github.com:AFLplusplus/AFLplusplus into dev 2021-03-16 17:04:59 +01:00
175a275a3d changelog 2021-03-16 17:04:52 +01:00
bd64315395 blacklist sanitize and debug in c++ 2021-03-16 16:54:48 +01:00
65e3770bad qemuafl 2021-03-16 16:32:35 +01:00
f5420e737a rtn fix 2021-03-16 16:15:29 +01:00
4e567d3f5d update qemuafl 2021-03-16 15:38:45 +01:00
1227776251 fix cmplog 2021-03-16 14:39:48 +01:00
862cb3217f fix cmplog rtn 2021-03-16 14:38:13 +01:00
8e11546536 Merge pull request #816 from realmadsci/add-more-qasan-checks
Add more qasan checks
2021-03-16 09:10:42 +01:00
73641be796 Merge pull request #819 from realmadsci/qemu-consistent-preload
Remove AFL_PRELOAD and AFL_USE_QASAN handlers
2021-03-16 09:08:23 +01:00
ff9f3fbe96 Merge pull request #818 from realmadsci/add-qemu-custom-bin
Add AFL_QEMU_CUSTOM_BIN environment flag
2021-03-16 09:01:13 +01:00
1dcc3549b6 v3.12a init 2021-03-15 23:21:03 +01:00
01ad7610be Remove AFL_PRELOAD and AFL_USE_QASAN handlers
These are now processed in afl-qemu-trace so that the "copy+paste" code
that is in all of the other AFL tools can be removed.

This also allows the AFL_USE_QASAN flag to work the same when used
with tools like afl-fuzz as it does with afl-qemu-trace. This is
important in situations where loading the QASAN library changes
the address of your desired entrypoint, or for crash validation
using the same environment that afl-fuzz was using.

With this change, the same set of environment variables can be used
in exactly the same way between afl-fuzz, afl-showmap, and
afl-qemu-trace, and you will get exactly the same guest environment.
2021-03-15 13:03:16 -07:00
d4fb7f8b40 Add AFL_QEMU_CUSTOM_BIN environment flag
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.
2021-03-15 12:57:06 -07:00
96574854b3 libqasan/malloc: Additional pointer checks
Add checks to free() and malloc_usable_size() to
verify (sort of) that the pointers are actually
pointing at valid allocated memory before dereferencing
them and using the chunk_begin struct info.

This will catch use-after-free and wildly bad pointers
a little bit earlier.
2021-03-15 12:07:22 -07:00
281cd47c15 libqasan: Add checks for read() and write() 2021-03-15 12:07:22 -07:00
54 changed files with 963 additions and 1026 deletions

View File

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

View File

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

1
.gitignore vendored
View File

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

View File

@ -558,6 +558,7 @@ clean:
-$(MAKE) -f GNUmakefile.gcc_plugin clean
$(MAKE) -C utils/libdislocator clean
$(MAKE) -C utils/libtokencap clean
$(MAKE) -C utils/aflpp_driver clean
$(MAKE) -C utils/afl_network_proxy clean
$(MAKE) -C utils/socket_fuzzing clean
$(MAKE) -C utils/argv_fuzzing clean
@ -576,7 +577,11 @@ endif
deepclean: clean
rm -rf unicorn_mode/unicornafl
rm -rf qemu_mode/qemuafl
ifeq "$(IN_REPO)" "1"
# 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
distrib: all

View File

@ -507,6 +507,8 @@ install: all
@echo .SH LICENSE >> ./$@
@echo Apache License Version 2.0, January 2004 >> ./$@
@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)" ""
ifeq "$(LLVM_LTO)" "1"
@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">
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)
@ -175,7 +175,13 @@ If you want to build afl++ yourself you have many options.
The easiest choice is to build and install everything:
```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
sudo make install
```
@ -1178,6 +1184,7 @@ without feedback, bug reports, or patches from:
Josephine Calliotte Konrad Welc
Thomas Rooijakkers David Carlier
Ruben ten Hove Joey Jiao
fuzzah
```
Thank you!

View File

@ -2,6 +2,7 @@
## Roadmap 3.00+
- Update afl->pending_not_fuzzed for MOpt
- CPU affinity for many cores? There seems to be an issue > 96 cores
- afl-plot to support multiple plot_data
- 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
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)
- afl-fuzz:
- 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"
- afl-cmin: support filenames with spaces
### Version ++3.10c (release)
- Mac OS ARM64 support
- 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), 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
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
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
some basic stats. This behavior is also automatically triggered when the
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)
- 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
processing the first queue entry; and `AFL_BENCH_UNTIL_CRASH` causes it to

View File

@ -5,6 +5,43 @@
"__afl_auto_init";
"__afl_area_initial";
"__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_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_max_det_extras, *afl_statsd_host, *afl_statsd_port,
*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;

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_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv);
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 *doc_path; /* path to documentation dir */
@ -58,6 +61,10 @@ extern u8 *doc_path; /* path to documentation dir */
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.
If the env is not set, sets the env to default_signal for the signal handlers
and returns the default_signal. */

View File

@ -26,7 +26,7 @@
/* Version string: */
// 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
*
* 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_GDB",
"AFL_DISABLE_TRIM",
"AFL_DISABLE_LLVM_INSTRUMENTATION",
"AFL_DONT_OPTIMIZE",
"AFL_DRIVER_STDERR_DUPLICATE_FILENAME",
"AFL_DUMB_FORKSRV",
@ -50,6 +51,7 @@ static char *afl_environment_variables[] = {
"AFL_FAST_CAL",
"AFL_FORCE_UI",
"AFL_FUZZER_ARGS", // oss-fuzz
"AFL_GDB",
"AFL_GCC_ALLOWLIST",
"AFL_GCC_DENYLIST",
"AFL_GCC_BLOCKLIST",
@ -129,7 +131,9 @@ static char *afl_environment_variables[] = {
"AFL_PATH",
"AFL_PERFORMANCE_FILE",
"AFL_PRELOAD",
"AFL_TARGET_ENV",
"AFL_PYTHON_MODULE",
"AFL_QEMU_CUSTOM_BIN",
"AFL_QEMU_COMPCOV",
"AFL_QEMU_COMPCOV_DEBUG",
"AFL_QEMU_DEBUG_MAPS",

View File

@ -113,7 +113,7 @@ cmake \
-DLLVM_LINK_LLVM_DYLIB="ON" \
-DLLVM_TARGETS_TO_BUILD="host" \
../llvm/
cmake --build . --parallel
cmake --build . -j4
export PATH="$(pwd)/bin:$PATH"
export LLVM_CONFIG="$(pwd)/bin/llvm-config"
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);
One = ConstantInt::get(Int8Tyi, 1);
initInstrumentList();
scanForDangerousFunctions(&M);
Mo = &M;
@ -1229,7 +1230,7 @@ void ModuleSanitizerCoverage::instrumentFunction(
// afl++ START
if (!F.size()) return;
if (isIgnoreFunction(&F)) return;
if (!isInInstrumentList(&F)) return;
// afl++ END
if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge)
@ -1291,10 +1292,17 @@ GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection(
*CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage,
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 (auto Comdat =
GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId))
Array->setComdat(Comdat);
#endif
Array->setSection(getSectionName(Section));
Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize()));
GlobalsToAppendToUsed.push_back(Array);

View File

@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/EHPersonalities.h"
@ -34,11 +35,11 @@
#include "llvm/InitializePasses.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SpecialCaseList.h"
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
#include "llvm/Support/VirtualFileSystem.h"
#endif
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
@ -47,65 +48,6 @@
#include "debug.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;
#define DEBUG_TYPE "sancov"
@ -156,96 +98,8 @@ static const char *const SanCovLowestStackName = "__sancov_lowest_stack";
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 {
/*
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) {
// Sets CoverageType and IndirectCalls.
@ -281,12 +135,14 @@ class ModuleSanitizerCoverage {
public:
ModuleSanitizerCoverage(
const SanitizerCoverageOptions &Options = SanitizerCoverageOptions(),
const SpecialCaseList * Allowlist = nullptr,
const SpecialCaseList * Blocklist = nullptr)
: Options(OverrideFromCL(Options)),
Allowlist(Allowlist),
Blocklist(Blocklist) {
const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()
#if LLVM_MAJOR > 10
,
const SpecialCaseList *Allowlist = nullptr,
const SpecialCaseList *Blocklist = nullptr
#endif
)
: Options(OverrideFromCL(Options)) {
}
@ -356,9 +212,6 @@ class ModuleSanitizerCoverage {
SanitizerCoverageOptions Options;
const SpecialCaseList *Allowlist;
const SpecialCaseList *Blocklist;
uint32_t instr = 0;
GlobalVariable *AFLMapPtr = NULL;
ConstantInt * One = NULL;
@ -370,27 +223,17 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass {
public:
ModuleSanitizerCoverageLegacyPass(
const SanitizerCoverageOptions &Options = SanitizerCoverageOptions(),
const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()
#if LLVM_VERSION_MAJOR > 10
,
const std::vector<std::string> &AllowlistFiles =
std::vector<std::string>(),
const std::vector<std::string> &BlocklistFiles =
std::vector<std::string>())
std::vector<std::string>()
#endif
)
: 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(
*PassRegistry::getPassRegistry());
@ -398,8 +241,12 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass {
bool runOnModule(Module &M) override {
ModuleSanitizerCoverage ModuleSancov(Options, Allowlist.get(),
Blocklist.get());
ModuleSanitizerCoverage ModuleSancov(Options
#if LLVM_MAJOR > 10
,
Allowlist.get(), Blocklist.get()
#endif
);
auto DTCallback = [this](Function &F) -> const DominatorTree * {
return &this->getAnalysis<DominatorTreeWrapperPass>(F).getDomTree();
@ -444,8 +291,12 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass {
PreservedAnalyses ModuleSanitizerCoveragePass::run(Module & M,
ModuleAnalysisManager &MAM) {
ModuleSanitizerCoverage ModuleSancov(Options, Allowlist.get(),
Blocklist.get());
ModuleSanitizerCoverage ModuleSancov(Options
#if LLVM_MAJOR > 10
,
Allowlist.get(), Blocklist.get()
#endif
);
auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
auto DTCallback = [&FAM](Function &F) -> const DominatorTree * {
@ -564,12 +415,6 @@ bool ModuleSanitizerCoverage::instrumentModule(
}
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());
DL = &M.getDataLayout();
CurModule = &M;
@ -842,9 +687,6 @@ void ModuleSanitizerCoverage::instrumentFunction(
if (F.hasPersonalityFn() &&
isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
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)
SplitAllCriticalEdges(
F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests());
@ -915,10 +757,18 @@ GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection(
*CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage,
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 (auto Comdat =
GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId))
Array->setComdat(Comdat);
#endif
Array->setSection(getSectionName(Section));
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize()));
@ -1354,12 +1204,20 @@ INITIALIZE_PASS_END(ModuleSanitizerCoverageLegacyPass, "sancov",
false)
ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass(
const SanitizerCoverageOptions &Options,
const SanitizerCoverageOptions &Options
#if LLVM_MAJOR > 10
,
const std::vector<std::string> &AllowlistFiles,
const std::vector<std::string> &BlocklistFiles) {
const std::vector<std::string> &BlocklistFiles
#endif
) {
return new ModuleSanitizerCoverageLegacyPass(Options, AllowlistFiles,
BlocklistFiles);
return new ModuleSanitizerCoverageLegacyPass(Options
#if LLVM_MAJOR > 10
,
AllowlistFiles, BlocklistFiles
#endif
);
}

View File

@ -204,7 +204,7 @@ static void __afl_map_shm_fuzz() {
int shm_fd = -1;
/* 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) {
fprintf(stderr, "shm_open() failed for fuzz\n");
@ -353,7 +353,7 @@ static void __afl_map_shm(void) {
unsigned char *shm_base = NULL;
/* create the shared memory segment as if it was a file */
shm_fd = shm_open(shm_file_path, O_RDWR, 0600);
shm_fd = shm_open(shm_file_path, O_RDWR, DEFAULT_PERMISSION);
if (shm_fd == -1) {
fprintf(stderr, "shm_open() failed\n");
@ -528,7 +528,7 @@ static void __afl_map_shm(void) {
struct cmp_map *shm_base = NULL;
/* 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) {
perror("shm_open() failed\n");
@ -729,7 +729,7 @@ static void __afl_start_snapshots(void) {
static uint32_t counter = 0;
char fn[32];
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 (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;
char fn[32];
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 (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
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
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;
long page_size = sysconf(_SC_PAGE_SIZE);
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);
// even if the write succeed this can be a false positive if we cross
// a page boundary. who knows why.
}
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 (likely(r >= 0 && r <= len)) {
if (page > p + len) {
// no, not crossing a page boundary
return (int)r;
} 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;
// fprintf(stderr, "RTN1 %p %p\n", ptr1, ptr2);
int l1, l2;
if ((l1 = area_is_valid(ptr1, 32)) <= 0 ||
(l2 = area_is_valid(ptr2, 32)) <= 0)
return;
int len = MIN(l1, l2);
// fprintf(stderr, "RTN2 %u\n", len);
uintptr_t k = (uintptr_t)__builtin_return_address(0);
k = (k >> 4) ^ (k << 8);
k &= CMP_MAP_W - 1;
@ -1809,6 +1818,7 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
ptr1, len);
__builtin_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v1,
ptr2, len);
// fprintf(stderr, "RTN3\n");
}

View File

@ -60,7 +60,7 @@ bool isIgnoreFunction(const llvm::Function *F) {
"asan.",
"llvm.",
"sancov.",
"__ubsan_",
"__ubsan",
"ign.",
"__afl",
"_fini",
@ -69,13 +69,16 @@ bool isIgnoreFunction(const llvm::Function *F) {
"__msan",
"__cmplog",
"__sancov",
"__san",
"__cxx_",
"__decide_deferred",
"_GLOBAL",
"_ZZN6__asan",
"_ZZN6__lsan",
"msan.",
"LLVMFuzzerM",
"LLVMFuzzerC",
"LLVMFuzzerI",
"__decide_deferred",
"maybe_duplicate_stderr",
"discard_output",
"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;
}

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);
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);
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);
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);
QASAN_DEBUG("\t\t = %zd\n", r);

View File

@ -159,6 +159,9 @@ size_t __libqasan_malloc_usable_size(void *ptr) {
char *p = ptr;
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;
}
@ -225,6 +228,9 @@ void __libqasan_free(void *ptr) {
struct chunk_begin *p = ptr;
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;
QASAN_STORE(ptr, n);

View File

@ -212,7 +212,7 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
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); }
@ -822,38 +822,7 @@ static void set_up_environment(void) {
if (qemu_mode) {
u8 *qemu_preload = getenv("QEMU_SET_ENV");
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);
/* afl-qemu-trace takes care of converting AFL_PRELOAD. */
} else {
@ -1079,31 +1048,6 @@ int main(int argc, char **argv_orig, char **envp) {
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();
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); }

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)
#ifdef __ANDROID__
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
instrument_mode != INSTRUMENT_LLVMNATIVE;
#else
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 "
"AFL_LLVM_ALLOWLIST/AFL_LLMV_DENYLIST instead.\n");
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
instrument_mode = INSTRUMENT_LLVMNATIVE;
} 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 "
"enhanced version.\n");
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
instrument_mode = INSTRUMENT_LLVMNATIVE;
#else
FATAL("pcguard instrumentation requires llvm 4.0.1+");
#endif
@ -682,19 +685,49 @@ static void edit_params(u32 argc, char **argv, char **envp) {
/* Detect stray -v calls from ./configure scripts. */
u8 skip_next = 0;
while (--argc) {
u8 *cur = *(++argv);
if (skip_next) {
skip_next = 0;
continue;
}
if (!strncmp(cur, "--afl", 5)) continue;
if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue;
if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue;
if (!strncmp(cur, "-fno-unroll", 11)) 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;
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); }
continue;
@ -962,18 +995,24 @@ static void edit_params(u32 argc, char **argv, char **envp) {
switch (bit_mode) {
case 0:
cc_params[cc_par_cnt++] =
alloc_printf("%s/afl-compiler-rt.o", obj_path);
if (!shared_linking)
cc_params[cc_par_cnt++] =
alloc_printf("%s/afl-compiler-rt.o", obj_path);
if (lto_mode)
cc_params[cc_par_cnt++] =
alloc_printf("%s/afl-llvm-rt-lto.o", obj_path);
break;
case 32:
cc_params[cc_par_cnt++] =
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 (!shared_linking) {
cc_params[cc_par_cnt++] =
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) {
cc_params[cc_par_cnt++] =
@ -986,10 +1025,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
break;
case 64:
cc_params[cc_par_cnt++] =
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 (!shared_linking) {
cc_params[cc_par_cnt++] =
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) {
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);
#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
cc_params[cc_par_cnt] = NULL;
@ -1220,6 +1264,7 @@ int main(int argc, char **argv, char **envp) {
} else if (strcasecmp(ptr, "LLVMNATIVE") == 0 ||
strcasecmp(ptr, "NATIVE") == 0 ||
strcasecmp(ptr, "LLVM-NATIVE") == 0) {
compiler_mode = LLVM;
@ -1632,8 +1677,8 @@ int main(int argc, char **argv, char **envp) {
"of afl-cc.\n\n");
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
#define NATIVE_MSG \
" NATIVE: use llvm's native PCGUARD instrumentation (less " \
#define NATIVE_MSG \
" LLVM-NATIVE: use llvm's native PCGUARD instrumentation (less " \
"performant)\n"
#else
#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) {
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));
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]. */
tmp = getenv("AFL_PATH");
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'.");
*target_path_p = new_argv[0] = find_afl_binary(own_loc, "afl-qemu-trace");
return new_argv;
}
@ -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) {
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));
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]. */
tmp = getenv("AFL_PATH");
if (tmp) {
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'.");
u8 *tmp = find_afl_binary(own_loc, "afl-qemu-trace");
ck_free(tmp);
*target_path_p = new_argv[0] = find_afl_binary(own_loc, "afl-wine-trace");
return new_argv;
}
@ -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.
If the env is not set, sets the env to default_signal for the signal handlers
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. */
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 */
u32 get_map_size(void) {
uint32_t map_size = 8000000; // a very large default map
uint32_t map_size = DEFAULT_SHMEM_SIZE;
char * ptr;
if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) {
@ -1151,7 +1104,7 @@ FILE *create_ffile(u8 *fn) {
s32 fd;
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); }
@ -1169,7 +1122,7 @@ s32 create_file(u8 *fn) {
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); }

View File

@ -809,7 +809,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
"have a\n"
" restrictive memory limit configured, this is expected; please "
"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);
} else if (!fsrv->mem_limit) {
@ -817,18 +817,21 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
SAYF("\n" cLRD "[-] " cRST
"Whoops, the target binary crashed suddenly, "
"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 "
"reporting.\n"
" Set a high value (e.g. AFL_MAP_SIZE=8000000) or use "
"AFL_DEBUG=1 to see the\n"
" message from the target binary\n\n"
" - The target binary crashes because necessary runtime "
"conditions 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"
" - 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"
" - Possibly the target requires a huge coverage map and has "
"CTORS.\n"
" Retry with setting AFL_MAP_SIZE=10000000.\n\n"
MSG_FORK_ON_APPLE
@ -844,13 +847,17 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
SAYF("\n" cLRD "[-] " cRST
"Whoops, the target binary crashed suddenly, "
"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 "
"reporting.\n"
" Set a high value (e.g. AFL_MAP_SIZE=8000000) or use "
"AFL_DEBUG=1 to see the\n"
" message from the target binary\n\n"
" - The target binary crashes because necessary runtime "
"conditions 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"
" - The current memory limit (%s) is too restrictive, causing "
"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 "
"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
" - 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 "
"options\n"
" 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"
" you have a restrictive memory limit configured, this is "
"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);
} else if (!fsrv->mem_limit) {
@ -911,10 +917,22 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
SAYF("\n" cLRD "[-] " cRST
"Hmm, looks like the target binary terminated before we could complete"
" a\n"
"handshake with the injected code.\n"
"Most likely the target has a huge coverage map, retry with setting"
" the\n"
"environment variable AFL_MAP_SIZE=8000000\n"
"handshake with the injected code. You can try the following:\n\n"
" - The target binary crashes because necessary runtime conditions "
"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"
"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
"Hmm, looks like the target binary terminated "
"before we could complete a\n"
" handshake with the injected code. There are %s probable "
"explanations:\n\n"
" handshake with the injected code. You can try the following:\n\n"
"%s"
" - Most likely the target has a huge coverage map, retry with "
"setting the\n"
" environment variable AFL_MAP_SIZE=8000000\n\n"
" - The target binary crashes because necessary runtime conditions "
"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"
" - The current memory limit (%s) is too restrictive, causing an "
"OOM\n"
@ -958,7 +985,6 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
"options\n"
" fail, poke <afl-users@googlegroups.com> for troubleshooting "
"tips.\n",
getenv(DEFER_ENV_VAR) ? "three" : "two",
getenv(DEFER_ENV_VAR)
? " - You are using deferred forkserver, but __AFL_INIT() is "
"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)) {
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 {
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;
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); }
@ -407,7 +407,7 @@ static void write_crash_readme(afl_state_t *afl) {
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. */
@ -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);
#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); }
ck_write(fd, mem, len, queue_fn);
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
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); }
ck_write(fd, mem, len, fn);
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);
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); }

View File

@ -152,7 +152,8 @@ void bind_to_free_cpu(afl_state_t *afl) {
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) {
@ -1219,7 +1220,7 @@ static void link_or_copy(u8 *old_path, u8 *new_path) {
sfd = open(old_path, O_RDONLY);
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); }
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 (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
ck_free(fn);
if (!afl->in_place_resume) {
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);
if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
@ -2008,17 +2013,35 @@ void setup_dirs_fds(afl_state_t *afl) {
/* Gnuplot output file. */
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->fsrv.plot_file) { PFATAL("fdopen() failed"); }
if (!afl->in_place_resume) {
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);
/* ignore errors */
@ -2035,7 +2058,7 @@ void setup_cmdline_file(afl_state_t *afl, char **argv) {
/* Store the command line to reproduce our findings */
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); }
ck_free(tmp);
@ -2070,7 +2093,8 @@ void setup_stdio_file(afl_state_t *afl) {
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) {
@ -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 ||
(afl->fsrv.qemu_mode && getenv("AFL_QEMU_CUSTOM_BIN")) ||
afl->non_instrumented_mode) {
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 */
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); }

View File

@ -5119,14 +5119,23 @@ pacemaker_fuzzing:
/* Update afl->pending_not_fuzzed count if we made it through the
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 &&
// !afl->queue_cur->was_fuzzed) {
if (!afl->queue_cur->was_fuzzed) {
// afl->queue_cur->was_fuzzed = 1;
// --afl->pending_not_fuzzed;
// if (afl->queue_cur->favored) --afl->pending_favored;
// }
--afl->pending_not_fuzzed;
afl->queue_cur->was_fuzzed = 1;
if (afl->queue_cur->favored) { --afl->pending_favored; }
}
}
*/
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,
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); }
close(fd);
@ -272,7 +272,7 @@ void mark_as_variable(afl_state_t *afl, struct queue_entry *q) {
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); }
close(fd);
@ -300,7 +300,7 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
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); }
close(fd);
@ -680,13 +680,17 @@ void cull_queue(afl_state_t *afl) {
}
afl->top_rated[i]->favored = 1;
++afl->queued_favored;
if (!afl->top_rated[i]->favored) {
if (afl->top_rated[i]->fuzz_level == 0 ||
!afl->top_rated[i]->was_fuzzed) {
afl->top_rated[i]->favored = 1;
++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++,
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)
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)) {
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 {
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 */
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);
/* 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);
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); }
@ -851,7 +855,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
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); }
@ -866,7 +870,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
} else {
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); }

View File

@ -433,6 +433,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_kill_signal =
(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 {

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,
"%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu, "
"%u\n",
get_cur_time() / 1000, afl->queue_cycle - 1, afl->current_entry,
afl->queued_paths, afl->pending_not_fuzzed, afl->pending_favored,
bitmap_cvg, afl->unique_crashes, afl->unique_hangs, afl->max_depth,
eps, afl->plot_prev_ed, t_bytes); /* ignore errors */
(afl->prev_run_time + get_cur_time() - afl->start_time),
afl->queue_cycle - 1, afl->current_entry, afl->queued_paths,
afl->pending_not_fuzzed, afl->pending_favored, bitmap_cvg,
afl->unique_crashes, afl->unique_hangs, afl->max_depth, eps,
afl->plot_prev_ed, t_bytes); /* ignore errors */
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_QUIET: suppress forkserver status messages\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_SKIP_BIN_CHECK: skip the check, if the target is an executable\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;
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) {
u8 *qemu_preload = getenv("QEMU_SET_ENV");
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);
/* afl-qemu-trace takes care of converting AFL_PRELOAD. */
} 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);
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 &&
!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.map_size = 8000000; // dummy temporary value
setenv("AFL_MAP_SIZE", "8000000", 1);
afl->fsrv.map_size = DEFAULT_SHMEM_SIZE; // dummy temporary value
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(
&afl->fsrv, afl->argv, &afl->stop_soon, afl->afl_env.afl_debug_child);
// only reinitialize when it makes sense
if ((map_size < new_map_size ||
(new_map_size != MAP_SIZE && new_map_size < map_size &&
map_size - new_map_size > MAP_SIZE))) {
// only reinitialize if the map needs to be larger than what we have.
if (map_size < 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) {
@ -1641,11 +1590,15 @@ int main(int argc, char **argv_orig, char **envp) {
afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary;
afl->cmplog_fsrv.init_child_func = cmplog_exec_child;
if (map_size <= 8000000 && !afl->non_instrumented_mode &&
!afl->fsrv.qemu_mode && !afl->unicorn_mode) {
if ((map_size <= DEFAULT_SHMEM_SIZE ||
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
setenv("AFL_MAP_SIZE", "8000000", 1);
afl->cmplog_fsrv.map_size = MAX(map_size, (u32)DEFAULT_SHMEM_SIZE);
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->afl_env.afl_debug_child);
} else {
afl->cmplog_fsrv.map_size = new_map_size;
}
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());
/* create the shared memory segment as if it was a file */
shm->g_shm_fd =
shm_open(shm->g_shm_file_path, O_CREAT | O_RDWR | O_EXCL, 0600);
shm->g_shm_fd = shm_open(shm->g_shm_file_path, O_CREAT | O_RDWR | O_EXCL,
DEFAULT_PERMISSION);
if (shm->g_shm_fd == -1) { PFATAL("shm_open() failed"); }
/* 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 */
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"); }
/* configure the size of the shared memory segment */
@ -241,13 +242,14 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size,
#else
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->cmplog_mode) {
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) {

View File

@ -252,7 +252,7 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
} else {
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); }
}
@ -599,38 +599,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
if (fsrv->qemu_mode) {
u8 *qemu_preload = getenv("QEMU_SET_ENV");
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);
/* afl-qemu-trace takes care of converting AFL_PRELOAD. */
} else {
@ -946,31 +915,6 @@ int main(int argc, char **argv_orig, char **envp) {
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 (!out_file && !collect_coverage)
@ -1175,7 +1119,8 @@ int main(int argc, char **argv_orig, char **envp) {
unlink(stdin_file);
atexit(at_exit_handler);
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 (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 */
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); }
@ -666,7 +666,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
unlink(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); }
@ -753,38 +753,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
if (fsrv->qemu_mode) {
u8 *qemu_preload = getenv("QEMU_SET_ENV");
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);
/* afl-qemu-trace takes care of converting AFL_PRELOAD. */
} else {
@ -1079,31 +1048,6 @@ int main(int argc, char **argv_orig, char **envp) {
check_environment_vars(envp);
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 */
shm.cmplog_mode = 0;

View File

@ -18,6 +18,10 @@
#include <sys/stat.h>
#include <fcntl.h>
#ifdef TEST_SHARED_OBJECT
#define main main_exported
#endif
int main(int argc, char **argv) {
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"
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 && {
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"

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'))

View File

@ -237,38 +237,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
if (fsrv->qemu_mode) {
u8 *qemu_preload = getenv("QEMU_SET_ENV");
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);
/* afl-qemu-trace takes care of converting AFL_PRELOAD. */
} else {

View File

@ -187,6 +187,8 @@ static int ExecuteFilesOnyByOne(int argc, char **argv) {
}
close(fd);
}
free(buf);
@ -208,6 +210,16 @@ int main(int argc, char **argv) {
"======================================================\n",
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;
maybe_duplicate_stderr();
maybe_close_fd_mask();

View File

@ -60,12 +60,12 @@ if
fi
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
fi
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
fi

View File

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