Loading...
.. 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