microsoft/openvmm

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
e8acaefba35969bbca0ffae96452cd05b47aa621

Branches

Tags

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

Clone

HTTPS

Download ZIP

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

169lines · 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```
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[toolchain-overrides-url]: https://rust-lang.github.io/rustup/overrides.html
75
76## Other Fuzzing Commands
77
78The `cargo xtask fuzz` CLI includes plenty of docs via `--help` text. Don't be
79afraid to dig into all the tools available via `cargo xtask fuzz` by using
80`--help` at both the top-level, and for more details regarding the various
81subcommands.
82
83Note that most `cargo xtask fuzz` commands mirror those from `cargo fuzz`, so
84for additional information on how certain commands work, check out the
85[cargo-fuzz book](https://rust-fuzz.github.io/book/cargo-fuzz.html).
86
87## Coverage
88
89The effectiveness of fuzzing can be measured with code coverage.
90
91Code coverage can be analyzed to determine which branches in the target were
92exercised and which were missed by the fuzzer. This can be used to determine if
93the fuzzer needs improvements or is doing an adequate job.
94
95Before you begin you'll need some additional dependencies to generate an html
96report:
97
98```bash
99rustup +nightly component add llvm-tools
100apt install lcov
101```
102
103To generate a report with "sane defaults", you can simply run:
104
105```bash
106cargo xtask fuzz coverage fuzz_ide --with-html-report
107```
108
109Simply navigate to the `html/report/dir/index.html`` on your machine and inspect the coverage!
110
111![LCOV Example](./_images/fuzz_lcov_example.png "Viewing the coverage of vm/devices/storage/ide/src generated by fuzz_ide")
112
113```admonish note
114`--with-html-report` offers a quick-and-easy way for an individual user
115generate a coverage report locally, but it may not be entirely appropriate for
116more "industrial scale" fuzzing pipelines.
117```
118
119### Manual Coverage Generation (Advanced)
120
121The basic way this is done is by running all the discovered input testcases
122through the fuzzer and merging all the coverage events together (remember, the
123fuzzers only save testcases which generate new coverage). Cargo-fuzz provides a
124way to do this with the `coverage` subcommand. This step generates a
125`coverage.profdata` file which can be turned into a human-readable HTML report:
126
127```bash
128# cargo xtask fuzz coverage <fuzzer name>
129cargo xtask fuzz coverage fuzz_ide
130# confirm coverage.profdata was created
131ls -l coverage.profdata
132```
133
134OR if you have a large number of inputs (5k+) the below will collect and merge
135coverage significantly faster:
136
137```bash
138# rebuild the fuzzer with coverage instrumentation
139RUSTFLAGS="-C instrument-coverage" cargo +nightly fuzz build
140# set env var to rustup's llvm-preview tools
141LLVM_TOOLS_PATH=$(dirname $(find $(rustc +nightly --print sysroot) -name 'llvm-profdata'))
142# make an output directory for corups minimation
143mkdir min_corp
144# run the minimizer putting the raw cov data into coverage.profraw
145LLVM_PROFILE_FILE="coverage.profraw" ./fuzz/targets/<target-path>/release/fuzz_ide min_corp <path to input corpus directory> -merge=1
146# merge the raw data into coverage.profdata
147$LLVM_TOOLS_PATH/llvm-profdata merge -sparse coverage.profraw -o coverage.profdata
148```
149
150Next find the location of the llvm-tools you installed with rustup
151(NOTE: rustup is used to install the LLVM tools to ensure that rust's llvm
152version and the tool version are in sync), and convert the coverage data into
153a report:
154
155```bash
156# set env var to rustup's llvm-preview tools
157LLVM_TOOLS_PATH=$(dirname $(find $(rustc +nightly --print sysroot) -name 'llvm-profdata'))
158# covert the coverage data into an lcov format
159$LLVM_TOOLS_PATH/llvm-cov export -instr-profile=coverage.profdata \
160 -format=lcov \
161 -object ./fuzz/targets/<target-triple>/coverage/<target-triple>/release/fuzz_ide \
162 --ignore-filename-regex "rustc" > coverage.lcov
163# summarize the coverage information
164lcov --summary ./coverage.lcov
165# make an output directory for the html report
166mkdir -p lcov_html
167# generate the html report
168genhtml -o lcov_html --legend --highlight ./coverage.lcov
169```
170