
From: Simon Glass <sjg@chromium.org> Add some docs for using fuzzing with U-Boot, including building, running tests, and adding new tests. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <sjg@chromium.org> --- doc/build/fuzz.rst | 219 ++++++++++++++++++++++++++++++++++++++++++++ doc/build/index.rst | 1 + 2 files changed, 220 insertions(+) create mode 100644 doc/build/fuzz.rst diff --git a/doc/build/fuzz.rst b/doc/build/fuzz.rst new file mode 100644 index 00000000000..4c05df4dc21 --- /dev/null +++ b/doc/build/fuzz.rst @@ -0,0 +1,219 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Building U-Boot with Fuzzing Support +===================================== + +U-Boot supports fuzzing through libFuzzer when built for the sandbox +architecture. Fuzzing helps identify security vulnerabilities and crashes by +testing with randomly generated inputs. + +Prerequisites +------------- + +The following tools are required: + +* Clang compiler with fuzzing support +* libstdc++ development libraries + +On Ubuntu/Debian systems, install the required packages:: + + sudo apt install clang libstdc++-dev + +Building with Fuzzing +--------------------- + +The recommended approach is to use buildman, which handles the configuration +automatically: + +1. Build with buildman (recommended):: + + buildman --bo sandbox -a FUZZ=y -O clang -L -o /tmp/fuzz -w + +The buildman options: + +* ``--booard sandbox`` - Build for sandbox board only +* ``-a FUZZ=y`` - Enable fuzzing support via CONFIG_FUZZ=y +* ``-O clang`` - Use Clang compiler (required for fuzzing) +* ``-L`` - Disable LTO to avoid sanitizer coverage linker issues +* ``-o /tmp/fuzz`` - Output directory +* ``-w`` - Use the output directory as the work directory + +Alternative: Manual build +~~~~~~~~~~~~~~~~~~~~~~~~~ + +To build manually with make: + +1. Configure the build with fuzzing enabled:: + + make HOSTCC=clang CC=clang O=/tmp/fuzz LTO_ENABLE= sandbox_defconfig + scripts/config --file /tmp/fuzz/.config --enable FUZZ + +2. Build the fuzzing-enabled binary:: + + make HOSTCC=clang CC=clang O=/tmp/fuzz LTO_ENABLE= -j$(nproc) + +Build Output +------------ + +The fuzzing build produces: + +* ``u-boot`` - Main fuzzing binary with AddressSanitizer and fuzzer + instrumentation +* Significantly larger binary size due to instrumentation (typically 40-50MB) +* Debug symbols included for better crash analysis + +Fuzzing Architecture +-------------------- + +The U-Boot fuzzing implementation consists of: + +* **Fuzzing Engine**: Sandbox-specific driver that interfaces with libFuzzer +* **Threading Model**: Separate threads for fuzzing harness and U-Boot + execution +* **Input Handling**: ``LLVMFuzzerTestOneInput()`` entry point processes + fuzz inputs +* **Command Fuzzing**: Tests U-Boot commands with generated inputs via + ``fuzz`` command + +Key source files: + +* ``arch/sandbox/cpu/fuzz.c`` - Main fuzzing implementation +* ``drivers/fuzz/`` - Fuzzing engine drivers +* ``test/fuzz/`` - Fuzzing test cases +* ``include/fuzzing_engine.h`` - Fuzzing engine interface + +Running Fuzz Tests +------------------ + +To run fuzzing tests, set the test name via environment variable and run the +fuzzing binary from the build directory: + +1. Change to the build directory:: + + cd /tmp/fuzz + +2. Set the fuzz test to run:: + + export UBOOT_SB_FUZZ_TEST=fuzz_vring + +3. Run the fuzzer:: + + ./u-boot + +The fuzzer will start libFuzzer with coverage-guided input generation. You +should see output similar to:: + + INFO: Running with entropic power schedule (0xFF, 100). + INFO: Seed: 1626867009 + INFO: Loaded 1 modules (104150 inline 8-bit counters): ... + #2 INITED cov: 28 ft: 29 corp: 1/1b exec/s: 0 rss: 318Mb + #4 NEW cov: 29 ft: 30 corp: 2/3b lim: 4 exec/s: 0 rss: 319Mb + +Available fuzz tests include: + +* ``fuzz_vring`` - Tests VirtIO ring buffer handling + +To stop fuzzing, use Ctrl+C. The fuzzer will automatically save any crash- +inducing inputs for later analysis. + +Understanding Fuzzer Output +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The fuzzer output shows: + +* ``cov: N`` - Number of code coverage points reached +* ``ft: N`` - Number of features discovered +* ``corp: N/Mb`` - Corpus size (number of test cases / total bytes) +* ``exec/s: N`` - Executions per second (performance metric) +* ``rss: NMb`` - Memory usage + +Error messages from the target code (like VirtIO "out of range" errors) are +expected and indicate the fuzzer is finding edge cases. + +Adding New Fuzz Tests +--------------------- + +To create a new fuzz test, follow these steps: + +1. **Create the test file** in ``test/fuzz/`` directory:: + + /* SPDX-License-Identifier: GPL-2.0+ */ + #include <test/fuzz.h> + + static int fuzz_my_component(const uint8_t *data, size_t size) + { + /* Your fuzzing logic here */ + if (size < 4) + return 0; /* Not enough data */ + + /* Test your component with fuzzed data */ + my_component_function(data, size); + + return 0; + } + FUZZ_TEST(fuzz_my_component, 0); + +2. **Add to Makefile** in ``test/fuzz/Makefile``:: + + obj-$(CONFIG_MY_COMPONENT) += my_component.o + + Or for tests that should always be included:: + + obj-y += my_component.o + +3. **Test the new fuzzer**:: + + export UBOOT_SB_FUZZ_TEST=fuzz_my_component + ./u-boot + +**Best practices for fuzz tests:** + +* **Input validation**: Check minimum data size requirements +* **Error handling**: Handle invalid inputs gracefully, don't panic +* **Resource cleanup**: Free any allocated resources +* **Focused testing**: Target specific functions or code paths +* **Deterministic**: Same input should produce same behavior + +**Example patterns:** + +* Parse structured data (protocols, file formats) +* Test buffer handling with varying sizes +* Exercise error paths with malformed inputs +* Stress test with boundary conditions + +Troubleshooting +--------------- + +**Linker errors about missing libstdc++**: + Install libstdc++ development libraries as shown in Prerequisites. + +**Sanitizer coverage linker errors**: + Ensure LTO is disabled with ``LTO_ENABLE=`` in the make command. + +**Build fails with GCC**: + Fuzzing requires Clang. Ensure both CC and HOSTCC are set to clang. + +**Fuzzer exits with "fdtdec_setup() failed"**: + Run the fuzzer from the build directory where u-boot.dtb is located. + The sandbox requires access to its device tree file. + +Security Considerations +----------------------- + +Fuzzing builds include: + +* **AddressSanitizer**: Detects buffer overflows, use-after-free, and other + memory errors +* **Fuzzer Coverage**: Instruments code for coverage-guided fuzzing +* **Debug Information**: Retained for crash analysis and debugging + +These features significantly increase binary size and runtime overhead, making +fuzzing builds unsuitable for production use. + +Further Reading +--------------- + +* :doc:`/arch/sandbox/sandbox` - General sandbox architecture documentation +* libFuzzer documentation: https://llvm.org/docs/LibFuzzer.html +* AddressSanitizer documentation: + https://clang.llvm.org/docs/AddressSanitizer.html diff --git a/doc/build/index.rst b/doc/build/index.rst index 7a4507b5746..bd380a5e6c2 100644 --- a/doc/build/index.rst +++ b/doc/build/index.rst @@ -9,6 +9,7 @@ Build U-Boot source gcc clang + fuzz reproducible docker tools -- 2.43.0