116 lines
4.4 KiB
Markdown
116 lines
4.4 KiB
Markdown
|
# Fuzzing
|
||
|
|
||
|
This directory contains coverage-guided fuzzers for KZG functions. It uses
|
||
|
LLVM's [libFuzzer](https://llvm.org/docs/LibFuzzer.html) for the heavy lifting.
|
||
|
Each directory is named after a target and contains a single file (`fuzz.c`)
|
||
|
that implements a `LLVMFuzzerTestOneInput` function. These are relatively
|
||
|
simple; if the input matches the size requirements, it passes the data to the
|
||
|
target function. There is a Makefile that compiles and starts the fuzzer, which
|
||
|
means it should be pretty easy.
|
||
|
|
||
|
## Dependencies
|
||
|
|
||
|
This is expected to run on Linux/macOS, it is not expected to work on Windows.
|
||
|
In additional to `build-essentials` and `clang`, this requires `llvm` be
|
||
|
installed:
|
||
|
|
||
|
### Linux
|
||
|
|
||
|
```
|
||
|
sudo apt install llvm
|
||
|
```
|
||
|
|
||
|
### macOS
|
||
|
|
||
|
```
|
||
|
brew install llvm
|
||
|
```
|
||
|
|
||
|
## Targets
|
||
|
|
||
|
Currently, only the public KZG interface functions are fuzzable:
|
||
|
```
|
||
|
$ make
|
||
|
Available targets:
|
||
|
- fuzz_blob_to_kzg_commitment
|
||
|
- fuzz_compute_blob_kzg_proof
|
||
|
- fuzz_compute_kzg_proof
|
||
|
- fuzz_verify_blob_kzg_proof
|
||
|
- fuzz_verify_blob_kzg_proof_batch
|
||
|
- fuzz_verify_kzg_proof
|
||
|
```
|
||
|
|
||
|
To run a fuzzer, run `make fuzz_<func>` like:
|
||
|
|
||
|
```
|
||
|
$ make fuzz_verify_kzg_proof
|
||
|
[+] Building blst
|
||
|
+ cc -O2 -fno-builtin -fPIC -Wall -Wextra -Werror -c ./src/server.c
|
||
|
+ cc -O2 -fno-builtin -fPIC -Wall -Wextra -Werror -c ./build/assembly.S
|
||
|
+ ar rc libblst.a assembly.o server.o
|
||
|
[+] Generating corpus
|
||
|
[+] Compiling verify_kzg_proof fuzzer
|
||
|
[+] Starting verify_kzg_proof fuzzer
|
||
|
INFO: Running with entropic power schedule (0xFF, 100).
|
||
|
INFO: Seed: 855755358
|
||
|
INFO: Loaded 1 modules (228 inline 8-bit counters): 228 [0x1025a00f8, 0x1025a01dc),
|
||
|
INFO: Loaded 1 PC tables (228 PCs): 228 [0x1025a01e0,0x1025a1020),
|
||
|
INFO: 1 files found in ./verify_kzg_proof/corpus
|
||
|
INFO: seed corpus: files: 1 min: 160b max: 160b total: 160b rss: 28Mb
|
||
|
#2 pulse ft: 17 exec/s: 1 rss: 29Mb
|
||
|
#2 INITED cov: 17 ft: 17 corp: 1/160b exec/s: 1 rss: 29Mb
|
||
|
#4 pulse cov: 17 ft: 17 corp: 1/160b lim: 160 exec/s: 2 rss: 29Mb
|
||
|
#5 NEW cov: 19 ft: 20 corp: 2/320b lim: 160 exec/s: 2 rss: 29Mb L: 160/160 MS: 3 ChangeASCIIInt-ChangeBit-ChangeBit-
|
||
|
#7 NEW cov: 20 ft: 21 corp: 3/477b lim: 160 exec/s: 3 rss: 29Mb L: 157/160 MS: 2 ChangeByte-EraseBytes-
|
||
|
#8 pulse cov: 20 ft: 21 corp: 3/477b lim: 160 exec/s: 4 rss: 29Mb
|
||
|
#13 NEW cov: 21 ft: 23 corp: 4/637b lim: 160 exec/s: 6 rss: 29Mb L: 160/160 MS: 1 ChangeBit-
|
||
|
#16 pulse cov: 21 ft: 23 corp: 4/637b lim: 160 exec/s: 8 rss: 29Mb
|
||
|
...
|
||
|
```
|
||
|
|
||
|
There are a few steps:
|
||
|
|
||
|
* Build the blst library.
|
||
|
* Generate initial corpora files.
|
||
|
* Compile the fuzzer.
|
||
|
* Start the fuzzer.
|
||
|
|
||
|
Reference [this page](https://llvm.org/docs/LibFuzzer.html#output) for a guide on reading the output.
|
||
|
|
||
|
To stop the fuzzer, press ctrl-C on your keyboard. It will print something like:
|
||
|
|
||
|
```
|
||
|
...
|
||
|
#65536 pulse cov: 25 ft: 29 corp: 7/961b lim: 160 exec/s: 16384 rss: 29Mb
|
||
|
#131072 pulse cov: 25 ft: 29 corp: 7/961b lim: 160 exec/s: 18724 rss: 29Mb
|
||
|
^C==11616== libFuzzer: run interrupted; exiting
|
||
|
make: [run_fuzz_verify_kzg_proof] Error 72 (ignored)
|
||
|
```
|
||
|
|
||
|
If your system has multiple cores, it's easy to run fuzzers on multiple threads.
|
||
|
Append `THREADS=<n>` where `n` is the number of threads you would like there to
|
||
|
be. If you wish to use all available CPU cores, specify `-1` as the count.
|
||
|
|
||
|
```
|
||
|
$ make fuzz_verify_kzg_proof THREADS=4
|
||
|
[+] Starting verify_kzg_proof fuzzer
|
||
|
./verify_kzg_proof/fuzz -artifact_prefix=./verify_kzg_proof/ -max_len=160 ./verify_kzg_proof/corpus >fuzz-0.log 2>&1
|
||
|
./verify_kzg_proof/fuzz -artifact_prefix=./verify_kzg_proof/ -max_len=160 ./verify_kzg_proof/corpus >fuzz-2.log 2>&1
|
||
|
./verify_kzg_proof/fuzz -artifact_prefix=./verify_kzg_proof/ -max_len=160 ./verify_kzg_proof/corpus >fuzz-1.log 2>&1
|
||
|
./verify_kzg_proof/fuzz -artifact_prefix=./verify_kzg_proof/ -max_len=160 ./verify_kzg_proof/corpus >fuzz-3.log 2>&1
|
||
|
```
|
||
|
|
||
|
When you press ctrl-C it will stop all the fuzzers and print their output to
|
||
|
your console sequentially. You will most likely need to scroll up to see their
|
||
|
outputs.
|
||
|
|
||
|
When operating in parallel (threads) the fuzzers use a shared corpus and are
|
||
|
intelligent enough to learn from other threads that have progressed further.
|
||
|
When you see a line that starts with "RELOAD" that fuzzer process is updating
|
||
|
its corpus with findings from other threads.
|
||
|
|
||
|
### Findings
|
||
|
|
||
|
If there is a crash or timeout, the fuzzer will write a file to the target
|
||
|
directory containing the input data associated with that crash/timeout. If this
|
||
|
happens, please report the finding via an issue on GitHub.
|