Merge pull request #542 from AFLplusplus/dev

push to stable
This commit is contained in:
van Hauser
2020-09-04 22:48:46 +02:00
committed by GitHub
24 changed files with 3720 additions and 3597 deletions

6
.gitmodules vendored
View File

@ -1,3 +1,7 @@
[submodule "unicorn_mode/unicornafl"] [submodule "unicorn_mode/unicornafl"]
path = unicorn_mode/unicornafl path = unicorn_mode/unicornafl
url = https://github.com/AFLplusplus/unicornafl.git url = https://github.com/AFLplusplus/unicornafl
[submodule "custom_mutators/Grammar-Mutator"]
path = custom_mutators/Grammar-Mutator
url = https://github.com/AFLplusplus/Grammar-Mutator

View File

@ -6,6 +6,7 @@ branches:
only: only:
- stable - stable
- dev - dev
- llvm_merge
matrix: matrix:
include: include:

View File

@ -530,7 +530,7 @@ clean:
$(MAKE) -C qemu_mode/libcompcov clean $(MAKE) -C qemu_mode/libcompcov clean
rm -rf qemu_mode/qemu-3.1.1 rm -rf qemu_mode/qemu-3.1.1
ifeq "$(IN_REPO)" "1" ifeq "$(IN_REPO)" "1"
test -d unicorn_mode/unicornafl && $(MAKE) -C unicorn_mode/unicornafl clean || true test -e unicorn_mode/unicornafl/Makefile && $(MAKE) -C unicorn_mode/unicornafl clean || true
else else
rm -rf qemu_mode/qemu-3.1.1.tar.xz rm -rf qemu_mode/qemu-3.1.1.tar.xz
rm -rf unicorn_mode/unicornafl rm -rf unicorn_mode/unicornafl

View File

@ -1035,6 +1035,7 @@ without feedback, bug reports, or patches from:
Andrea Biondo Vincent Le Garrec Andrea Biondo Vincent Le Garrec
Khaled Yakdan Kuang-che Wu Khaled Yakdan Kuang-che Wu
Josephine Calliotte Konrad Welc Josephine Calliotte Konrad Welc
Thomas Rooijakkers
``` ```
Thank you! Thank you!

View File

@ -7,7 +7,6 @@
- afl-plot to support multiple plot_data - afl-plot to support multiple plot_data
- afl_custom_fuzz_splice_optin() - afl_custom_fuzz_splice_optin()
- intel-pt tracer - intel-pt tracer
- honor -O flags and -fno-unroll-loops in afl-cc
## Further down the road ## Further down the road
@ -22,7 +21,6 @@ gcc_plugin:
- (wait for submission then decide) - (wait for submission then decide)
qemu_mode: qemu_mode:
- update to 5.x (if the performance bug is gone)
- non colliding instrumentation - non colliding instrumentation
- rename qemu specific envs to AFL_QEMU (AFL_ENTRYPOINT, AFL_CODE_START/END, - rename qemu specific envs to AFL_QEMU (AFL_ENTRYPOINT, AFL_CODE_START/END,
AFL_COMPCOV_LEVEL?) AFL_COMPCOV_LEVEL?)

View File

