[Concept,01/18] doc: Add fuzzing build documentation

Message ID 20250904130459.848794-2-sjg@u-boot.org
State New
Headers
Series ulib: Introduce building U-Boot as a shared library |

Commit Message

Simon Glass Sept. 4, 2025, 1:04 p.m. UTC
  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
  

Patch

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