microsoft/openvmm

Public

mirrored fromhttps://github.com/microsoft/openvmmAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
045b1b0dbef400c88d68fce3fbe84ee2cedb2fa2

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

Guide/src/dev_guide/tests/fuzzing/running.md

168lines · modecode

1# Running Fuzzers Locally
2
3## Installing Dependencies
4
5To begin fuzzing in OpenVMM, you'll need to install `cargo-fuzz` and a nightly
6rust compiler.
7
8Installation should be as simple as:
9
10```bash
11rustup install nightly
12cargo install cargo-fuzz
13```
14
15```admonish info
16`cargo-fuzz` requires a nightly toolchain as it compiles targets with
17[ASAN](https://learn.microsoft.com/en-us/cpp/sanitizers/asan?view=msvc-170) to
18improve the likelihood of finding bugs and the reproducibility of testcases.
19```
20
21## Running
22
23While its entirely possible to run the various fuzzers in the OpenVMM repo using
24`cargo fuzz` directly, the OpenVMM repo includes additional tooling to streamline
25working with fuzzers at "OpenVMM scale": `cargo xtask fuzz`
26
27`cargo xtask fuzz` bridges the gap between `cargo fuzz`'s "crate-oriented"
28tooling, and OpenVMM's "repo-oriented" tooling.
29
30e.g: instead of manually navigating to each individual `crate/fuzz` directory in
31order to use `cargo fuzz`, with `cargo xtask fuzz`, you can list/run/build _any_
32fuzzer in the OpenVMM repo, regardless where it happens to be in the repo!
33
34Before you can run a fuzzer, you need to know its name. To see a list of all
35fuzzers currently in the OpenVMM tree, you can run:
36
37```bash
38cargo xtask fuzz list
39```
40
41The output will be a list of available "fuzz targets":
42
43```bash
44$ cargo xtask fuzz list
45fuzz_chipset_battery
46fuzz_ide
47fuzz_scsi_buffers
48```
49
50Once you've got a fuzzer you're interested in running (e.g: `fuzz_ide`),
51starting a fuzzing session is as easy as running:
52
53```bash
54cargo xtask fuzz run fuzz_ide
55```
56
57And you're off! If you see a whole bunch of terminal spew, congrats, you're
58fuzzing!
59
60When run locally using the above command, the fuzzer will run indefinitely until
61a crash is discovered.
62
63If you need to tweak the runtime behavior of the command, all of libFuzzer's
64[commandline options][cli-opts] are at your disposal. Alternatively you can
65print the help of the fuzzer like so:
66
67```bash
68# NOTE: The "-- --" is required to differentiate between `xtask fuzz`'s
69# extra-args, and `cargo fuzz`'s extra-args
70cargo xtask fuzz run fuzz_ide -- -- -help=1
71```
72
73[cli-opts]: https://www.llvm.org/docs/LibFuzzer.html#options
74
75## Other Fuzzing Commands
76
77The `cargo xtask fuzz` CLI includes plenty of docs via `--help` text. Don't be
78afraid to dig into all the tools available via `cargo xtask fuzz` by using
79`--help` at both the top-level, and for more details regarding the various
80subcommands.
81
82Note that most `cargo xtask fuzz` commands mirror those from `cargo fuzz`, so
83for additional information on how certain commands work, check out the
84[cargo-fuzz book](https://rust-fuzz.github.io/book/cargo-fuzz.html).
85
86## Coverage
87
88The effectiveness of fuzzing can be measured with code coverage.
89
90Code coverage can be analyzed to determine which branches in the target were
91exercised and which were missed by the fuzzer. This can be used to determine if
92the fuzzer needs improvements or is doing an adequate job.
93
94Before you begin you'll need some additional dependencies to generate an html
95report:
96
97```bash
98rustup +nightly component add llvm-tools
99apt install lcov
100```
101
102To generate a report with "sane defaults", you can simply run:
103
104```bash
105cargo xtask fuzz coverage fuzz_ide --with-html-report
106```
107
108Simply navigate to the `html/report/dir/index.html`` on your machine and inspect the coverage!
109
110![LCOV Example](./_images/fuzz_lcov_example.png "Viewing the coverage of vm/devices/storage/ide/src generated by fuzz_ide")
111
112```admonish note
113`--with-html-report` offers a quick-and-easy way for an individual user
114generate a coverage report locally, but it may not be entirely appropriate for
115more "industrial scale" fuzzing pipelines.
116```
117
118### Manual Coverage Generation (Advanced)
119
120The basic way this is done is by running all the discovered input testcases
121through the fuzzer and merging all the coverage events together (remember, the
122fuzzers only save testcases which generate new coverage). Cargo-fuzz provides a
123way to do this with the `coverage` subcommand. This step generates a
124`coverage.profdata` file which can be turned into a human-readable HTML report:
125
126```bash
127# cargo xtask fuzz coverage <fuzzer name>
128cargo xtask fuzz coverage fuzz_ide
129# confirm coverage.profdata was created
130ls -l coverage.profdata
131```
132
133OR if you have a large number of inputs (5k+) the below will collect and merge
134coverage significantly faster:
135
136```bash
137# rebuild the fuzzer with coverage instrumentation
138RUSTFLAGS="-C instrument-coverage" cargo +nightly fuzz build
139# set env var to rustup's llvm-preview tools
140LLVM_TOOLS_PATH=$(dirname $(find $(rustc +nightly --print sysroot) -name 'llvm-profdata'))
141# make an output directory for corups minimation
142mkdir min_corp
143# run the minimizer putting the raw cov data into coverage.profraw
144LLVM_PROFILE_FILE="coverage.profraw" ./fuzz/targets/<target-path>/release/fuzz_ide min_corp <path to input corpus directory> -merge=1
145# merge the raw data into coverage.profdata
146$LLVM_TOOLS_PATH/llvm-profdata merge -sparse coverage.profraw -o coverage.profdata
147```
148
149Next find the location of the llvm-tools you installed with rustup
150(NOTE: rustup is used to install the LLVM tools to ensure that rust's llvm
151version and the tool version are in sync), and convert the coverage data into
152a report:
153
154```bash
155# set env var to rustup's llvm-preview tools
156LLVM_TOOLS_PATH=$(dirname $(find $(rustc +nightly --print sysroot) -name 'llvm-profdata'))
157# covert the coverage data into an lcov format
158$LLVM_TOOLS_PATH/llvm-cov export -instr-profile=coverage.profdata \
159 -format=lcov \
160 -object ./fuzz/targets/<target-triple>/coverage/<target-triple>/release/fuzz_ide \
161 --ignore-filename-regex "rustc" > coverage.lcov
162# summarize the coverage information
163lcov --summary ./coverage.lcov
164# make an output directory for the html report
165mkdir -p lcov_html
166# generate the html report
167genhtml -o lcov_html --legend --highlight ./coverage.lcov
168```
169