@ -99,7 +99,7 @@ fi
fmt_duration() fmt_duration()
{ {
DUR_STRING= DUR_STRING=
if [ $1 -eq 0 ]; then if [ $1 -le 0 ]; then
return 1 return 1
fi fi
@ -109,7 +109,11 @@ fmt_duration()
local minutes=$(((duration / 60) % 60)) local minutes=$(((duration / 60) % 60))
local seconds=$((duration % 60)) local seconds=$((duration % 60))
if [ $days -gt 0 ]; then if [ $duration -le 0 ]; then
DUR_STRING="0 seconds"
elif [ $duration -eq 1 ]; then
DUR_STRING="1 second"
elif [ $days -gt 0 ]; then
DUR_STRING="$days days, $hours hours" DUR_STRING="$days days, $hours hours"
elif [ $hours -gt 0 ]; then elif [ $hours -gt 0 ]; then
DUR_STRING="$hours hours, $minutes minutes" DUR_STRING="$hours hours, $minutes minutes"

View File

@ -3,6 +3,22 @@
Custom mutators enhance and alter the mutation strategies of afl++. Custom mutators enhance and alter the mutation strategies of afl++.
For further information and documentation on how to write your own, read [the docs](../docs/custom_mutators.md). For further information and documentation on how to write your own, read [the docs](../docs/custom_mutators.md).
## The afl++ Grammar Mutator
If you use git to clone afl++, then the following will incorporate our
excellent grammar custom mutator:
```
git submodule init
git submodule update
```
otherwise just checkout the repository here with either
`git clone https://github.com/AFLplusplus/Grammar-Mutator` or
`svn co https://github.com/AFLplusplus/Grammar-Mutator`.
Read the [Grammar-Mutator/README.md](Grammar-Mutator/README.md) on how to use
it.
## Production-Ready Custom Mutators ## Production-Ready Custom Mutators
This directory holds ready to use custom mutators. This directory holds ready to use custom mutators.

View File

@ -10,22 +10,28 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
### Version ++2.67d (develop) ### Version ++2.67d (develop)
- added the GSoC excellent afl++ grammar mutator by Shengtuo to our
custom_mutators/ (see custom_mutators/README.md) - or get it here:
https://github.com/AFLplusplus/Grammar-Mutator
- a few QOL changes for Apple and its outdated gmake - a few QOL changes for Apple and its outdated gmake
- afl-fuzz: - afl-fuzz:
- Fix for auto dictionary entries found during fuzzing to not throw out - fix for auto dictionary entries found during fuzzing to not throw out
a -x dictionary a -x dictionary
- added total execs done to plot file - added total execs done to plot file
- AFL_MAX_DET_EXTRAS env variable added to control the amount of deterministic - AFL_MAX_DET_EXTRAS env variable added to control the amount of
dict entries without recompiling. deterministic dict entries without recompiling.
- AFL_FORKSRV_INIT_TMOUT env variable added to control the time to wait for - AFL_FORKSRV_INIT_TMOUT env variable added to control the time to wait
the forkserver to come up without the need to increase the overall timeout. for the forkserver to come up without the need to increase the overall
timeout.
- bugfix for cmplog that results in a heap overflow based on target data - bugfix for cmplog that results in a heap overflow based on target data
(thanks to the magma team for reporting!) (thanks to the magma team for reporting!)
- write fuzzing setup into out/fuzzer_setup (environment variables and
command line)
- custom mutators: - custom mutators:
- added afl_custom_fuzz_count/fuzz_count function to allow specifying the - added afl_custom_fuzz_count/fuzz_count function to allow specifying
number of fuzz attempts for custom_fuzz the number of fuzz attempts for custom_fuzz
- llvm_mode: - llvm_mode:
- Ported SanCov to LTO, and made it the default for LTO. better - ported SanCov to LTO, and made it the default for LTO. better
instrumentation locations instrumentation locations
- Further llvm 12 support (fast moving target like afl++ :-) ) - Further llvm 12 support (fast moving target like afl++ :-) )
- deprecated LLVM SKIPSINGLEBLOCK env environment - deprecated LLVM SKIPSINGLEBLOCK env environment

View File

