Run Fuzzing
Fuzz testing or fuzzing is a software testing technique to discover vulnerabilities, crashes, and unexpected behaviors in a program. EmbedOps CLI can be used to add a fuzz testing template to get you started on running a fuzzer on your project.
Prerequisites
- EmbedOps CLI is installed. Check out the How-To Install EmbedOps CLI page.
- Log in to the EmbedOps platform. Check out the How-To Log In page.
Steps
1. Connect Your Project To The EmbedOps Platform
Running the following command in the root of your project connects it to the EmbedOps platform and creates the configuration files for a dev container and a Continuous Integration (CI) pipeline.
2. Add The Fuzzing Template
Running the following command adds the scripts to run a fuzzing example to your project. It will prompt for the pipeline provider, and what name you'd like the fuzzing example directory to be called. This example directory can be called anything, but ideally you'll want to use a new folder name (i.e. one that doesn't yet exist).
Once these files are added you'll see the following:
fuzzing
├── ci
│ ├── fuzzing.gitlab.yml
│ ├── fuzzing.sh
│ ...
└── fuzzingExample
├── CMakeLists.txt
├── ReadMe.md
├── corpus
│ ├── overflow_int64_seed
│ ├── overflow_uint32_seed
│ ├── starting_seed_1
│ └── string_finder_seed
├── main_no_crash.c
├── main_with_crash.c
├── more_fuzzing.c
└── more_fuzzing.h
-
A
cifolder that contains thefuzzing.shscript. This is what gets called when you runeo run fuzzing. Thefuzzing.shscript uses CMake to build the example project and run the fuzzing target. -
The folder name that you specified in
eo add fuzzing. This folder contains the following:- Directory named
corpuswith a few files. These files are used as initial seed data for the fuzz run - A
CMakeLists.txtused as part of the cmake build process to build the fuzzing project with llvm (clang). libFuzzer is used under the covers, and thus whatever is desired to be fuzzed must be built with clang.
- Directory named
3. Run The Fuzzing Example
-
Open your project in Visual Studio Code.
-
If the Dev Containers extension has not been installed, go to the Extensions tab on the left column, search for
Dev Containers, and install it. -
Open the Command Palette with
command + shift + P, search forDev Containers: Reopen in Container, and press enter. This will create a development container with the directories and files in your project and the necessary dependencies to run the fuzzing example. -
Open the Command Palette again, search for
View: Toggle Terminal, and press enter. This will open a terminal in the development container. -
Run the fuzzing example with:
-
A few reports are generated. All this information is sent to EmbedOps if using a CI run. (i.e. on GitHub Actions, etc)
fuzz_output.log- Copy of the build log that was outputted to the terminal screen.
coverage.lcov- Line and Branch coverage file.
Note: You can also run this exact command outside of the devcontainer. To do so you'll want to install the devcontainer CLI:
Info
Install the devcontainer CLI and run it outside of the container.
host> brew install npm
host> sudo npm install -g @devcontainers/cli
host> devcontainer up --workspace-folder .
host> eo run fuzzing
For installation on other OSes, please follow the official installation guide
4. Setting and Overriding Configurations
The eo run fuzzing command is a wrapper around eo fuzz. eo run fuzzing is intended to be used with the example template and will look for and execute ci/fuzzing.sh which will eventually execute eo fuzz. The eo fuzz command takes optional arguments that specify things like corpus directory, total fuzzing runtime, maximum crashes allowed, and more. To see a full list of possible arguments run:
eo fuzz has an option called --bin-path. This option specifies the binary you'll run fuzzing on. If this option is not present, then eo fuzz will attempt to locate the ci/fuzzing.sh script and run that.
On a normal run, eo fuzz pulls all of its configuration from the EmbedOps platform
Fuzzing Configuration page for the repo (created when you ran eo init).
You can reach this page by running eo open at the root of the repo (at the same level the .embedops directory exists) and navigate to Security > Fuzzing Configuration
Whatever is set on this page will be used for the given eo fuzz run. Any of these arguments can be overridden locally on the command line. To see the options available to override use eo fuzz --help.
Additionally, eo fuzz attempts to ensure that there is no architecture mismatch between fuzzing binaries that have been built and the system (for example, one built on the devcontainer won't work locally). If this is giving issues, you can override this check by adding the --ignore-arch 1 option to eo fuzz.
5. Run The Fuzzing Example With Crashes
The fuzzing example is configured to run a program without crashes. To run fuzzing with crashes, update fuzzingExample/CMakeLists.txt as shown below to point to main_with_crash.c (Here this is assuming that you've named your directory for fuzzing from Step 2 fuzzingExample. Replace fuzzingExample below with whatever you've named it from Step 2.):
--- a/fuzzingExample/CMakeLists.txt
+++ b/fuzzingExample/CMakeLists.txt
@@ -13,7 +13,7 @@ add_executable(${LOCAL_PROJ_NAME})
# Add all the files (here you can add your own files or add more)
target_sources(${LOCAL_PROJ_NAME} PRIVATE
- ${CMAKE_CURRENT_LIST_DIR}/main_no_crash.c
+ ${CMAKE_CURRENT_LIST_DIR}/main_with_crash.c
${CMAKE_CURRENT_LIST_DIR}/more_fuzzing.c
)
You can update the file in a text editor or with the following bash command:
Then, repeat Step 3 to rebuild and rerun the fuzzing example.
6. Fuzz Reports on the EmbedOps Platform
The fuzz data is automatically sent to the EmbedOps Platform while running.
You can reach this page by running eo open at the root of the repo (at the same level the .embedops directory exists) and navigate to Security > Dashboard.
Running eo fuzz in your local terminal will generate a single data point in the report. If ran in CI, you will get historical data of fuzzing runs for that branch.
7. Run Fuzzer On Your Project
This example is a quick intro on how to use fuzzing. Use the existing CMake file to compile certain sections of your own code base with Clang and run fuzzing on your own code. It is suggested to start small as trying to compile your entire project with Clang may take some time since you'll likely need to fake out different compiler-specific and embedded targeted items.
One example would be taking a single static function and getting that to compile with Clang. Then call it from LLVMFuzzerTestOneInput() and watch it fuzz.
Because eo run fuzzing relies on libFuzzer, you must compile with a version of Clang that contains libFuzzer. The compiler options specified
in the example CMakeLists.txt (specifically the -fsanitize=fuzzer, -fcoverage-mapping, and -fprofile-instr-generate MUST be used when building). In addition,
compiling with debug symbols on (-g) will make it easier to debug any crashes that fuzzing finds.
Please refer to the fuzzingExample/ReadMe.md (the ReadMe.md file generated in Step 2) to learn more about how to add fuzzing to your project.


