Index: third_party/afl/src/docs/notes_for_asan.txt |
diff --git a/third_party/afl/src/docs/notes_for_asan.txt b/third_party/afl/src/docs/notes_for_asan.txt |
new file mode 100644 |
index 0000000000000000000000000000000000000000..649bb29a314d698e463eac8420ae2a44e3bb36a2 |
--- /dev/null |
+++ b/third_party/afl/src/docs/notes_for_asan.txt |
@@ -0,0 +1,125 @@ |
+================================== |
+Notes for using ASAN with afl-fuzz |
+================================== |
+ |
+ This file discusses some of the caveats for fuzzing under ASAN, and suggests |
+ a handful of alternatives. See README for the general instruction manual. |
+ |
+1) Short version |
+---------------- |
+ |
+ASAN on 64-bit systems requests a lot of memory in a way that can't be easily |
+distinguished from a misbehaving program bent on crashing your system. |
+ |
+Because of this, fuzzing with ASAN is recommended only in four scenarios: |
+ |
+ - On 32-bit systems, where we can always enforce a reasonable memory limit |
+ (-m 800 or so is a good starting point), |
+ |
+ - On 64-bit systems only if you can do one of the following: |
+ |
+ - Compile the binary in 32-bit mode (gcc -m32), |
+ |
+ - Precisely gauge memory needs using http://jwilk.net/software/recidivm . |
+ |
+ - Limit the memory available to process using cgroups on Linux (see |
+ experimental/asan_cgroups). |
+ |
+To compile with ASAN, set AFL_USE_ASAN=1 before calling 'make clean all'. The |
+afl-gcc / afl-clang wrappers will pick that up and add the appropriate flags. |
+Note that ASAN is incompatible with -static, so be mindful of that. |
+ |
+(You can also use AFL_USE_MSAN=1 to enable MSAN instead.) |
+ |
+There is also the option of generating a corpus using a non-ASAN binary, and |
+then feeding it to an ASAN-instrumented one to check for bugs. This is faster, |
+and can give you somewhat comparable results. |
+ |
+2) Long version |
+--------------- |
+ |
+ASAN allocates a huge region of virtual address space for bookkeeping purposes. |
+Most of this is never actually accessed, so the OS never has to allocate any |
+real pages of memory for the process, and the VM grabbed by ASAN is essentially |
+"free" - but the mapping counts against the standard OS-enforced limit |
+(RLIMIT_AS, aka ulimit -v). |
+ |
+On our end, afl-fuzz tries to protect you from processes that go off-rails |
+and start consuming all the available memory in a vain attempt to parse a |
+malformed input file. This happens surprisingly often, so enforcing such a limit |
+is important for almost any fuzzer: the alternative is for the kernel OOM |
+handler to step in and start killing random processes to free up resources. |
+Needless to say, that's not a very nice prospect to live with. |
+ |
+Unfortunately, un*x systems offer no portable way to limit the amount of |
+pages actually given to a process in a way that distinguishes between that |
+and the harmless "land grab" done by ASAN. In principle, there are three standard |
+ways to limit the size of the heap: |
+ |
+ - The RLIMIT_AS mechanism (ulimit -v) caps the size of the virtual space - |
+ but as noted, this pays no attention to the number of pages actually |
+ in use by the process, and doesn't help us here. |
+ |
+ - The RLIMIT_DATA mechanism (ulimit -d) seems like a good fit, but it applies |
+ only to the traditional sbrk() / brk() methods of requesting heap space; |
+ modern allocators, including the one in glibc, routinely rely on mmap() |
+ instead, and circumvent this limit completely. |
+ |
+ - Finally, the RLIMIT_RSS limit (ulimit -m) sounds like what we need, but |
+ doesn't work on Linux - mostly because nobody felt like implementing it. |
+ |
+There are also cgroups, but they are Linux-specific, not universally available |
+even on Linux systems, and they require root permissions to set up; I'm a bit |
+hesitant to make afl-fuzz require root permissions just for that. That said, |
+if you are on Linux and want to use cgroups, check out the contributed script |
+that ships in experimental/asan_cgroups/. |
+ |
+In settings where cgroups aren't available, we have no nice, portable way to |
+avoid counting the ASAN allocation toward the limit. On 32-bit systems, or for |
+binaries compiled in 32-bit mode (-m32), this is not a big deal: ASAN needs |
+around 600-800 MB or so, depending on the compiler - so all you need to do is |
+to specify -m that is a bit higher than that. |
+ |
+On 64-bit systems, the situation is more murky, because the ASAN allocation |
+is completely outlandish - around 17.5 TB in older versions, and closer to |
+20 TB with newest ones. The actual amount of memory on your system is |
+(probably!) just a tiny fraction of that - so unless you dial the limit |
+with surgical precision, you will get no protection from OOM bugs. |
+ |
+On my system, the amount of memory grabbed by ASAN with a slightly older |
+version of gcc is around 17,825,850 MB; for newest clang, it's 20,971,600. |
+But there is no guarantee that these numbers are stable, and if you get them |
+wrong by "just" a couple gigs or so, you will be at risk. |
+ |
+To get the precise number, you can use the recidivm tool developed by Jakub |
+Wilk (http://jwilk.net/software/recidivm). In absence of this, ASAN is *not* |
+recommended when fuzzing 64-bit binaries, unless you are confident that they |
+are robust and enforce reasonable memory limits (in which case, you can |
+specify '-m none' when calling afl-fuzz). |
+ |
+Using recidivm or running with no limits aside, there are two other decent |
+alternatives: build a corpus of test cases using a non-ASAN binary, and then |
+examine them with ASAN, Valgrind, or other heavy-duty tools in a more |
+controlled setting; or compile the target program with -m32 (32-bit mode) |
+if your system supports that. |
+ |
+3) Interactions with the QEMU mode |
+---------------------------------- |
+ |
+ASAN, MSAN, and other sanitizers appear to be incompatible with QEMU user |
+emulation, so please do not try to use them with the -Q option; QEMU doesn't |
+seem to appreciate the shadow VM trick used by these tools, and will likely |
+just allocate all your physical memory, then crash. |
+ |
+4) What about UBSAN? |
+-------------------- |
+ |
+Some folks expressed interest in fuzzing with UBSAN. This isn't officially |
+supported, because many installations of UBSAN don't offer a consistent way |
+to abort() on fault conditions or to terminate with a distinctive exit code. |
+ |
+That said, some versions of the library can be binary-patched to address this |
+issue, while newer releases support explicit compile-time flags - see this |
+mailing list thread for tips: |
+ |
+ https://groups.google.com/forum/#!topic/afl-users/GyeSBJt4M38 |