oss-fuzz/docs/advanced-topics/ideal_integration.md

170 lines
7.7 KiB
Markdown
Raw Normal View History

2019-08-07 14:37:16 +00:00
---
layout: default
title: Ideal integration
parent: Advanced topics
nav_order: 1
permalink: /advanced-topics/ideal-integration
---
2016-11-15 18:04:07 +00:00
# Ideal integration with OSS-Fuzz
2016-11-16 16:59:35 +00:00
OSS projects have different build and test systems. So, we can not expect them
2019-08-07 14:37:16 +00:00
to have a unified way of implementing and maintaining fuzz targets and
integrating them with OSS-Fuzz. However, we will still try to give
recommendations on the preferred ways.
Here are several features (starting from the easiest) that will make automated
fuzzing simple and efficient, and will allow to catch regressions early on in
the development cycle.
2016-11-15 18:04:07 +00:00
2019-08-07 14:37:16 +00:00
- TOC
{:toc}
---
2016-11-16 06:07:18 +00:00
2017-08-04 18:15:52 +00:00
## TL;DR
Every [fuzz target](http://libfuzzer.info/#fuzz-target):
* Is [maintained by code owners](#fuzz-target) in their RCS (Git, SVN, etc).
* Is [built with the rest of the tests](#build-support) - no bit rot!
2017-08-04 18:16:18 +00:00
* Has a [seed corpus](#seed-corpus) with good [code coverage](#coverage).
2019-08-15 22:07:23 +00:00
* Has a [dictionary](#dictionary), if applicable.
2019-08-07 14:37:16 +00:00
* Is [continuously tested on the seed corpus](#regression-testing) with
[ASan/UBSan/MSan](https://github.com/google/sanitizers).
* Is [fast and has no OOMs](#performance).
2017-08-04 18:15:52 +00:00
2016-11-18 23:04:06 +00:00
## Fuzz Target
2019-08-07 14:37:16 +00:00
The code of the [fuzz target(s)](http://libfuzzer.info/#fuzz-target) should be
part of the project's source code repository.
All fuzz targets should be easily discoverable (e.g. reside in the same
directory, or follow the same naming pattern, etc).
2016-11-15 18:04:07 +00:00
2019-08-07 14:37:16 +00:00
This makes it easy to maintain the fuzzers and minimizes breakages that can
arise as source code changes over time.
2016-11-18 23:25:28 +00:00
Make sure to fuzz the target locally for a small period of time to ensure that
it does not crash, hang, or run out of memory instantly.
2019-08-15 22:07:23 +00:00
You can read more about what makes a good fuzz target [here]
(https://github.com/google/fuzzing/blob/master/docs/good-fuzz-target.md)
2016-11-16 16:59:35 +00:00
2016-12-13 17:33:59 +00:00
The interface between the [fuzz target]((http://libfuzzer.info/#fuzz-target))
and the fuzzing engines is C, so you may use C or C++ to implement the fuzz target.
2016-11-15 18:04:07 +00:00
Examples:
[boringssl](https://github.com/google/boringssl/tree/master/fuzz),
[SQLite](https://www.sqlite.org/src/artifact/ad79e867fb504338),
[s2n](https://github.com/awslabs/s2n/tree/master/tests/fuzz),
[openssl](https://github.com/openssl/openssl/tree/master/fuzz),
[FreeType](http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/src/tools/ftfuzzer),
2016-11-15 19:56:11 +00:00
[re2](https://github.com/google/re2/tree/master/re2/fuzzing),
2016-11-15 18:04:07 +00:00
[harfbuzz](https://github.com/behdad/harfbuzz/tree/master/test/fuzzing),
[pcre2](https://vcs.pcre.org/pcre2/code/trunk/src/pcre2_fuzzsupport.c?view=markup),
2017-01-31 15:42:12 +00:00
[ffmpeg](https://github.com/FFmpeg/FFmpeg/blob/master/tools/target_dec_fuzzer.c).
2016-11-15 18:04:07 +00:00
2017-04-24 20:25:22 +00:00
## Build support
A plethora of different build systems exist in the open-source world.
And the less OSS-Fuzz knows about them, the better it can scale.
An ideal build integration for OSS-Fuzz would look like this:
2019-08-07 14:37:16 +00:00
* For every fuzz target `foo` in the project, there is a build rule that
builds `foo_fuzzer`, a binary that contains the fuzzing entry point
(`LLVMFuzzerTestOneInput`) and all the code it depends on, and that uses the
`main()` function from `$LIB_FUZZING_ENGINE`
(env var [provided]({{ site.baseurl }}/getting-started/new-project-guide/) by OSS-Fuzz environment).
2017-04-24 20:25:22 +00:00
* The build system supports changing the compiler and passing extra compiler
flags so that the build command for a `foo_fuzzer` looks similar to this:
```bash
# Assume the following env vars are set:
# CC, CXX, CFLAGS, CXXFLAGS, LIB_FUZZING_ENGINE
$ make_or_whatever_other_command foo_fuzzer
```
2019-08-07 14:37:16 +00:00
This will allow to have minimal OSS-Fuzz-specific configuration and thus be
more robust.
2017-04-24 20:25:22 +00:00
2019-08-07 14:37:16 +00:00
There is no point in hardcoding the exact compiler flags in the build system
because they a) may change and b) are different depending on the fuzzing engine
and the sanitizer being used.
2016-11-15 18:04:07 +00:00
2016-11-18 23:04:06 +00:00
## Seed Corpus
2016-11-17 04:20:49 +00:00
The *corpus* is a set of inputs for the fuzz target (stored as individual files).
When starting the fuzzing process, one should have a "seed corpus",
i.e. a set of inputs to "seed" the mutations.
2019-08-07 14:37:16 +00:00
The quality of the seed corpus has a huge impact on fuzzing efficiency as it
allows the fuzzer to discover new code paths more easily.
2016-11-15 18:04:07 +00:00
The ideal corpus is a minimal set of inputs that provides maximal code coverage.
2016-11-17 04:20:49 +00:00
2016-11-23 18:27:29 +00:00
For better OSS-Fuzz integration,
2019-08-07 14:37:16 +00:00
the seed corpus should be available in revision control (can be same or
different as the source code). It should be regularly extended with the inputs
that (used to) trigger bugs and/or touch new parts of the code.
2016-11-16 06:10:56 +00:00
2016-11-15 18:04:07 +00:00
Examples:
[boringssl](https://github.com/google/boringssl/tree/master/fuzz),
[openssl](https://github.com/openssl/openssl/tree/master/fuzz),
2016-11-29 19:19:32 +00:00
[nss](https://github.com/mozilla/nss-fuzzing-corpus) (corpus in a separate repo).
2016-11-15 18:04:07 +00:00
2019-08-15 22:07:23 +00:00
## Dictionary
2016-11-23 18:27:29 +00:00
For some input types, a simple dictionary of tokens used by the input language
can have a dramatic positive effect on fuzzing efficiency.
2016-11-18 23:04:06 +00:00
For example, when fuzzing an XML parser, a dictionary of XML tokens will help.
AFL has a [collection](https://github.com/rc0r/afl-fuzz/tree/master/dictionaries)
of such dictionaries for some of the popular data formats.
Ideally, a dictionary should be maintained alongside the fuzz target.
The syntax is described [here](http://libfuzzer.info/#dictionaries).
2017-04-25 02:20:38 +00:00
## Coverage
2019-08-07 14:37:16 +00:00
For a fuzz target to be useful, it must have good coverage in the code that it
is testing. You can view the coverage for your fuzz targets by looking at the
[fuzzer stats]({{ site.baseurl }}/further-reading/clusterfuzz#fuzzer-stats)
2019-08-07 14:37:16 +00:00
dashboard on ClusterFuzz, as well as
[coverage reports]({{ site.baseurl }}/further-reading/clusterfuzz#coverage-reports).
2017-04-25 02:20:38 +00:00
To generate an aggregated code coverage report for your project, please see
2019-08-07 14:37:16 +00:00
[code coverage]({{ site.baseurl }}/advanced-topics/code-coverage)
documentation page.
2019-08-07 14:37:16 +00:00
Coverage can often be improved by adding dictionaries, more inputs for seed
corpora, and fixing timeouts/out-of-memory bugs in your targets.
2017-04-25 02:20:38 +00:00
2019-08-15 22:07:23 +00:00
## Regression Testing
The fuzz targets should be regularly tested (not necessarily fuzzed!) as a part
of the project's regression testing process.
One way to do so is to link the fuzz target with a simple standalone driver
(e.g. [this one](https://github.com/llvm-mirror/compiler-rt/tree/master/lib/fuzzer/standalone))
that runs the provided inputs and use this driver with the seed corpus created
in previous step. It is recommended to use
[sanitizers](https://github.com/google/sanitizers) during regression testing.
Examples: [SQLite](https://www.sqlite.org/src/artifact/d9f1a6f43e7bab45),
[openssl](https://github.com/openssl/openssl/blob/master/fuzz/test-corpus.c)
2017-04-25 02:24:00 +00:00
## Performance
2019-08-07 14:37:16 +00:00
Fuzz targets should also be performant, as high memory usage and/or slow
execution speed can slow the down the growth of coverage and finding of new
bugs. ClusterFuzz provides a
[performance analyzer]({{ site.baseurl }}/further-reading/clusterfuzz/#performance-analyzer)
2019-08-07 14:37:16 +00:00
for each fuzz target that shows problems that are impacting the performance of
the fuzz target.
2016-11-17 04:26:11 +00:00
2017-05-15 22:17:40 +00:00
## Example
2019-08-07 14:37:16 +00:00
You may look at a simple
[example](https://github.com/google/oss-fuzz/tree/master/projects/example/my-api-repo)
that covers most of the items above.
2017-05-15 22:17:40 +00:00
2016-11-18 23:25:28 +00:00
## Not a project member?
2016-11-18 23:26:02 +00:00
If you are a member of the project you want to fuzz, most of the steps above are simple.
2016-11-23 18:27:29 +00:00
However in some cases, someone outside the project team may want to fuzz the code
2016-11-18 23:30:46 +00:00
and the project maintainers are not interested in helping.
2016-11-23 18:27:29 +00:00
In such cases, we can host the fuzz targets, dictionaries, etc in OSS-Fuzz's
2016-11-19 00:04:50 +00:00
repository and mention them in the Dockerfile.
2019-08-07 14:37:16 +00:00
Examples: [libxml2](https://github.com/google/oss-fuzz/tree/master/projects/libxml2),
[c-ares](https://github.com/google/oss-fuzz/tree/master/projects/c-ares), [expat](https://github.com/google/oss-fuzz/tree/master/projects/expat).
2016-11-19 02:54:10 +00:00
This is far from ideal because the fuzz targets will not be continuously tested
2016-11-18 23:33:16 +00:00
and hence may quickly bitrot.
2016-11-18 23:30:46 +00:00
2019-08-07 14:37:16 +00:00
If you are not a project maintainer, we may not be able to CC you to security
bugs found by OSS-Fuzz.