OLD | NEW |
(Empty) | |
| 1 ================================== |
| 2 Notes for using ASAN with afl-fuzz |
| 3 ================================== |
| 4 |
| 5 This file discusses some of the caveats for fuzzing under ASAN, and suggests |
| 6 a handful of alternatives. See README for the general instruction manual. |
| 7 |
| 8 1) Short version |
| 9 ---------------- |
| 10 |
| 11 ASAN on 64-bit systems requests a lot of memory in a way that can't be easily |
| 12 distinguished from a misbehaving program bent on crashing your system. |
| 13 |
| 14 Because of this, fuzzing with ASAN is recommended only in four scenarios: |
| 15 |
| 16 - On 32-bit systems, where we can always enforce a reasonable memory limit |
| 17 (-m 800 or so is a good starting point), |
| 18 |
| 19 - On 64-bit systems only if you can do one of the following: |
| 20 |
| 21 - Compile the binary in 32-bit mode (gcc -m32), |
| 22 |
| 23 - Precisely gauge memory needs using http://jwilk.net/software/recidivm . |
| 24 |
| 25 - Limit the memory available to process using cgroups on Linux (see |
| 26 experimental/asan_cgroups). |
| 27 |
| 28 To compile with ASAN, set AFL_USE_ASAN=1 before calling 'make clean all'. The |
| 29 afl-gcc / afl-clang wrappers will pick that up and add the appropriate flags. |
| 30 Note that ASAN is incompatible with -static, so be mindful of that. |
| 31 |
| 32 (You can also use AFL_USE_MSAN=1 to enable MSAN instead.) |
| 33 |
| 34 There is also the option of generating a corpus using a non-ASAN binary, and |
| 35 then feeding it to an ASAN-instrumented one to check for bugs. This is faster, |
| 36 and can give you somewhat comparable results. |
| 37 |
| 38 2) Long version |
| 39 --------------- |
| 40 |
| 41 ASAN allocates a huge region of virtual address space for bookkeeping purposes. |
| 42 Most of this is never actually accessed, so the OS never has to allocate any |
| 43 real pages of memory for the process, and the VM grabbed by ASAN is essentially |
| 44 "free" - but the mapping counts against the standard OS-enforced limit |
| 45 (RLIMIT_AS, aka ulimit -v). |
| 46 |
| 47 On our end, afl-fuzz tries to protect you from processes that go off-rails |
| 48 and start consuming all the available memory in a vain attempt to parse a |
| 49 malformed input file. This happens surprisingly often, so enforcing such a limit |
| 50 is important for almost any fuzzer: the alternative is for the kernel OOM |
| 51 handler to step in and start killing random processes to free up resources. |
| 52 Needless to say, that's not a very nice prospect to live with. |
| 53 |
| 54 Unfortunately, un*x systems offer no portable way to limit the amount of |
| 55 pages actually given to a process in a way that distinguishes between that |
| 56 and the harmless "land grab" done by ASAN. In principle, there are three standar
d |
| 57 ways to limit the size of the heap: |
| 58 |
| 59 - The RLIMIT_AS mechanism (ulimit -v) caps the size of the virtual space - |
| 60 but as noted, this pays no attention to the number of pages actually |
| 61 in use by the process, and doesn't help us here. |
| 62 |
| 63 - The RLIMIT_DATA mechanism (ulimit -d) seems like a good fit, but it applies |
| 64 only to the traditional sbrk() / brk() methods of requesting heap space; |
| 65 modern allocators, including the one in glibc, routinely rely on mmap() |
| 66 instead, and circumvent this limit completely. |
| 67 |
| 68 - Finally, the RLIMIT_RSS limit (ulimit -m) sounds like what we need, but |
| 69 doesn't work on Linux - mostly because nobody felt like implementing it. |
| 70 |
| 71 There are also cgroups, but they are Linux-specific, not universally available |
| 72 even on Linux systems, and they require root permissions to set up; I'm a bit |
| 73 hesitant to make afl-fuzz require root permissions just for that. That said, |
| 74 if you are on Linux and want to use cgroups, check out the contributed script |
| 75 that ships in experimental/asan_cgroups/. |
| 76 |
| 77 In settings where cgroups aren't available, we have no nice, portable way to |
| 78 avoid counting the ASAN allocation toward the limit. On 32-bit systems, or for |
| 79 binaries compiled in 32-bit mode (-m32), this is not a big deal: ASAN needs |
| 80 around 600-800 MB or so, depending on the compiler - so all you need to do is |
| 81 to specify -m that is a bit higher than that. |
| 82 |
| 83 On 64-bit systems, the situation is more murky, because the ASAN allocation |
| 84 is completely outlandish - around 17.5 TB in older versions, and closer to |
| 85 20 TB with newest ones. The actual amount of memory on your system is |
| 86 (probably!) just a tiny fraction of that - so unless you dial the limit |
| 87 with surgical precision, you will get no protection from OOM bugs. |
| 88 |
| 89 On my system, the amount of memory grabbed by ASAN with a slightly older |
| 90 version of gcc is around 17,825,850 MB; for newest clang, it's 20,971,600. |
| 91 But there is no guarantee that these numbers are stable, and if you get them |
| 92 wrong by "just" a couple gigs or so, you will be at risk. |
| 93 |
| 94 To get the precise number, you can use the recidivm tool developed by Jakub |
| 95 Wilk (http://jwilk.net/software/recidivm). In absence of this, ASAN is *not* |
| 96 recommended when fuzzing 64-bit binaries, unless you are confident that they |
| 97 are robust and enforce reasonable memory limits (in which case, you can |
| 98 specify '-m none' when calling afl-fuzz). |
| 99 |
| 100 Using recidivm or running with no limits aside, there are two other decent |
| 101 alternatives: build a corpus of test cases using a non-ASAN binary, and then |
| 102 examine them with ASAN, Valgrind, or other heavy-duty tools in a more |
| 103 controlled setting; or compile the target program with -m32 (32-bit mode) |
| 104 if your system supports that. |
| 105 |
| 106 3) Interactions with the QEMU mode |
| 107 ---------------------------------- |
| 108 |
| 109 ASAN, MSAN, and other sanitizers appear to be incompatible with QEMU user |
| 110 emulation, so please do not try to use them with the -Q option; QEMU doesn't |
| 111 seem to appreciate the shadow VM trick used by these tools, and will likely |
| 112 just allocate all your physical memory, then crash. |
| 113 |
| 114 4) What about UBSAN? |
| 115 -------------------- |
| 116 |
| 117 Some folks expressed interest in fuzzing with UBSAN. This isn't officially |
| 118 supported, because many installations of UBSAN don't offer a consistent way |
| 119 to abort() on fault conditions or to terminate with a distinctive exit code. |
| 120 |
| 121 That said, some versions of the library can be binary-patched to address this |
| 122 issue, while newer releases support explicit compile-time flags - see this |
| 123 mailing list thread for tips: |
| 124 |
| 125 https://groups.google.com/forum/#!topic/afl-users/GyeSBJt4M38 |
OLD | NEW |