[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