microsoft/openvmm

Public

mirrored from https://github.com/microsoft/openvmmAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
72af67f6f4d9d042a32318a024b4ccb612bbd2db

Branches

Tags

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

Clone

HTTPS

Download ZIP

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

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