2016-10-28 22:25:08 +00:00
# Setting up New Target
2016-08-29 20:38:51 +00:00
2016-10-25 23:36:29 +00:00
Fuzzer build configurations are placed into [`targets/` ](https://github.com/google/oss-fuzz/tree/master/targets )
subdirectories of the [oss-fuzz repo] on GitHub.
For example, fuzzers for the expat library are located in
[`targets/expat/` ](https://github.com/google/oss-fuzz/tree/master/targets/expat ).
2016-08-29 20:38:51 +00:00
## Prerequisites
2016-10-27 03:49:56 +00:00
[Install Docker ](https://docs.docker.com/engine/installation ). Googlers: [go/installdocker ](https://goto.google.com/installdocker ).
2016-10-25 21:41:22 +00:00
([Why Docker?](faq.md#why-do-you-use-docker))
2016-08-29 20:38:51 +00:00
2016-10-13 15:09:12 +00:00
*NOTE: if you want to run `docker` without `sudo` also follow the optional [Create a docker group ](https://docs.docker.com/engine/installation/linux/ubuntulinux/#/create-a-docker-group ) section.*
2016-10-12 01:26:42 +00:00
*NOTE: Docker images can consume significant disk space. Run*
2016-10-12 01:27:02 +00:00
*[docker-cleanup](https://gist.github.com/mikea/d23a839cba68778d94e0302e8a2c200f)*
2016-10-12 01:26:42 +00:00
*periodically to garbage collect unused images.*
2016-09-27 19:17:38 +00:00
## Overview
2016-08-29 20:38:51 +00:00
2016-10-25 23:36:29 +00:00
To add a new OSS target to oss-fuzz, 3 supporting files have to be added to oss-fuzz source code repository:
2016-08-29 20:38:51 +00:00
2016-10-26 18:16:51 +00:00
* `targets/<target_name>/Dockerfile` - defines an container environment with all the dependencies
2016-10-18 22:37:23 +00:00
needed to build the project and the fuzzer.
2016-10-26 18:16:51 +00:00
* `targets/<target_name>/build.sh` - build script that will be executed inside the container.
* `targets/<target_name>/Jenkinsfile` - will be needed to integrate fuzzers with ClusterFuzz build and distributed execution system.
2016-10-25 23:36:29 +00:00
Specify your target VCS location in it.
2016-08-29 20:38:51 +00:00
2016-10-25 23:36:29 +00:00
To create a new directory for the target and *automatically generate* these 3 files a python script can be used:
2016-09-01 18:43:44 +00:00
```bash
2016-09-27 18:39:04 +00:00
$ cd /path/to/oss-fuzz
2016-10-25 23:36:29 +00:00
$ export TARGET_NAME=target_name
$ python infra/helper.py generate $TARGET_NAME
2016-09-01 18:43:44 +00:00
```
2016-10-25 23:36:29 +00:00
Create a fuzzer and add it to the *target_name/* directory as well.
2016-09-27 21:07:19 +00:00
2016-09-27 19:17:38 +00:00
## Dockerfile
2016-08-29 20:38:51 +00:00
2016-09-27 20:41:52 +00:00
This is the Docker image definition that build.sh will be executed in.
2016-09-27 19:27:58 +00:00
It is very simple for most libraries:
2016-10-12 23:25:06 +00:00
```docker
2016-09-27 19:27:58 +00:00
FROM ossfuzz/base-libfuzzer # base image with clang toolchain
2016-10-12 23:25:06 +00:00
MAINTAINER YOUR_EMAIL # each file should have a maintainer
2016-09-27 19:27:58 +00:00
RUN apt-get install -y ... # install required packages to build a project
2016-10-25 23:36:29 +00:00
RUN git checkout < git_url > # checkout all sources needed to build your target
2016-10-19 20:04:35 +00:00
COPY build.sh fuzzer.cc /src/ # install build script and other source files.
2016-08-29 20:38:51 +00:00
```
2016-09-27 20:41:52 +00:00
Expat example: [expat/Dockerfile ](../expat/Dockerfile )
2016-08-29 20:38:51 +00:00
2016-10-12 23:25:06 +00:00
## Create Fuzzer Source File
Create a new .cc file, define a `LLVMFuzzerTestOneInput` function and call
2016-10-25 23:36:29 +00:00
your target:
2016-10-12 23:25:06 +00:00
```c++
#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;
}
```
Make sure you add the file to your Docker image:
```docker
COPY build.sh my_fuzzer.cc /src/ # install build script & fuzzer.
```
There are [lots ](../libxml2/libxml2_xml_read_memory_fuzzer.cc )
[of ](../expat/parse_fuzzer.cc ) [examples ](../zlib/zlib_uncompress_fuzzer.cc )
in this project repository.
2016-09-27 19:17:38 +00:00
## build.sh
2016-08-29 20:38:51 +00:00
2016-10-25 23:36:29 +00:00
This is where most of the work is done to build fuzzers for your target. The script will
2016-09-27 20:41:52 +00:00
be executed within an image built from a `Dockerfile` .
2016-08-29 20:38:51 +00:00
In general, this script will need to:
2016-10-25 23:36:29 +00:00
1. Build the target using its build system *with* correct compiler and its flags provided as
*environment variables* (see below).
2. Build the fuzzers, linking with the target and libFuzzer. Resulting fuzzers
2016-08-29 20:38:51 +00:00
should be placed in `/out` .
For expat, this looks like:
```bash
#!/bin/bash -eu
cd /src/expat/expat
./buildconf.sh
2016-09-27 20:41:52 +00:00
# configure scripts usually use correct environment variables.
2016-08-29 20:38:51 +00:00
./configure
2016-09-27 20:41:52 +00:00
2016-11-01 20:23:23 +00:00
make -j$(nproc) clean all
2016-08-29 20:38:51 +00:00
# build the fuzzer, linking with libFuzzer and libexpat.a
$CXX $CXXFLAGS -std=c++11 -Ilib/ \
2016-10-19 20:04:35 +00:00
/src/parse_fuzzer.cc -o /out/expat_parse_fuzzer \
2016-10-17 21:32:10 +00:00
-lfuzzer .libs/libexpat.a \
2016-10-13 21:19:30 +00:00
$FUZZER_LDFLAGS
2016-08-29 20:38:51 +00:00
```
2016-09-27 20:41:52 +00:00
### build.sh Script Environment
2016-08-29 20:38:51 +00:00
2016-09-27 20:41:52 +00:00
When build.sh script is executed, the following locations are available within the image:
2016-08-29 20:38:51 +00:00
2016-10-18 22:37:23 +00:00
| Path | Description
| ------ | -----
2016-10-25 23:36:29 +00:00
| `/src/<some_dir>` | Source code needed to build your target.
2016-10-17 21:32:10 +00:00
| `/usr/lib/libfuzzer.a` | Prebuilt libFuzzer library that need to be linked into all fuzzers (`-lfuzzer`).
2016-09-27 20:41:52 +00:00
2016-10-25 23:36:29 +00:00
You *must* use special compiler flags to build your target and fuzzers.
2016-09-27 20:41:52 +00:00
These flags are provided in following environment variables:
2016-10-13 21:19:30 +00:00
| Env Variable | Description
| ------------- | --------
| `$CC` , `$CXX` , `$CCC` | The C and C++ compiler binaries.
| `$CFLAGS` , `$CXXFLAGS` | C and C++ compiler flags.
| `$FUZZER_LDFLAGS` | Linker flags for fuzzer binaries.
2016-09-27 20:41:52 +00:00
Many well-crafted build scripts will automatically use these variables. If not,
passing them manually to a build tool might be required.
2016-08-29 20:38:51 +00:00
2016-10-13 21:03:43 +00:00
See [Provided Environment Variables ](../infra/base-images/base-libfuzzer/README.md#provided-environment-variables ) section in
`base-libfuzzer` image documentation for more details.
2016-10-13 15:24:56 +00:00
### Custom libFuzzer options for ClusterFuzz
2016-09-27 21:07:19 +00:00
2016-10-13 15:27:26 +00:00
By default ClusterFuzz will run your fuzzer without any options. You can specify
2016-10-28 22:09:44 +00:00
custom options by creating a `my_fuzzer.options` file next to a `my_fuzzer` executable in `/out` :
2016-08-30 21:20:32 +00:00
```
2016-10-13 15:33:02 +00:00
[libfuzzer]
2016-10-13 15:24:56 +00:00
max_len = 1024
2016-08-30 21:20:32 +00:00
```
2016-10-13 15:27:26 +00:00
[List of available options ](http://llvm.org/docs/LibFuzzer.html#options )
2016-10-13 15:24:56 +00:00
2016-10-13 15:27:26 +00:00
At least `max_len` is highly recommended.
For out of tree fuzzers you will likely add options file using docker's
2016-10-13 15:24:56 +00:00
`COPY` directive and will copy it into output in build script.
2016-10-28 22:29:42 +00:00
([Woff2 example](https://github.com/google/oss-fuzz/blob/master/targets/woff2/convert_woff2ttf_fuzzer.options).)
2016-10-28 22:09:44 +00:00
2016-10-28 22:13:26 +00:00
### Seed Corpus
2016-10-28 22:09:44 +00:00
oss-fuzz uses evolutionary fuzzing algorithms. Supplying seed corpus consisting
of sample inputs is one of the best ways to improve fuzzer coverage.
To provide a corpus for `my_fuzzer` , put `my_fuzzer_seed_corpus.zip` file next
to the fuzzer binary in `/out` during the build. Individual files in the zip file
will be used as starting inputs for mutations. You can store the corpus next to
source files, generate during build or fetch it using curl or any other tool of
2016-10-28 22:29:42 +00:00
your choice.
([Boringssl example](https://github.com/google/oss-fuzz/blob/master/targets/boringssl/build.sh#L42).)
2016-10-28 22:09:44 +00:00
Seed corpus files will be used for cross-mutations and portions of them might appear
in bug reports or be used for further security research. It is important that corpus
has an appropriate and consistent license.
2016-10-13 15:24:56 +00:00
### Dictionaries
2016-08-30 21:20:32 +00:00
2016-10-13 15:24:56 +00:00
Dictionaries hugely improve fuzzer effectiveness for inputs with lots of similar
sequences of bytes. [libFuzzer documentation ](http://llvm.org/docs/LibFuzzer.html#dictionaries )
2016-08-29 20:38:51 +00:00
2016-10-28 22:09:44 +00:00
Put your dict file in `/out` and specify in .options file:
2016-10-13 15:24:56 +00:00
```
[libfuzzer]
dict = dictionary_name.dict
```
2016-08-29 20:38:51 +00:00
2016-10-28 22:09:44 +00:00
It is common for several fuzzers to reuse the same dictionary if they are fuzzing very similar inputs.
2016-10-28 22:29:42 +00:00
([Expat example](https://github.com/google/oss-fuzz/blob/master/targets/expat/parse_fuzzer.options).)
2016-10-17 19:39:28 +00:00
2016-09-27 20:56:30 +00:00
## Jenkinsfile
This file will be largely the same for most libraries, and is used by our build
infrastructure. For expat, this is:
```groovy
// load libFuzzer pipeline definition.
def libfuzzerBuild = fileLoader.fromGit('infra/libfuzzer-pipeline.groovy',
2016-10-11 21:39:47 +00:00
'https://github.com/google/oss-fuzz.git')
2016-09-27 20:56:30 +00:00
libfuzzerBuild {
git = "git://git.code.sf.net/p/expat/code_git"
}
```
2016-10-25 23:36:29 +00:00
Simply replace the the "git" entry with the correct git url for the target.
2016-09-27 20:56:30 +00:00
*Note*: only git is supported right now.
2016-08-29 20:38:51 +00:00
## Testing locally
2016-09-27 20:41:52 +00:00
Helper script can be used to build images and fuzzers. Non-script
version using docker commands directly is documented [here ](building_running_fuzzers_external.md ).
2016-08-29 20:38:51 +00:00
```bash
2016-09-27 20:41:52 +00:00
$ cd /path/to/oss-fuzz
2016-10-25 23:36:29 +00:00
$ python infra/helper.py build_image $TARGET_NAME
$ python infra/helper.py build_fuzzers $TARGET_NAME
2016-08-29 20:38:51 +00:00
```
2016-10-25 23:36:29 +00:00
This should place the built fuzzers into `/path/to/oss-fuzz/build/out/$TARGET_NAME`
2016-09-01 23:44:09 +00:00
on your machine (`/out` in the container). You can then try to run these fuzzers
inside the container to make sure that they work properly:
2016-08-29 20:38:51 +00:00
```bash
2016-10-25 23:36:29 +00:00
$ python infra/helper.py run_fuzzer $TARGET_NAME name_of_a_fuzzer
2016-08-29 20:38:51 +00:00
```
If everything works locally, then it should also work on our automated builders
and ClusterFuzz.
2016-10-14 01:07:57 +00:00
It's recommended to look at coverage as a sanity check to make sure that fuzzer gets to the code you expect.
```bash
2016-10-25 23:36:29 +00:00
$ python infra/helper.py coverage $TARGET_NAME name_of_a_fuzzer
2016-10-14 01:07:57 +00:00
```
2016-10-04 18:55:46 +00:00
## Debugging Problems
2016-09-29 20:02:03 +00:00
2016-10-04 18:58:18 +00:00
[Debugging ](debugging.md ) document lists ways to debug your build scripts or fuzzers
in case you run into problems.
2016-09-29 20:02:03 +00:00
2016-08-29 20:38:51 +00:00
## Checking in to oss-fuzz repository
Fork oss-fuzz, commit and push to the fork, and then create a pull request with
2016-10-13 21:07:40 +00:00
your change! Follow the [Forking Project ](https://guides.github.com/activities/forking/ ) guide
if you are new to contributing via GitHub.
2016-08-29 20:38:51 +00:00
### Copyright headers
Please include copyright headers for all files checked in to oss-fuzz:
```
# Copyright 2016 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################
```
If porting a fuzzer from Chromium, keep the Chromium license header.
## The end
Once your change is merged, the fuzzers should be automatically built and run on
ClusterFuzz after a short while!
[oss-fuzz repo]: https://github.com/google/oss-fuzz
2016-08-30 21:20:32 +00:00
[dictionaries]: http://llvm.org/docs/LibFuzzer.html#dictionaries
2016-09-01 18:39:23 +00:00
[Install Docker]: https://docs.docker.com/engine/installation/linux/ubuntulinux/