@ -4,11 +4,11 @@
* [What is the difference between afl and afl++?](#what-is-the-difference-between-afl-and-afl) * [What is the difference between afl and afl++?](#what-is-the-difference-between-afl-and-afl)
* [How to improve the fuzzing speed?](#how-to-improve-the-fuzzing-speed) * [How to improve the fuzzing speed?](#how-to-improve-the-fuzzing-speed)
* [How do I fuzz a network service?](#how-to-fuzz-a-network-service) * [How do I fuzz a network service?](#how-do-i-fuzz-a-network-service)
* [How do I fuzz a GUI program?](#how-to-fuzz-a-gui-program) * [How do I fuzz a GUI program?](#how-do-i-fuzz-a-gui-program)
* [What is an edge?](#what-is-an-edge) * [What is an edge?](#what-is-an-edge)
* [Why is my stability below 100%?](#why-is-my-stability-below-100) * [Why is my stability below 100%?](#why-is-my-stability-below-100)
* [How can I improve the stability value](#how-can-i-improve-the-stability-value) * [How can I improve the stability value?](#how-can-i-improve-the-stability-value)
If you find an interesting or important question missing, submit it via If you find an interesting or important question missing, submit it via
[https://github.com/AFLplusplus/AFLplusplus/issues](https://github.com/AFLplusplus/AFLplusplus/issues) [https://github.com/AFLplusplus/AFLplusplus/issues](https://github.com/AFLplusplus/AFLplusplus/issues)
@ -18,51 +18,52 @@ If you find an interesting or important question missing, submit it via
American Fuzzy Lop (AFL) was developed by Michał "lcamtuf" Zalewski starting in American Fuzzy Lop (AFL) was developed by Michał "lcamtuf" Zalewski starting in
2013/2014, and when he left Google end of 2017 he stopped developing it. 2013/2014, and when he left Google end of 2017 he stopped developing it.
At the end of 2019 the Google fuzzing team took over maintance of AFL, however At the end of 2019 the Google fuzzing team took over maintenance of AFL, however
it is only accepting PR from the community and is not developing enhancements it is only accepting PRs from the community and is not developing enhancements
anymore. anymore.
In the second quarter of 2019, 1 1/2 years after no further development of In the second quarter of 2019, 1 1/2 year later when no further development of
AFL had happened and it became clear there would be none coming, afl++ AFL had happened and it became clear there would none be coming, afl++
was born, where initially first community patches were collected and applied was born, where initially community patches were collected and applied
for bugs and enhancements. Then from various AFL spin-offs - mostly academic for bug fixes and enhancements. Then from various AFL spin-offs - mostly academic
research - features were integrated. This already resulted in a much advanced research - features were integrated. This already resulted in a much advanced
AFL. AFL.
Until the end of 2019 the afl++ team had grown to four active developers which Until the end of 2019 the afl++ team had grown to four active developers which
then implemented their own research and feature, making it now by far the most then implemented their own research and features, making it now by far the most
flexible and feature rich guided fuzzer available as open source. flexible and feature rich guided fuzzer available as open source.
And in independent fuzzing benchmarks it is one of the best fuzzers available, And in independent fuzzing benchmarks it is one of the best fuzzers available,
e.g. [Fuzzbench Report](https://www.fuzzbench.com/reports/2020-08-03/index.html) e.g. [Fuzzbench Report](https://www.fuzzbench.com/reports/2020-08-03/index.html)
## How to improve the fuzzing speed ## How to improve the fuzzing speed?
1. use [llvm_mode](docs/llvm_mode/README.md): afl-clang-lto (llvm >= 11) or afl-clang-fast (llvm >= 9 recommended) 1. Use [llvm_mode](docs/llvm_mode/README.md): afl-clang-lto (llvm >= 11) or afl-clang-fast (llvm >= 9 recommended)
2. Use [persistent mode](llvm_mode/README.persistent_mode.md) (x2-x20 speed increase) 2. Use [persistent mode](llvm_mode/README.persistent_mode.md) (x2-x20 speed increase)
3. Use the [afl++ snapshot module](https://github.com/AFLplusplus/AFL-Snapshot-LKM) (x2 speed increase) 3. Use the [afl++ snapshot module](https://github.com/AFLplusplus/AFL-Snapshot-LKM) (x2 speed increase)
4. If you do not use shmem persistent mode, use `AFL_TMPDIR` to point the input file on a tempfs location, see [docs/env_variables.md](docs/env_variables.md) 4. If you do not use shmem persistent mode, use `AFL_TMPDIR` to put the input file directory on a tempfs location, see [docs/env_variables.md](docs/env_variables.md)
5. Improve kernel performance: modify `/etc/default/grub`, set `GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=off l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs nopcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off"`; then `update-grub` and `reboot` (warning: makes the system more insecure) 5. Improve Linux kernel performance: modify `/etc/default/grub`, set `GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=off l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs nopcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off"`; then `update-grub` and `reboot` (warning: makes the system less secure)
6. Running on an `ext2` filesystem with `noatime` mount option will be a bit faster than on any other journaling filesystem 6. Running on an `ext2` filesystem with `noatime` mount option will be a bit faster than on any other journaling filesystem
7. Use your cores! [README.md:3.b) Using multiple cores/threads](../README.md#b-using-multiple-coresthreads) 7. Use your cores! [README.md:3.b) Using multiple cores/threads](../README.md#b-using-multiple-coresthreads)
## How do I fuzz a network service? ## How do I fuzz a network service?
The short answer is - you cannot, at least "out of the box". The short answer is - you cannot, at least not "out of the box".
Using network has a slow-down of x10-20 on the fuzzing speed, does not scale, Using a network channel is inadequate for several reasons:
and finally usually it is more than one initial data packet but a back-and-forth - it has a slow-down of x10-20 on the fuzzing speed
which is totally unsupported by most coverage aware fuzzers. - it does not scale to fuzzing multiple instances easily,
- instead of one initial data packet often a back-and-forth interplay of packets is needed for stateful protocols (which is totally unsupported by most coverage aware fuzzers).
The established method to fuzz network services is to modify the source code The established method to fuzz network services is to modify the source code
to read from a file or stdin (fd 0) (or even faster via shared memory, combine to read from a file or stdin (fd 0) (or even faster via shared memory, combine
this with persistent mode [llvm_mode/README.persistent_mode.md](llvm_mode/README.persistent_mode.md) this with persistent mode [llvm_mode/README.persistent_mode.md](llvm_mode/README.persistent_mode.md)
and you have a performance gain of x10 instead of a performance loss of over and you have a performance gain of x10 instead of a performance loss of over
x10 - that is a x100 difference! x10 - that is a x100 difference!).
If modifying the source is not an option (e.g. because you only have a binary If modifying the source is not an option (e.g. because you only have a binary
and perform binary fuzzing) you can also use a shared library with AFL_PRELOAD and perform binary fuzzing) you can also use a shared library with AFL_PRELOAD
to emulate the network. This is also much faster than network would be. to emulate the network. This is also much faster than the real network would be.
See [examples/socket_fuzzing/](../examples/socket_fuzzing/) See [examples/socket_fuzzing/](../examples/socket_fuzzing/).
There is an outdated afl++ branch that implements networking if you are There is an outdated afl++ branch that implements networking if you are
desperate though: [https://github.com/AFLplusplus/AFLplusplus/tree/networking](https://github.com/AFLplusplus/AFLplusplus/tree/networking) - desperate though: [https://github.com/AFLplusplus/AFLplusplus/tree/networking](https://github.com/AFLplusplus/AFLplusplus/tree/networking) -
@ -73,7 +74,7 @@ which allows you to define network state with different type of data packets.
If the GUI program can read the fuzz data from a file (via the command line, If the GUI program can read the fuzz data from a file (via the command line,
a fixed location or via an environment variable) without needing any user a fixed location or via an environment variable) without needing any user
interaction then then yes. interaction then it would be suitable for fuzzing.
Otherwise it is not possible without modifying the source code - which is a Otherwise it is not possible without modifying the source code - which is a
very good idea anyway as the GUI functionality is a huge CPU/time overhead very good idea anyway as the GUI functionality is a huge CPU/time overhead
@ -82,13 +83,13 @@ for the fuzzing.
So create a new `main()` that just reads the test case and calls the So create a new `main()` that just reads the test case and calls the
functionality for processing the input that the GUI program is using. functionality for processing the input that the GUI program is using.
## What is an "edge" ## What is an "edge"?
A program contains `functions`, `functions` contain the compiled machine code. A program contains `functions`, `functions` contain the compiled machine code.
The compiled machine code in a `function` can be in a single or many `basic blocks`. The compiled machine code in a `function` can be in a single or many `basic blocks`.
A `basic block` is the largest possible number of subsequent machine code A `basic block` is the largest possible number of subsequent machine code
instructions that runs independent, meaning it does not split up to different instructions that has exactly one entrypoint (which can be be entered by multiple other basic blocks)
locations nor is it jumped into it from a different location: and runs linearly without branching or jumping to other addresses (except at the end).
``` ```
function() { function() {
A: A:
@ -98,7 +99,7 @@ function() {
if (x) goto C; else goto D; if (x) goto C; else goto D;
C: C:
some code some code
goto D goto E
D: D:
some code some code
goto B goto B
@ -108,7 +109,7 @@ function() {
``` ```
Every code block between two jump locations is a `basic block`. Every code block between two jump locations is a `basic block`.
An `edge` is then the unique relationship between two `basic blocks` (from the An `edge` is then the unique relationship between two directly connected `basic blocks` (from the
code example above): code example above):
``` ```
Block A Block A
@ -123,8 +124,9 @@ code example above):
Block E Block E
``` ```
Every line between two blocks is an `edge`. Every line between two blocks is an `edge`.
Note that a few basic block loop to itself, this too would be an edge.
## Why is my stability below 100% ## Why is my stability below 100%?
Stability is measured by how many percent of the edges in the target are Stability is measured by how many percent of the edges in the target are
"stable". Sending the same input again and again should take the exact same "stable". Sending the same input again and again should take the exact same
@ -132,37 +134,37 @@ path through the target every time. If that is the case, the stability is 100%.
If however randomness happens, e.g. a thread reading other external data, If however randomness happens, e.g. a thread reading other external data,
reaction to timing, etc. then in some of the re-executions with the same data reaction to timing, etc. then in some of the re-executions with the same data
the result in the edge information will be different accross runs. the edge coverage result will be different accross runs.
Those edges that change are then flagged "unstable". Those edges that change are then flagged "unstable".
The more "unstable" edges, the more difficult for afl++ to identify valid new The more "unstable" edges, the more difficult for afl++ to identify valid new
paths. paths.
A value above 90% is usually fine and a value above 80% is also still ok, and A value above 90% is usually fine and a value above 80% is also still ok, and
even above 20% can still result in successful finds of bugs. even a value above 20% can still result in successful finds of bugs.
However, it is recommended that below 90% or 80% you should take measures to However, it is recommended that for values below 90% or 80% you should take
improve the stability. countermeasures to improve stability.
## How can I improve the stability value ## How can I improve the stability value?
For fuzzing a 100% stable target that covers all edges is the best. For fuzzing a 100% stable target that covers all edges is the best case.
A 90% stable target that covers all edges is however better than a 100% stable A 90% stable target that covers all edges is however better than a 100% stable
target that ignores 10% of the edges. target that ignores 10% of the edges.
With instability you basically have a partial coverage loss on an edge, with With instability you basically have a partial coverage loss on an edge, with
ignore you have a full loss on that edge. ignored functions you have a full loss on that edges.
There are functions that are unstable, but also provide value to coverage, eg There are functions that are unstable, but also provide value to coverage, eg
init functions that use fuzz data as input for example. init functions that use fuzz data as input for example.
If however it is a function that has nothing to do with the input data is the If however a function that has nothing to do with the input data is the
source, e.g. checking jitter, or is a hash map function etc. then it should source of instability, e.g. checking jitter, or is a hash map function etc.
not be instrumented. then it should not be instrumented.
To be able to make this decision the following process will allow you to To be able to exclude these functions (based on AFL++'s measured stability)
identify the functions with variable edges so you can make this decision. the following process will allow to identify functions with variable edges.
Four steps are required to do this and requires quite some knowledge of Four steps are required to do this and it also requires quite some knowledge
coding and/or disassembly and it is only effectively possible with of coding and/or disassembly and is effectively possible only with
afl-clang-fast PCGUARD and afl-clang-lto LTO instrumentation. afl-clang-fast PCGUARD and afl-clang-lto LTO instrumentation.
1. First step: Identify which edge ID numbers are unstable 1. First step: Identify which edge ID numbers are unstable
@ -171,7 +173,7 @@ afl-clang-fast PCGUARD and afl-clang-lto LTO instrumentation.
The out/fuzzer_stats file will then show the edge IDs that were identified The out/fuzzer_stats file will then show the edge IDs that were identified
as unstable. as unstable.
2. Second step: Find the responsible function. 2. Second step: Find the responsible function(s).
a) For LTO instrumented binaries this can be documented during compile a) For LTO instrumented binaries this can be documented during compile
time, just set `export AFL_LLVM_DOCUMENT_IDS=/path/to/a/file`. time, just set `export AFL_LLVM_DOCUMENT_IDS=/path/to/a/file`.
@ -191,20 +193,20 @@ afl-clang-fast PCGUARD and afl-clang-lto LTO instrumentation.
and set a write breakpoint to that address (`watch 0x.....`). and set a write breakpoint to that address (`watch 0x.....`).
c) in all other instrumentation types this is not possible. So just c) in all other instrumentation types this is not possible. So just
recompile with the the two mentioned above. This is just for recompile with the two mentioned above. This is just for
identifying the functions that have unstable edges. identifying the functions that have unstable edges.
3. Third step: create a text file with the filenames/functions 3. Third step: create a text file with the filenames/functions
Identify which source code files contain the functions that you need to Identify which source code files contain the functions that you need to
remove from instrumentation, or just specify the functions you want to remove from instrumentation, or just specify the functions you want to
skip instrumenting. Note that optimization might inline functions! skip for instrumentation. Note that optimization might inline functions!
Simply follow this document on how to do this: [llvm_mode/README.instrument_list.md](llvm_mode/README.instrument_list.md) Simply follow this document on how to do this: [llvm_mode/README.instrument_list.md](llvm_mode/README.instrument_list.md)
If PCGUARD is used, then you need to follow this guide (needs llvm 12+!): If PCGUARD is used, then you need to follow this guide (needs llvm 12+!):
[http://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation](http://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation) [http://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation](http://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation)
Only deny those functions from instrumentation that provide no value Only exclude those functions from instrumentation that provide no value
for coverage - that is if it does not process any fuzz data directly for coverage - that is if it does not process any fuzz data directly
or indirectly (e.g. hash maps, thread management etc.). or indirectly (e.g. hash maps, thread management etc.).
If however a function directly or indirectly handles fuzz data then you If however a function directly or indirectly handles fuzz data then you

View File

@ -6,6 +6,8 @@
void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) { void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
if (Size < 5) return;
if (Data[0] == 'F') if (Data[0] == 'F')
if (Data[1] == 'A') if (Data[1] == 'A')
if (Data[2] == '$') if (Data[2] == '$')
@ -16,12 +18,11 @@ void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
fprintf(stderr, "FUNC crc: %016llx len: %lu\n", if (Size)
hash64((u8 *)Data, (unsigned int)Size, fprintf(stderr, "FUNC crc: %016llx len: %lu\n",
(unsigned long long int)0xa5b35705), hash64((u8 *)Data, (unsigned int)Size,
Size); (unsigned long long int)0xa5b35705),
Size);
if (Size < 5) return 0;
crashme(Data, Size); crashme(Data, Size);

View File

@ -945,6 +945,7 @@ void destroy_extras(afl_state_t *);
/* Stats */ /* Stats */
void write_setup_file(afl_state_t *, u32, char **);
void write_stats_file(afl_state_t *, double, double, double); void write_stats_file(afl_state_t *, double, double, double);
void maybe_update_plot_file(afl_state_t *, double, double); void maybe_update_plot_file(afl_state_t *, double, double);
void show_stats(afl_state_t *); void show_stats(afl_state_t *);

View File

@ -110,5 +110,11 @@ u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms);
/* Reads the map size from ENV */ /* Reads the map size from ENV */
u32 get_map_size(void); u32 get_map_size(void);
/* create a stream file */
FILE *create_ffile(u8 *fn);
/* create a file */
s32 create_file(u8 *fn);
#endif #endif

View File

@ -112,12 +112,16 @@ static char *afl_environment_variables[] = {
"AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_COMPCOV_DEBUG",
"AFL_QEMU_DEBUG_MAPS", "AFL_QEMU_DEBUG_MAPS",
"AFL_QEMU_DISABLE_CACHE", "AFL_QEMU_DISABLE_CACHE",
"AFL_QEMU_DRIVER_NO_HOOK",
"AFL_QEMU_PERSISTENT_ADDR", "AFL_QEMU_PERSISTENT_ADDR",
"AFL_QEMU_PERSISTENT_CNT", "AFL_QEMU_PERSISTENT_CNT",
"AFL_QEMU_PERSISTENT_GPR", "AFL_QEMU_PERSISTENT_GPR",
"AFL_QEMU_PERSISTENT_HOOK", "AFL_QEMU_PERSISTENT_HOOK",
"AFL_QEMU_PERSISTENT_RET", "AFL_QEMU_PERSISTENT_RET",
"AFL_QEMU_PERSISTENT_RETADDR_OFFSET", "AFL_QEMU_PERSISTENT_RETADDR_OFFSET",
"AFL_QEMU_PERSISTENT_EXITS",
"AFL_QEMU_INST_RANGES",
"AFL_QEMU_SNAPSHOT",
"AFL_QUIET", "AFL_QUIET",
"AFL_RANDOM_ALLOC_CANARY", "AFL_RANDOM_ALLOC_CANARY",
"AFL_REAL_PATH", "AFL_REAL_PATH",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -217,6 +217,12 @@ ifeq "$(LLVM_LTO)" "1"
endif endif
endif endif
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fdebug-prefix-map=$(CURDIR)=llvm_mode -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
AFL_CLANG_DEBUG_PREFIX = -fdebug-prefix-map="$(CURDIR)=llvm_mode"
else
AFL_CLANG_DEBUG_PREFIX = ""
endif
CFLAGS ?= -O3 -funroll-loops -fPIC -D_FORTIFY_SOURCE=2 CFLAGS ?= -O3 -funroll-loops -fPIC -D_FORTIFY_SOURCE=2
CFLAGS_SAFE := -Wall -g -Wno-pointer-sign -I ../include/ \ CFLAGS_SAFE := -Wall -g -Wno-pointer-sign -I ../include/ \
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \ -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
@ -227,7 +233,7 @@ CFLAGS_SAFE := -Wall -g -Wno-pointer-sign -I ../include/ \
-DAFL_CLANG_LDPATH=\"$(AFL_CLANG_LDPATH)\" \ -DAFL_CLANG_LDPATH=\"$(AFL_CLANG_LDPATH)\" \
-DAFL_CLANG_FUSELD=\"$(AFL_CLANG_FUSELD)\" \ -DAFL_CLANG_FUSELD=\"$(AFL_CLANG_FUSELD)\" \
-DCLANG_BIN=\"$(CLANG_BIN)\" -DCLANGPP_BIN=\"$(CLANGPP_BIN)\" -DUSE_BINDIR=$(USE_BINDIR) -Wno-unused-function \ -DCLANG_BIN=\"$(CLANG_BIN)\" -DCLANGPP_BIN=\"$(CLANGPP_BIN)\" -DUSE_BINDIR=$(USE_BINDIR) -Wno-unused-function \
-fdebug-prefix-map="$(CURDIR)=llvm_mode" $(AFL_CLANG_DEBUG_PREFIX)
override CFLAGS += $(CFLAGS_SAFE) override CFLAGS += $(CFLAGS_SAFE)
ifdef AFL_TRACE_PC ifdef AFL_TRACE_PC

View File

@ -356,6 +356,8 @@ bool SplitComparesTransform::simplifyIntSignedness(Module &M) {
* all signed compares to icomps vector */ * all signed compares to icomps vector */
for (auto &F : M) { for (auto &F : M) {
if (!isInInstrumentList(&F)) continue;
for (auto &BB : F) { for (auto &BB : F) {
for (auto &IN : BB) { for (auto &IN : BB) {
@ -542,6 +544,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
* functions were executed only these four predicates should exist */ * functions were executed only these four predicates should exist */
for (auto &F : M) { for (auto &F : M) {
if (!isInInstrumentList(&F)) continue;
for (auto &BB : F) { for (auto &BB : F) {
for (auto &IN : BB) { for (auto &IN : BB) {
@ -1052,6 +1056,8 @@ size_t SplitComparesTransform::splitIntCompares(Module &M, unsigned bitw) {
* were executed only these four predicates should exist */ * were executed only these four predicates should exist */
for (auto &F : M) { for (auto &F : M) {
if (!isInInstrumentList(&F)) continue;
for (auto &BB : F) { for (auto &BB : F) {
for (auto &IN : BB) { for (auto &IN : BB) {

View File

@ -877,3 +877,36 @@ u32 get_map_size(void) {
} }
/* Create a stream file */
FILE *create_ffile(u8 *fn) {
s32 fd;
FILE *f;
fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
f = fdopen(fd, "w");
if (!f) { PFATAL("fdopen() failed"); }
return f;
}
/* Create a file */
s32 create_file(u8 *fn) {
s32 fd;
fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
return fd;
}

View File

@ -240,6 +240,23 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
if (!child_pid) { // New child if (!child_pid) { // New child
close(fsrv->out_dir_fd);
close(fsrv->dev_null_fd);
close(fsrv->dev_urandom_fd);
if (fsrv->plot_file != NULL) {
fclose(fsrv->plot_file);
fsrv->plot_file = NULL;
}
// enable terminating on sigpipe in the childs
struct sigaction sa;
memset((char *)&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
sigaction(SIGPIPE, &sa, NULL);
signal(SIGCHLD, old_sigchld_handler); signal(SIGCHLD, old_sigchld_handler);
// FORKSRV_FD is for communication with AFL, we don't need it in the // FORKSRV_FD is for communication with AFL, we don't need it in the
// child. // child.
@ -361,11 +378,16 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
/* CHILD PROCESS */ /* CHILD PROCESS */
// enable terminating on sigpipe in the childs
struct sigaction sa;
memset((char *)&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
sigaction(SIGPIPE, &sa, NULL);
struct rlimit r; struct rlimit r;
/* Umpf. On OpenBSD, the default fd limit for root users is set to /* Umpf. On OpenBSD, the default fd limit for root users is set to
soft 128. Let's try to fix that... */ soft 128. Let's try to fix that... */
if (!getrlimit(RLIMIT_NOFILE, &r) && r.rlim_cur < FORKSRV_FD + 2) { if (!getrlimit(RLIMIT_NOFILE, &r) && r.rlim_cur < FORKSRV_FD + 2) {
r.rlim_cur = FORKSRV_FD + 2; r.rlim_cur = FORKSRV_FD + 2;
@ -432,7 +454,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
close(fsrv->dev_null_fd); close(fsrv->dev_null_fd);
close(fsrv->dev_urandom_fd); close(fsrv->dev_urandom_fd);
if (fsrv->plot_file != NULL) { fclose(fsrv->plot_file); } if (fsrv->plot_file != NULL) {
fclose(fsrv->plot_file);
fsrv->plot_file = NULL;
}
/* This should improve performance a bit, since it stops the linker from /* This should improve performance a bit, since it stops the linker from
doing extra work post-fork(). */ doing extra work post-fork(). */

View File

@ -138,9 +138,9 @@ static u8 check_if_text(struct queue_entry *q) {
} }
// non-overlong 2-byte // non-overlong 2-byte
if (((0xC2 <= buf[offset + 0] && buf[offset + 0] <= 0xDF) && if (len - offset > 1 &&
(0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF)) && ((0xC2 <= buf[offset + 0] && buf[offset + 0] <= 0xDF) &&
len - offset > 1) { (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF))) {
offset += 2; offset += 2;
utf8++; utf8++;

View File

@ -265,7 +265,7 @@ static u8 its_fuzz(afl_state_t *afl, u8 *buf, u32 len, u8 *status) {
} }
static int strntoll(const char *str, size_t sz, char **end, int base, static int strntoll(const char *str, size_t sz, char **end, int base,
long long* out) { long long *out) {
char buf[64]; char buf[64];
long long ret; long long ret;
@ -273,16 +273,13 @@ static int strntoll(const char *str, size_t sz, char **end, int base,
for (; beg && sz && *beg == ' '; beg++, sz--) {}; for (; beg && sz && *beg == ' '; beg++, sz--) {};
if (!sz) if (!sz) return 1;
return 1; if (sz >= sizeof(buf)) sz = sizeof(buf) - 1;
if (sz >= sizeof(buf))
sz = sizeof(buf) -1;
memcpy(buf, beg, sz); memcpy(buf, beg, sz);
buf[sz] = '\0'; buf[sz] = '\0';
ret = strtoll(buf, end, base); ret = strtoll(buf, end, base);
if ((ret == LLONG_MIN || ret == LLONG_MAX) && errno == ERANGE) if ((ret == LLONG_MIN || ret == LLONG_MAX) && errno == ERANGE) return 1;
return 1;
if (end) *end = (char *)beg + (*end - buf); if (end) *end = (char *)beg + (*end - buf);
*out = ret; *out = ret;
@ -291,7 +288,7 @@ static int strntoll(const char *str, size_t sz, char **end, int base,
} }
static int strntoull(const char *str, size_t sz, char **end, int base, static int strntoull(const char *str, size_t sz, char **end, int base,
unsigned long long* out) { unsigned long long *out) {
char buf[64]; char buf[64];
unsigned long long ret; unsigned long long ret;
@ -300,16 +297,13 @@ static int strntoull(const char *str, size_t sz, char **end, int base,
for (; beg && sz && *beg == ' '; beg++, sz--) for (; beg && sz && *beg == ' '; beg++, sz--)
; ;
if (!sz) if (!sz) return 1;
return 1; if (sz >= sizeof(buf)) sz = sizeof(buf) - 1;
if (sz >= sizeof(buf))
sz = sizeof(buf) -1;
memcpy(buf, beg, sz); memcpy(buf, beg, sz);
buf[sz] = '\0'; buf[sz] = '\0';
ret = strtoull(buf, end, base); ret = strtoull(buf, end, base);
if (ret == ULLONG_MAX && errno == ERANGE) if (ret == ULLONG_MAX && errno == ERANGE) return 1;
return 1;
if (end) *end = (char *)beg + (*end - buf); if (end) *end = (char *)beg + (*end - buf);
*out = ret; *out = ret;
@ -350,6 +344,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
use_unum = 1; use_unum = 1;
} else } else
use_num = 1; use_num = 1;
} }

View File

@ -24,8 +24,64 @@
*/ */
#include "afl-fuzz.h" #include "afl-fuzz.h"
#include "envs.h"
#include <limits.h> #include <limits.h>
/* Write fuzzer setup file */
void write_setup_file(afl_state_t *afl, u32 argc, char **argv) {
char *val;
u8 fn[PATH_MAX];
snprintf(fn, PATH_MAX, "%s/fuzzer_setup", afl->out_dir);
FILE *f = create_ffile(fn);
u32 i;
fprintf(f, "# environment variables:\n");
u32 s_afl_env = (u32)
sizeof(afl_environment_variables) / sizeof(afl_environment_variables[0]) -
1U;
for (i = 0; i < s_afl_env; ++i) {
if ((val = getenv(afl_environment_variables[i])) != NULL) {
fprintf(f, "%s=%s\n", afl_environment_variables[i], val);
}
}
fprintf(f, "# command line:\n");
size_t j;
for (i = 0; i < argc; ++i) {
if (i) fprintf(f, " ");
if (index(argv[i], '\'')) {
fprintf(f, "'");
for (j = 0; j < strlen(argv[i]); j++)
if (argv[i][j] == '\'')
fprintf(f, "'\"'\"'");
else
fprintf(f, "%c", argv[i][j]);
fprintf(f, "'");
} else {
fprintf(f, "'%s'", argv[i]);
}
}
fprintf(f, "\n");
fclose(f);
(void)(afl_environment_deprecated);
}
/* Update stats file for unattended monitoring. */ /* Update stats file for unattended monitoring. */
void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
@ -35,21 +91,13 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
struct rusage rus; struct rusage rus;
#endif #endif
unsigned long long int cur_time = get_cur_time(); u64 cur_time = get_cur_time();
u8 fn[PATH_MAX]; u32 t_bytes = count_non_255_bytes(afl, afl->virgin_bits);
s32 fd; u8 fn[PATH_MAX];
FILE * f; FILE *f;
u32 t_bytes = count_non_255_bytes(afl, afl->virgin_bits);
snprintf(fn, PATH_MAX, "%s/fuzzer_stats", afl->out_dir); snprintf(fn, PATH_MAX, "%s/fuzzer_stats", afl->out_dir);
f = create_ffile(fn);
fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
f = fdopen(fd, "w");
if (!f) { PFATAL("fdopen() failed"); }
/* Keep last values in case we're called from another context /* Keep last values in case we're called from another context
where exec/sec stats and such are not readily available. */ where exec/sec stats and such are not readily available. */
@ -163,11 +211,12 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
? "" ? ""
: "default", : "default",
afl->orig_cmdline); afl->orig_cmdline);
/* ignore errors */ /* ignore errors */
if (afl->debug) { if (afl->debug) {
uint32_t i = 0; u32 i = 0;
fprintf(f, "virgin_bytes :"); fprintf(f, "virgin_bytes :");
for (i = 0; i < afl->fsrv.map_size; i++) { for (i = 0; i < afl->fsrv.map_size; i++) {

View File

@ -1128,6 +1128,8 @@ int main(int argc, char **argv_orig, char **envp) {
setup_custom_mutators(afl); setup_custom_mutators(afl);
write_setup_file(afl, argc, argv);
setup_cmdline_file(afl, argv + optind); setup_cmdline_file(afl, argv + optind);
read_testcases(afl); read_testcases(afl);

View File

@ -22,7 +22,10 @@
#include <stdint.h> #include <stdint.h>
#include "afl-fuzz.h" #include "afl-fuzz.h"
#include "types.h" #include "types.h"
#include "xxh3.h"
#define XXH_INLINE_ALL
#include "xxhash.h"
#undef XXH_INLINE_ALL
/* we use xoshiro256** instead of rand/random because it is 10x faster and has /* we use xoshiro256** instead of rand/random because it is 10x faster and has
better randomness properties. */ better randomness properties. */