Coverage-guided differential fuzzing for GNU coreutils versus uutils/coreutils powered by libAFL. The harness repeatedly feeds the same stdin into both implementations and preserves any behavioural differences for later triage.
scripts/run_libafl.sh— convenience wrapper that invokes the Rust harness withcargo run.fuzzers/libafl-diff/— libAFL-based differential fuzzer; run it directly or via the script.instrumented-coreutils/— checkout of the uutils project that you build with coverage instrumentation (ignored by git so you can clone your own copy).queue-*— per-target libAFL queues keeping the evolving corpus.artifacts-*— saved repro bundles for divergences (stdin, stdout/stderr pairs, metadata).reports/— human-readable write-ups once a divergence is confirmed (see theuu-nlexample).logs/— optional run logs (ignored by VCS).
- Rust toolchain (stable ≥ 1.70 is fine; nightly also works).
clang+lldso the AFL runtime links cleanly (apt install clang lldon Debian/Ubuntu).cargo-afl(cargo install cargo-afl) or another compiler wrapper that emits LLVM coverage instrumentation.- A GNU coreutils installation (e.g.
/usr/bin) to act as the reference implementation.
Clone uutils and build the utilities you want to fuzz with AFL instrumentation enabled:
git clone https://github.com/uutils/coreutils instrumented-coreutils
env RUSTFLAGS='-C linker=clang -C link-arg=-fuse-ld=lld \
-C link-arg=-Wl,--no-as-needed -C link-arg=-ldl' \
PROG_PREFIX=uu- \
cargo afl build --release \
--manifest-path instrumented-coreutils/Cargo.toml \
-p uu_nlThe resulting binary lives at instrumented-coreutils/target/release/uu-nl. Repeat the final cargo afl build invocation with a different package (-p uu_sort, -p uu_base64, …) for each extra utility you want to cover.
Point the harness at matching GNU and uutils binaries and let libAFL drive the inputs:
./scripts/run_libafl.sh \
--util nl \
--uutils-path "$(pwd)/instrumented-coreutils/target/release" \
--gnu-path /usr/bin \
--queue queue-libafl-nl \
--artifacts artifacts-libafl-nl \
--timeout-sec 3 \
--max-iterations 0Key options (run ./scripts/run_libafl.sh --help for the full list):
--util— utility name without theuu-prefix; defaults tocat.--uutils-path/--gnu-path— directories that contain the instrumented uutils binaries and the reference GNU binaries respectively.--queue/--artifacts— output directories; you can run multiple fuzzers in parallel by giving each its own pair.--arg— repeatable flag to pin baseline arguments that should be present on every execution (e.g.--arg --number).--timeout-secand--max-iterations— per-execution timeout and an optional iteration cap (set to0for “run forever”).
Tips:
- Pin runs to dedicated cores when you fan out multiple harnesses, e.g.
taskset -c 80-95 ./scripts/run_libafl.sh …. - Seed
queue-*with interesting inputs before launching to bias exploration; the harness will create the directory if it doesn’t exist. - Keep an eye on
logs/(if you redirect output there) to see throughput, unique crashes, and other libAFL stats.
queue-*contains the evolving corpus of interesting inputs that survive minimisation.artifacts-*/<util>/case-*/holds reproducer bundles with stdin, stdout/stderr for both binaries, exit code summaries, and metadata (including a stable hash you can reference in reports).- Once you confirm a behavioural gap, drop a Markdown write-up under
reports/mirroring the format inreports/uu-nl-multiple-b-flags.md.
The provided Dockerfile installs Rust, clang, and related tooling on top of Ubuntu 24.04. Build it if you want an isolated environment:
docker build -t fuzz-coreutils .
docker run --rm -it -v "$PWD":/work fuzz-coreutilsInside the container you still need to clone uutils and build your instrumented binaries as shown above.
- Heavy fuzzing runs produce a lot of bundles—prune
artifacts-*andqueue-*periodically to keep disk usage in check. - Keep the uutils checkout fresh (
git pull) to fuzz new releases. - When filing upstream issues, include the metadata and repro files from the relevant
artifacts-*directory so maintainers can verify the discrepancy.
Happy hunting!