update the README to reflect recent decisions

pull/1/head
Levi Rak 2017-07-20 15:06:20 -06:00
parent 168332e84a
commit 6549bb51ca
1 changed files with 68 additions and 69 deletions

137
README.md
View File

@ -1,7 +1,7 @@
Fuzz Targets Fuzz Targets
============ ============
The files in this directory are fuzzing targets for wolfSSL. They follow the The files in this repository are fuzzing targets for wolfSSL. They follow the
LLVM libFuzzer API and have a very specific naming scheme for integration with LLVM libFuzzer API and have a very specific naming scheme for integration with
[Google's OSS-Fuzz service][oss-fuzz]. For more information about these [Google's OSS-Fuzz service][oss-fuzz]. For more information about these
qualities, see [the section on making new targets](#new_target) below. To be qualities, see [the section on making new targets](#new_target) below. To be
@ -9,7 +9,7 @@ run, they must be linked against `libFuzzer.a`. For more information about
compilation, see [the section on compiling](#compiling_target) below. compilation, see [the section on compiling](#compiling_target) below.
[The very last section of this README](#future) is meant to document the [The very last section of this README](#future) is meant to document the
foreseeable future of this directory, including suggestions on what fuzz foreseeable future of this repository, including suggestions on what fuzz
targets should be written next. It is requested that future editors of this targets should be written next. It is requested that future editors of this
directory update that section to reflect their work and thoughts. directory update that section to reflect their work and thoughts.
@ -25,20 +25,21 @@ For information on how to get a target running inside of OSS-Fuzz, see [the
section on OSS-Fuzz](#with_oss-fuzz) below. section on OSS-Fuzz](#with_oss-fuzz) below.
For the entirety of this section, let "`fuzz_target`" be a stand-in for the For the entirety of this section, let "`fuzz_target`" be a stand-in for the
name of your target. It will be identical to the file name of the source code, name of your target. It will be identical to the directory name containing the
but with out the ".c" extension. source code.
If you have access to the make utility, everything will be simple: simply If you have access to the make utility, everything will be simple. Before
execute `make fuzz_target` to compile it. If necessary, make will automatically compiling any individual target, run `make deps`. If necessary, make will
retrieve the libFuzzer library and the most recent version of clang, both of automatically retrieve the libFuzzer library and the most recent version of
which are required for compilation. Neither are installed, but kept locally clang, both of which are required for compilation. Neither are installed, but
instead. If you wish to get these dependencies explicitly, call `make deps` or kept locally instead. `make dependencies` is synonymous.
`make dependencies`. They are synonymous
Furthermore, running `make` or `make all` will compile all files ending in ".c" From there, simply execute `make fuzz_target` to compile a fuzz target.
as fuzz targets, running `make clean` will delete the compiled fuzz targets but
leave the source files intact, and running `make spotless` will act like `make Furthermore, running `make` or `make all` will compile all fuzz targets,
clean` but also delete libFuzzer and clang. running `make clean` will delete the compiled fuzz targets but leave the source
files intact, and running `make spotless` will act like `make clean` but also
delete the dependencies build by `make deps`.
If you don't have access to make, you're going to have to do it all by hand. If you don't have access to make, you're going to have to do it all by hand.
What follows for the rest of this section are the instructions for doing what What follows for the rest of this section are the instructions for doing what
@ -57,8 +58,10 @@ The first thing to do is to get libFuzzer. To do this, run these commands from
the shell: the shell:
``` ```
$ git clone https://chromium.googlesource.com/chromium/llvm-project/llvm/lib/Fuzzer Fuzzer $ url=https://chromium.googlesource.com/chromium/llvm-project/llvm/lib/Fuzzer
$ git clone $url Fuzzer
$ ./Fuzzer/build.sh $ ./Fuzzer/build.sh
$ rm -rf Fuzzer
``` ```
The above clones in the libFuzzer git repository then builds it. There should The above clones in the libFuzzer git repository then builds it. There should
@ -71,48 +74,44 @@ use those tools to pull down the most up-to-date version of clang then make a
link for our convenience. In all, that looks like this: link for our convenience. In all, that looks like this:
``` ```
$ export CLANG_TOOLS=https://chromium.googlesource.com/chromium/src/tools/clang $ url=https://chromium.googlesource.com/chromium/src/tools/clang
$ git clone $CLANG_TOOLS new_clang/clang/clang $ git clone $url new_clang/clang/clang
$ python new_clang/clang/clang/scripts/update.py $ python new_clang/clang/clang/scripts/update.py
$ cp -s -t . new_clang/third_party/llvm-build/Release+Asserts/bin/clang{,++} $ ln -s -t . new_clang/third_party/llvm-build/Release+Asserts/bin/clang{,++}
``` ```
And with that, you now have a recent version of clang. It has not been And with that, you now have a recent version of clang. It has not been
installed, so to use it you'll have to call clang like installed, so to use it you'll have to call clang like `./clang` from this
``` directory.
$ ./clang
```
from this directory. Alternatively, you could call it like
```
$ ./new_clang/third_party/llvm-build/Release+Asserts/bin/clang
```
but that's a huge command. That's why we make links.
To compile, run these commands from the shell: To compile, run these commands from the shell:
``` ```
$ ./clang -fsanitize=address -fsanitize-coverage=trace-pc-guard -c fuzz_target.c -o fuzz_target.o $ CFLAGS="-fsanitize=address -fsanitize-coverage=trace-pc-guard"
$ ./clang++ -fsanitize=address -fsanitize-coverage=trace-pc-guard fuzz_target.o -L. -lwolfssl -lFuzzer -o fuzz_target $ LDFLAGS="-L. -lwolfssl -lFuzzer"
$ ./clang $CFLAGS -c fuzz_target/target.c -o fuzz_target/target.o
$ ./clang++ $CFLAGS fuzz_target/target.o -o fuzz_target/target $LDFLAGS
$ rm fuzz_target.o $ rm fuzz_target.o
``` ```
And with that, `fuzz_target` has been compiled. This compile step is the only And with that, `fuzz_target` has been compiled. This compile step is the only
<a name="run_target">Running Targets</a> <a name="run_target">Running Targets</a>
---------------------------------------- ----------------------------------------
For the entirety of this section, let "`fuzz_target`" be a stand-in for the For the entirety of this section, let "`fuzz_target`" be a stand-in for the
name of your target. It will be identical to the file name of the source code, name of your target. It will be identical to the directory name containing
but with out the ".c" extention. the source code.
After compiling, `fuzz_target` is an executable that can be called like this: After compiling, `cd` into `fuzz_target/`, and `target` is an executable that
can be called like this:
``` ```
$ ./fuzz_target [OPTION ...] [CORPUS ...] $ ./target [OPTION ...] [CORPUS ...]
``` ```
or or
``` ```
$ ./fuzz_target [OPTION ...] [FILE ...] $ ./target [OPTION ...] [FILE ...]
``` ```
A corpus is a directory with files containing example input data, good or bad, A corpus is a directory with files containing example input data, good or bad,
@ -137,34 +136,33 @@ fuzz target: [source code](#target_src), [options](#target_opt), and
[corpus](#target_corp). See their respective subsections below for more [corpus](#target_corp). See their respective subsections below for more
information on each. information on each.
All three parts must be placed in the same directory with all the other fuzz All three parts must be placed in the same directory, but separate from any
targets. There are no exceptions; failure to comply with this will prevent your other fuzz target. The name of this directory will be the name of the fuzz
target. There are no exceptions; failure to comply with this will prevent your
fuzz target from being found by OSS-Fuzz. fuzz target from being found by OSS-Fuzz.
The only required part is the source code; options files and corpuses (corpi?) The only required part is the source code; options files and corpora may be
may be omitted, though it is recommended that you include all three components. omitted, though it is recommended that you at least also include a corpus.
The fourth, extra optional part is the dictionary. You can read more about how The fourth, extra optional part is the dictionary. You can read more about how
to use or include them in [the OSS-Fuzz documentation][dict]. If you wish to to use or include them in [the OSS-Fuzz documentation][dict]. If you wish to
include one, create a file ending in ".dict" in this directory, then add a line include one, create a file ending in ".dict" in the root directory of this
like this to the options file for the fuzz target that will use it: repository, then add a line like this to the options file for the fuzz target
that will use it:
``` ```
[libfuzzer] [libfuzzer]
dict = my_dictionary.dict dict = my_dictionary.dict
``` ```
Furthermore, in this directory is a file named `user_settings.h`. The contents Note that dictionaries are found relative to the root directory of this
of this file will be used when compiling wolfSSL in the OSS-Fuzz environment. repository. Do not use relative or absolute paths, simply the name of the file.
It's most important job is to replace the random number generator with a
counter so that wolfSSL will behave deterministically.
### <a name="target_src">Source Code</a> ### <a name="target_src">Source Code</a>
The source code is more or less what you'd expect: the code describing the The source code is more or less what you'd expect: the code describing the
test. It can be named however you like, though must end with ".c". Internally, test. It must be named `target.c`. Internally, the only requirement is that it
the only requirement is that it not implement `main()` and instead implement a not implement `main()` and instead implement a function for this prototype:
function for this prototype:
```c ```c
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz); int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz);
@ -178,21 +176,17 @@ the content of a file. If the target was invoked at the command line with file
names, the content of data will be exactly the content of the file. Otherwise, names, the content of data will be exactly the content of the file. Otherwise,
it will contain the fuzzed version of files in the corpus. it will contain the fuzzed version of files in the corpus.
From here, all you need to do to accomplish the test is to pass `data` and `sz` From here, `data` and `sz` must become the input of another function. In many
to whatever API call you wish to fuzz. For examples, please see the other fuzz cases, this is as simple as using `data` and `sz` in the function call, but
targets contained in this directory. sometimes creativity must be used to expose the library to the fuzzed data.
### <a name="target_opt">Options</a> ### <a name="target_opt">Options</a>
An options file will indicate to OSS-Fuzz which flags and values to pass to the An options file will indicate to OSS-Fuzz which flags and values to pass to the
fuzz target when running it. It is not required, but it is recommended that you fuzz target when running it. An options file must be named `target.options`.
at least define `max_len`.
An options file should be named the same as the source code, but with
".options" in place of ".c".
The format seems to be similar to [the ini format][ini], though no explicit The format seems to be similar to [the ini format][ini], though no explicit
confirmation of this was found. Regardless, a file about like this is suitable: confirmation of this was found. For example, a file like this is valid:
``` ```
[libfuzzer] [libfuzzer]
@ -208,12 +202,13 @@ recommended that you include a few examples of good input. If ever fuzzing
finds an example of bad input, it is also recommended that you add this bad finds an example of bad input, it is also recommended that you add this bad
input to make sure the problem that created it is not re-introduced. input to make sure the problem that created it is not re-introduced.
The corpus must be a directory named the same as the source code, but with The corpus must be a directory. It may have any name, though know that when
`_corpus` in place of ".c". OSS-Fuzz tries to find corpora, it will assume every directory in the target's
directory is a corpus.
The contents of the corpus do not need to conform to any kind of naming scheme, The contents of the corpus do not need to conform to any kind of naming scheme,
though libFuzzer expects the file's name to be the sha1 sum of the file, and so though libFuzzer is happiest when the file's name is the sha1 sum of the file,
it is recommended that all corpus files are named accordingly. and so it is recommended that all corpus files are named accordingly.
<a name="with_oss-fuzz">Running Targets in OSS-Fuzz</a> <a name="with_oss-fuzz">Running Targets in OSS-Fuzz</a>
------------------------------------------------------- -------------------------------------------------------
@ -242,13 +237,16 @@ $ git clone https://github.com/google/oss-fuzz
Note that if you are going to be modifying the fuzz targets, you'll need to Note that if you are going to be modifying the fuzz targets, you'll need to
modify where Docker will get its targets. Open modify where Docker will get its targets. Open
`./oss-fuzz/projects/wolfssl/Dockerfile` and change the line `./oss-fuzz/projects/wolfssl/Dockerfile` and change this line:
``` ```
RUN git clone --depth 1 https://github.com/wolfssl/wolfssl.git wolfssl RUN git clone --depth 1 https://github.com/wolfssl/wolfssl.git wolfssl
``` ```
to something like this: to something like this:
``` ```
RUN git clone --depth 1 https://github.com/<you>/wolfssl.git -b <work_branch>wolfssl RUN git clone --depth 1 https://github.com/<you>/wolfssl.git -b <work_branch> wolfssl
``` ```
Be sure to replace `<you>` with your github user name and `<work_branch>` with Be sure to replace `<you>` with your github user name and `<work_branch>` with
@ -270,20 +268,21 @@ You may also choose to use `memory` or `undefined` for the sanitizer option.
To actually run a fuzz target, run this command: To actually run a fuzz target, run this command:
``` ```
# python infra/helper.py run_fuzzer wolfssl <fuzz_target> # python infra/helper.py run_fuzzer wolfssl fuzz_target
``` ```
Where `<fuzz_target>` corresponds with the file name (without the ".c") of the Where `fuzz_target` stands for the fuzz target you wish to run. The name of the
target you wish to run. fuzz target corresponds with the directory name containing the source code of
the target you wish to run.
<a name="future">Future Direction</a> <a name="future">Future Direction</a>
------------------------------------- -------------------------------------
Add more tests for various wolfSSL and wolfCrypt APIs. Focus on APIs which Add more tests for various wolfSSL and wolfCrypt APIs. Focus on APIs which
process buffers containing data that plausibly could originate from some process buffers containing data that plausibly could originate from some
outside source. As examples, in `server.c` the fuzzed data is impersonating a outside source. It is possible that a target for any given API has already been
server, and in `pem2der.c` the fuzzed data is used as a PEM certificate. In written: check the private wolfssl testing repository for targets before
each case, the fuzzed data represents malformed input. writing them yourself.
<!-- References --> <!-- References -->
[libFuzzer]: http://llvm.org/docs/LibFuzzer.html [libFuzzer]: http://llvm.org/docs/LibFuzzer.html