An automatic fuzzing tool for ROS 2 C++ projects. The tool comprises two different commands: auto_detector
and ros2_fuzzer
.
Install the ros_automatic_fuzzer
folder with pip:
pip3 install -e ros2_automatic_fuzzer
Alternatively, start the start.sh
command, which spawn a Docker container with both the examples and the tool.
- Navigate to your ROS working space.
- Run
auto_detector
. This generates afuzz.yaml
file withTODO
gaps. - Fill the missing
TODO
s in thefuzz.yaml
file and complete it. - Run
ros2_fuzzer
and follow the instructions. - Add the generated fuzzers to their CMakeLists.txt.
- Make a clean build with the
CC
andCXX
environment variables pointing to AFL. - Run the AFL fuzzers.
Check the following sections for detailed instructions for each step.
The auto_detector
command generates a YAML file called fuzz.yaml
which contains descriptions for three types of artifacts: topics, services, and action servers. The detection process relies on regular expressions in C++, and therefore it is not bullet-proof.
Optional arguments:
--path PATH
. The path where to search for ROS artifacts. By default it is the working directory.
Optional flags:
-f
or--overwrite
to force overwriting the file.-v
or--verbose
to increase the output verbosity.
Typical bash invocation:
auto_detector
The fuzz.yaml
file contains descriptions for topics, services, and action servers. Some of the fields can be automatically extracted in the previous step thanks to the auto_detector
command, but others must be manually introduced. There may be TODO
blanks that must be filled.
The format is simple: there are three optional categories: topics
, services
and actions
. Each of those is a dictionary, with the keys being the name of the artifact. Each artifact contains the following descriptors:
headers_file
(compulsory). A string pointing to thehpp
file where the type of the artifact is defined (the topic type, the service type, or the action type). Sometimes it can be directly inferred.source
(compulsory). A relative path to thefuzz.yaml
file where the artifact to be fuzzed is located. It must be a C++ source code file.type
(compulsory). The type of the fuzzed artifact. It must conform to theros2 interface show
syntax. That is, with::
as a separator and providing the full type. Correct examples areexample_interfaces::srv::AddTwoInts
andstd_msgs::msg::String
, but notexample_interfaces/srv/AddTwoInts
norString
.parameters
(optional). A list with all the parameters of the artifact. It can be inferred with theauto_detector
command.
Follows a concrete example. You can also check the syntax that is followed in the YAML schema, which all fuzz.yaml
files must conform to.
topics:
minimal_topic:
headers_file: std_msgs/msg/string.hpp
source: src/publisher_subscriber_example/src/publisher_member_function.cpp
type: std_msgs::msg::String
parameters: []
topic:
headers_file: std_msgs/msg/string.hpp
source: src/parameters_example_package/src/fuzz_target.cpp
type: std_msgs::msg::String
parameters: []
services:
add_two_ints:
headers_file: example_interfaces/srv/add_two_ints.hpp
node_name: minimal_subscriber
source: src/parameters_example_package/src/add_two_ints_server.cpp
type: example_interfaces::srv::AddTwoInts
parameters: []
add_three_ints:
headers_file: tutorial_interfaces/srv/add_three_ints.hpp
source: src/client_service_example/src/add_three_ints_server.cpp
type: tutorial_interfaces::srv::AddThreeInts
parameters: []
It consumes the fuzz.yaml
file to generate C++ fuzzers for the selected artifacts. It allows generating fuzzers for all or some of them. Simply follow the steps on the screen. It may require calling ros2 interface show
, and thus sourcing the ROS setup bash (with . install/setup.bash
) may be required.
Optional arguments:
--path PATH
. The path where to search for afuzz.yaml
file. By default it is on the working directory.
Optional flags:
-v
or--verbose
to increase the output verbosity.
Typical bash invocation:
ros2_fuzzer
The ros2_fuzzer
command generates files of the *_generated.cpp
form, which have to be linked to their CMakeList.txt
files to be compiled.
For example, for the following fuzz.yaml
file:
services:
add_three_ints:
headers_file: tutorial_interfaces/srv/add_three_ints.hpp
source: src/client_service_example/src/add_three_ints_server.cpp
type: tutorial_interfaces::srv::AddThreeInts
parameters: []
The following code can be added into its CMakeLists.txt
file (the generated_fuzzer
keyword can be changed):
add_executable(generated_fuzzer src/add_three_ints_server_generated.cpp)
ament_target_dependencies(generated_fuzzer rclcpp tutorial_interfaces)
install(TARGETS generated_fuzzer DESTINATION lib/${PROJECT_NAME})
To fuzz your C++ artifacts, it is necessary to recompile the projects so that they include instrumentalization annotations on the byte code to be used in the fuzzing search. We have decided to use AFL, an state-of-the-art fuzzer backed by Google.
If you haven't done so, you can install AFL with
apt install afl
To use it, set the CC
and CXX
environment variables to point to AFL and build the projects. We add the --cmake-clean-cache
flag to prevent stale build files. Of course, you can use a more sofisticated way to build your projects, but make sure that the AFL's instrumentalization takes place.
export CC=afl-gcc
export CXX=afl-g++
colcon build --cmake-clean-cache
Navigate to install/<package>/lib/<package>/
, where <package>
is the name of your ROS package (or wherever the installation files are placed) and start the fuzzing search.
The command requires an inputs/
folder, with some files with content. You can use random values extracted from /dev/urandom
, for instance:
mkdir inputs
head -c 50 /dev/urandom > inputs/input0.txt
Now execute the afl-fuzz
command (from AFL). Use the name of the executable found in that folder (try an ls
) as the last parameter. The example shown in step #5 would be fuzzed with the following command:
afl-fuzz -i inputs/ -o outputs/ -m none -- ./generated_fuzzer
You should just change the generated_fuzzer
execution file to yours to make AFL work.
Supported by ROSIN - ROS-Industrial Quality-Assured Robot Software Components. More information: rosin-project.eu
This project has received funding from the European Union’s Horizon 2020 research and innovation programme under grant agreement no. 732287.