blob: 1269bfbd1a0aed8c7f11a552849021fb6caf38d0 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
# Getting Started with libFuzzer in Chrome
*** note
**Prerequisites:** libFuzzer in Chrome is supported with GN on Linux only.
***
This document will walk you through:
* setting up your build enviroment.
* creating your first fuzzer.
* running the fuzzer and verifying its vitals.
## Configure Build
Use `use_libfuzzer` GN argument together with sanitizer to generate build files:
*Notice*: current implementation also supports `use_afl` argument, but it is
recommended to use libFuzzer for development. Running libFuzzer locally doesn't
require any special configuration and quickly gives meaningful output for speed,
coverage and other parameters.
```bash
# With address sanitizer
gn gen out/libfuzzer '--args=use_libfuzzer=true is_asan=true is_debug=false enable_nacl=false' --check
```
Supported sanitizer configurations are:
| GN Argument | Description |
|--------------|----|
| `is_asan=true` | enables [Address Sanitizer] to catch problems like buffer overruns. |
| `is_msan=true` | enables [Memory Sanitizer] to catch problems like uninitialed reads<sup>\[[1](#note1)\]</sup>. |
| `is_ubsan_security=true` | enables [Undefined Behavior Sanitizer] to catch<sup>\[[2](#note2)\]</sup> undefined behavior like integer overflow. |
| | it is possible to run libfuzzer without any sanitizers; *probably not what you want*.|
## Write Fuzzer Function
Create a new .cc file and define a `LLVMFuzzerTestOneInput` function:
```cpp
#include <stddef.h>
#include <stdint.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
// put your fuzzing code here and use data+size as input.
return 0;
}
```
[url_parse_fuzzer.cc] is a simple example of real-world fuzzer.
## Define GN Target
Define `fuzzer_test` GN target:
```python
import("//testing/libfuzzer/fuzzer_test.gni")
fuzzer_test("my_fuzzer") {
sources = [ "my_fuzzer.cc" ]
deps = [ ... ]
}
```
## Build and Run Fuzzer Locally
Build with ninja as usual and run:
```bash
ninja -C out/libfuzzer url_parse_fuzzer
./out/libfuzzer/url_parse_fuzzer
```
Your fuzzer should produce output like this:
```
INFO: Seed: 1787335005
INFO: -max_len is not provided, using 64
INFO: PreferSmall: 1
#0 READ units: 1 exec/s: 0
#1 INITED cov: 2361 bits: 95 indir: 29 units: 1 exec/s: 0
#2 NEW cov: 2710 bits: 359 indir: 36 units: 2 exec/s: 0 L: 64 MS: 0
```
The `... NEW ...` line appears when libFuzzer finds new and interesting input. The
efficient fuzzer should be able to finds lots of them rather quickly.
The `... pulse ...` line will appear periodically to show the current status.
## Improving Your Fuzzer
Your fuzzer may immediately discover interesting (i.e. crashing) inputs.
To make it more efficient, several small steps can take you really far:
* Create seed corpus. Add `seed_corpus = "src/fuzz-testcases/"` attribute
to your fuzzer targets and add example files in appropriate folder. Read more
in [Seed Corpus] section of efficient fuzzer guide.
*Make sure corpus files are appropriately licensed.*
* Create mutation dictionary. With a `dict = "protocol.dict"` attribute and
`key=value` dicitionary file format, mutations can be more effective.
See [Fuzzer Dictionary].
* Specify maximum testcase length. By default libFuzzer uses `-max_len=64`
(or takes the longest testcase in a corpus). ClusterFuzz takes
random value in range from `1` to `10000` for each fuzzing session and passes
that value to libFuzzers. If corpus contains testcases of size greater than
`max_len`, libFuzzer will use only first `max_len` bytes of such testcases.
See [Maximum Testcase Length].
## Disable noisy error message logging
If the code that you are a fuzzing generates error messages when encountering
incorrect or invalid data then you need to silence those errors in the fuzzer.
If the target uses the Chromium logging APIs, the best way to do that is to
override the environment used for logging in your fuzzer:
```cpp
struct Environment {
Environment() {
logging::SetMinLogLevel(logging::LOG_FATAL);
}
};
Environment* env = new Environment();
```
## Submitting Fuzzer to ClusterFuzz
ClusterFuzz builds and executes all `fuzzer_test` targets in the source tree.
The only thing you should do is to submit a fuzzer into Chrome.
## Next Steps
* After your fuzzer is submitted, you should check its [ClusterFuzz status] in
a day or two.
* Check the [Efficient Fuzzer Guide] to better understand your fuzzer
performance and for optimization hints.
## Notes
*[1]* {#note1}You need to [download prebuilt instrumented libraries](https://www.chromium.org/developers/testing/memorysanitizer#TOC-How-to-build-and-run)
to use msan ([crbug/653712](https://bugs.chromium.org/p/chromium/issues/detail?id=653712)):
```bash
GYP_DEFINES='use_goma=1 msan=1 use_prebuilt_instrumented_libraries=1' gclient runhooks
```
*[2]* {#note2}By default UBSan doesn't crash once undefined behavior has been detected.
To make it crash the following additional option should be provided:
```bash
UBSAN_OPTIONS=halt_on_error=1 ./fuzzer <corpus_directory_or_single_testcase_path>
```
Other useful options (used by ClusterFuzz) are:
```bash
UBSAN_OPTIONS=symbolize=1:halt_on_error=1:print_stacktrace=1 ./fuzzer <corpus_directory_or_single_testcase_path>
```
[Address Sanitizer]: http://clang.llvm.org/docs/AddressSanitizer.html
[ClusterFuzz status]: clusterfuzz.md#Status-Links
[Efficient Fuzzer Guide]: efficient_fuzzer.md
[Fuzzer Dictionary]: efficient_fuzzer.md#Fuzzer-Dictionary
[Maximum Testcase Length]: efficient_fuzzer.md#Maximum-Testcase-Length
[Memory Sanitizer]: http://clang.llvm.org/docs/MemorySanitizer.html
[Seed Corpus]: efficient_fuzzer.md#Seed-Corpus
[Undefined Behavior Sanitizer]: http://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
[crbug/598448]: https://bugs.chromium.org/p/chromium/issues/detail?id=598448
[url_parse_fuzzer.cc]: https://code.google.com/p/chromium/codesearch#chromium/src/testing/libfuzzer/fuzzers/url_parse_fuzzer.cc
|