[PATCH 20/21] Documentation: add LLVM libfuzzer documentation
Ahmad Fatoum
a.fatoum at pengutronix.de
Thu Jun 5 04:35:29 PDT 2025
Now that first fuzzing support is in place, add a defconfig and document
how to use it to fuzz.
Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
Documentation/devel/devel.rst | 1 +
Documentation/devel/fuzzing.rst | 106 +++++++++++++++++++++++++
arch/sandbox/Makefile | 5 +-
common/boards/configs/libfuzzer.config | 14 ++++
4 files changed, 125 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devel/fuzzing.rst
create mode 100644 common/boards/configs/libfuzzer.config
diff --git a/Documentation/devel/devel.rst b/Documentation/devel/devel.rst
index 3e9d44218334..d985bff40d42 100644
--- a/Documentation/devel/devel.rst
+++ b/Documentation/devel/devel.rst
@@ -12,6 +12,7 @@ Contents:
filesystems
background-execution
project-ideas
+ fuzzing
* :ref:`search`
* :ref:`genindex`
diff --git a/Documentation/devel/fuzzing.rst b/Documentation/devel/fuzzing.rst
new file mode 100644
index 000000000000..3151246aef1a
--- /dev/null
+++ b/Documentation/devel/fuzzing.rst
@@ -0,0 +1,106 @@
+Fuzzing barebox
+===============
+
+As described in the :ref:`security` chapter, some parts of barebox need to
+deal with untrusted inputs. To aid in finding and fixing issues that might
+be exploited, barebox can be built with LLVM's libfuzzer to exercise
+these security-critical parsers.
+
+Building
+^^^^^^^^
+
+The barebox sandbox architecture has support for libfuzzer when compiled with
+LLVM. The ``libfuzzer_defconfig`` enables it as well as different hardening
+options to crash barebox on detection of memory safety issues::
+
+ $ export LLVM=1 # or e.g. LLVM=-19, if clang is called clang-19
+ $ make libfuzzer_defconfig
+ $ make -j$(nproc)
+ # [snip]
+ images built:
+ barebox
+ fuzz-filetype
+ fuzz-fit
+ fuzz-fs
+ fuzz-dtb
+ fuzz-fdt-compatible
+ fuzz-partitions
+
+All fuzzers generated are symlinks to the same barebox executable. barebox
+will detect that it was invoked via symlink and switch to fuzzing mode.
+
+Fuzzing
+^^^^^^^
+
+Fuzzers can be run directly or by invoked the main barebox binary with the
+``--fuzz`` option. The latter is mostly useful for debugging.
+
+Examples of running the fuzzers::
+
+ # Just run the fuzzer with no corpus
+ images/fuzz-filetype
+
+ # Multi-threaded fuzzing is recommended as is using a corpus
+ images/fuzz-dtb -rss_limit_mb=10000 -max_len=51200 -jobs=64 \
+ ../barebox-fuzz-corpora/dtb
+
+ # Some fuzzers still leak, so disable leak detection till resolved
+ images/fuzz-fit -max_total_time=600 -rss_limit_mb=20000 -max_len=128000 -detect_leaks=0
+
+ # Debug a crash
+ gdb --args images/fuzz-fit crash-$HASH
+
+When a crash is detected, libfuzzer will create a ``crash-$HASH`` file
+that can be passed instead of the corpus directory to run the fuzz test
+once.
+
+Corpora
+^^^^^^^
+
+We maintain a corpus for every fuzz test on
+`Github <https://github.com/barebox/barebox-fuzz-corpora>`_.
+
+This helps bootstrap the fuzzer, so it can exercise new paths more quickly.
+
+Adding a fuzzer
+^^^^^^^^^^^^^^^
+
+The barebox integration of libfuzzer is a bit unusual; barebox supplies
+its own ``main()`` and calls into libfuzzer instead of the over way round.
+
+This allows us to write fuzz tests naturally inline without having
+to setup things beforehand as barebox will have already executed all
+of its initcalls for example.
+
+To add a new fuzz test, just add a function next to the parser that
+parses a memory buffer::
+
+ #include <fuzz.h>
+
+ static int fuzz_dtb(const u8 *data, size_t size)
+ {
+ struct device_node *np;
+
+ np = of_unflatten_dtb_const(data, size);
+ if (!IS_ERR(np))
+ of_delete_node(np);
+
+ return 0;
+ }
+ fuzz_test("dtb", fuzz_dtb);
+
+
+.. note:: Fuzz tests should not leak memory, otherwise
+ the fuzzing process may abort eventually due to memory exhaustion.
+
+This function than needs to be registered by name in
+``images/Makefile.sandbox``::
+
+ fuzzer-$(CONFIG_OFTREE) += dtb
+
+Searching the source tree for ``fuzz_test`` will show more examples,
+e.g. how to wrap the received buffer in a ramdisk to interface
+with code that requires block devices.
+
+When adding a new fuzzing test, please also `submit a pullrequest
+with a corpus <https://github.com/barebox/barebox-fuzz-corpora/compare>_.
diff --git a/arch/sandbox/Makefile b/arch/sandbox/Makefile
index 6566cd563ed8..f33d7fa961da 100644
--- a/arch/sandbox/Makefile
+++ b/arch/sandbox/Makefile
@@ -2,13 +2,16 @@
KBUILD_DEFCONFIG := sandbox_defconfig
-generated_configs += headless_defconfig noshell_defconfig lockdown_defconfig
+generated_configs += headless_defconfig noshell_defconfig lockdown_defconfig \
+ libfuzzer_defconfig
headless_defconfig:
$(call merge_into_defconfig,sandbox_defconfig,headless)
noshell_defconfig:
$(call merge_into_defconfig,sandbox_defconfig,noshell)
lockdown_defconfig:
$(call merge_into_defconfig,sandbox_defconfig,headless noshell)
+libfuzzer_defconfig:
+ $(call merge_into_defconfig,sandbox_defconfig,libfuzzer)
KBUILD_CPPFLAGS += -D__SANDBOX__ -fno-strict-aliasing -fvisibility=hidden
diff --git a/common/boards/configs/libfuzzer.config b/common/boards/configs/libfuzzer.config
new file mode 100644
index 000000000000..df03beac0ec8
--- /dev/null
+++ b/common/boards/configs/libfuzzer.config
@@ -0,0 +1,14 @@
+CONFIG_BOOTM_FITIMAGE=y
+CONFIG_PRINTF_FULL=y
+CONFIG_BUG_ON_DATA_CORRUPTION=y
+CONFIG_UBSAN=y
+CONFIG_UBSAN_NO_ALIGNMENT=y
+CONFIG_ASAN=y
+CONFIG_FORTIFY_SOURCE=y
+CONFIG_HWRNG=y
+CONFIG_HWRNG_DEV_RANDOM=y
+CONFIG_STACKPROTECTOR_STRONG=y
+CONFIG_TEST=y
+CONFIG_FUZZ=y
+CONFIG_FUZZ_EXTERNAL=y
+CONFIG_CMD_FUZZ=y
--
2.39.5
More information about the barebox
mailing list