Adrian Taylor | 41b1837 | 2023-03-22 18:34:14 | [diff] [blame] | 1 | # Fuzzing browsertests |
| 2 | |
| 3 | Fuzzing is effective if either: |
| 4 | |
| 5 | * it's guided by code coverage, and can execute incredible numbers of test cases |
| 6 | per second to explore the codebase (thousands); or |
| 7 | * it has a smart mutator of some kind (out of scope here). |
| 8 | |
| 9 | If you have an API to be fuzzed, make a simple libfuzzer fuzzer for just that |
| 10 | API, to get the speed required to explore its attack surface. If however we want |
| 11 | to fuzz a larger, more complex set of Chromium code, we usually need an entire |
| 12 | browser process environment around us. The browser process takes seconds to |
| 13 | start, preventing coverage guided fuzzing from being effective. |
| 14 | |
| 15 | We now have an experimental 'in process fuzz test' framework which attempts to: |
| 16 | * Start the browser process _once_ |
| 17 | * Execute lots of fuzz cases in that pre-existing browser. |
| 18 | This _may_ amortize the start up cost sufficiently to make such coverage-guided |
| 19 | fuzzing plausible. We don't yet know. But this document shows how to use it, |
| 20 | just in case. |
| 21 | |
| 22 | # Writing an in process fuzz case |
| 23 | |
Adrian Taylor | 33c7c25 | 2023-11-08 13:40:04 | [diff] [blame] | 24 | * Use the template `chrome/test/fuzzing/in_process_fuzzer.gni` |
Caleb Raitto | cb8cccc | 2023-12-18 12:47:33 | [diff] [blame] | 25 | * Provide a source code file which inherits from `InProcessFuzzer`. This |
Adrian Taylor | 41b1837 | 2023-03-22 18:34:14 | [diff] [blame] | 26 | must override the `Fuzz` method. You'll find that your base class inherits |
| 27 | from the full browser test infrastructure, so you can do anything you'd |
| 28 | do in a normal Chrome browser test. |
| 29 | * In your `cc` file, also use the macro `REGISTER_IN_PROCESS_FUZZER` to |
| 30 | declare that this is the one and only such fuzzer in your executable. |
| 31 | |
| 32 | # Running such an in process fuzz case |
| 33 | |
| 34 | These cases can be run either with libfuzzer or centipede. |
| 35 | |
| 36 | For libfuzzer, provide gn arguments `use_sanitizer_coverage = true`, |
| 37 | `use_libfuzzer = true`, `is_component_build = false` and `is_asan = true` |
| 38 | (other permutations may work). |
| 39 | |
| 40 | This will give you a single binary you can run like this: |
| 41 | `my_fuzzer /tmp/corpus -rss_limit_mb=81920` |
| 42 | |
| 43 | However, you'll more likely want to use |
| 44 | [centipede](https://github.com/google/centipede) which has an |
| 45 | out-of-process co-ordinator. |
| 46 | |
| 47 | To use centipede, specify `use_centipede = true` instead of `use_libfuzzer = |
Adrian Taylor | 4f154d8 | 2023-04-28 15:31:28 | [diff] [blame] | 48 | true`. You should also build the `centipede` target as well as your fuzzer. |
| 49 | You'll then want to run centipede using some command like: |
Adrian Taylor | 41b1837 | 2023-03-22 18:34:14 | [diff] [blame] | 50 | |
| 51 | ``` |
Adrian Taylor | 4f154d8 | 2023-04-28 15:31:28 | [diff] [blame] | 52 | mkdir wd && ASAN_OPTIONS=detect_odr_violation=0 out/ASAN/centipede --binary=out/ASAN/html_in_process_fuzz_tests --workdir=wd --shmem_size_mb 4096 --rss_limit_mb 0 --batch_size 100 --log_features_shards 2 --exit_on_crash 1 |
Adrian Taylor | 41b1837 | 2023-03-22 18:34:14 | [diff] [blame] | 53 | ``` |