
Un fuzzer orientato alla GPU e guidato dalla copertura del codice per applicazioni CUDA in spazio utente.
Questo repository contiene gli artefatti per cuFuzz, un fuzzer orientato alla GPU e guidato dalla copertura per applicazioni CUDA in spazio utente. cuFuzz combina la raccolta della copertura lato host e lato device con la sanitizzazione per scoprire efficacemente bug nei programmi CUDA.

cufuzz-artifacts/
├── src/ # Core cuFuzz components
│ ├── cufuzz_cov_nvbit/ # NVBit-based device-side coverage collection tool
│ └── cufuzz_sand/ # Sanitizer wrappers for SAND integration
├── targets/ # Example fuzzing targets
│ └── sampleApp/ # Simple CUDA app with intentional bug for testing
├── scripts/ # Evaluation and analysis scripts
├── Tools/ # External dependencies
│ ├── AFLplusplus/ # AFL++ fuzzer (git submodule)
│ └── AFLplusplus.patch # cuFuzz patches for AFL++
├── third-party-licenses/ # Third-party license files
│ ├── LICENSE_from_aflplusplus # AFL++ Apache 2.0 license
│ └── LICENSE_from_nvbit # NVBit NVIDIA EULA
├── images/ # Documentation images
├── build.sh # Automated build script
├── verify_build.sh # Quick verification test
├── Dockerfile # Docker container definition
├── LICENSE # Apache License 2.0
└── CONTRIBUTING.md # Contribution guidelines and DCO
cuFuzz è stato testato sulla seguente configurazione hardware:
| Componente | Specifica |
|---|---|
| GPU | NVIDIA A40 (48GB VRAM, Compute Capability 8.6) |
| CPU | Intel Xeon Platinum 8362 (64 core, 2 thread/core) |
| Memoria | 120GB+ di RAM consigliati |
| Archiviazione | 50GB+ di spazio libero per l'immagine Docker e gli output del fuzzing |
Altre GPU: cuFuzz dovrebbe funzionare su altre GPU NVIDIA con Compute Capability ≥ 7.0. Regola la variabile d'ambiente GPU_ARCH di conseguenza (vedi Configurazione dell'architettura GPU).
| Componente | Versione |
|---|---|
| Ubuntu | 22.04 LTS |
| NVIDIA Driver | 570.144 o compatibile |
| CUDA Toolkit | 12.9 |
| Docker | 20.10+ (consigliato) |
| nvidia-container-toolkit | Necessario per il supporto del flag --gpus |
| clang | 14 |
Il modo più rapido per provare cuFuzz è utilizzare un container Docker. Il nostro Dockerfile utilizza l'immagine di sviluppo ufficiale NVIDIA CUDA 12.9.
tar -xzvf cufuzz-artifacts.tar.gz
cd cufuzz-artifacts
# Clone AFL++ (required dependency)
git clone https://github.com/AFLplusplus/AFLplusplus.git Tools/AFLplusplus
cd Tools/AFLplusplus
git checkout 9cac7ced05eb9f36c1d0b02ad594b3b09cd3938b
cd ../..
Crea l'immagine Docker specificando la tua architettura GPU:
sudo docker build --build-arg GPU_ARCH=<your_arch> -t cufuzz .
Riferimento delle architetture GPU:
| Famiglia GPU | Architettura | Esempi |
|---|---|---|
| Ampere (Data Center) | sm_80 | A100 |
| Ampere (Consumer/Pro) | sm_86 | A40, RTX 3090, RTX 3060 |
| Hopper | sm_90 | H100 |
| Ada Lovelace | sm_89 | RTX 4090, L40 |
| Turing | sm_75 | RTX 2080, T4 |
Per un elenco completo, vedi: https://developer.nvidia.com/cuda-gpus
Esempio per A40/RTX 3090:
sudo docker build --build-arg GPU_ARCH=sm_86 -t cufuzz .
Nota: Questo passaggio potrebbe richiedere diversi minuti a seconda della tua macchina e della connessione di rete.
sudo docker run --rm --gpus all -it -v /:/my_workspace cufuzz bash
Una volta che il container Docker è in esecuzione, verifica la build:
root@container:~/cufuzz# ./verify_build.sh
Installa le dipendenze richieste su Ubuntu 22.04:
apt-get update && apt-get install -y build-essential python3-dev automake cmake git flex \
bison libglib2.0-dev libpixman-1-dev python3-setuptools cargo libgtk-3-dev lld llvm llvm-dev \
clang ninja-build cpio libcapstone-dev wget curl python3-pip vim less libxxhash-dev bc zlib1g-dev
Imposta la variabile d'ambiente GPU_ARCH per la tua GPU (vedi la tabella delle architetture sopra):
export GPU_ARCH=sm_86 # Change to match your GPU
cd Tools/AFLplusplus
patch -N -p1 < ../AFLplusplus.patch
export CXX=/usr/bin/clang++-14
export CC=/usr/bin/clang-14
make -j8 &> build.log
Scarica NVBit versione 1.7.5:
mkdir -p Tools/NVBit
wget https://github.com/NVlabs/NVBit/releases/download/v1.7.5/nvbit-Linux-x86_64-1.7.5.tar.bz2
tar -xvf nvbit-Linux-x86_64-1.7.5.tar.bz2
mv nvbit_release_x86_64/* Tools/NVBit/
rm -rf nvbit_release_x86_64 nvbit-Linux-x86_64-1.7.5.tar.bz2
Compila il nostro strumento di copertura NVBit:
cd src/cufuzz_cov_nvbit/
export GPU_ARCH=sm_86 # Adjust for your GPU
ARCH=$GPU_ARCH make
cd src/cufuzz_sand
AFL_SAN_NO_INST=1 ../../Tools/AFLplusplus/afl-clang-fast -O2 wrapper_san.c -o wrapper_memcheck.out
AFL_SAN_NO_INST=1 ../../Tools/AFLplusplus/afl-clang-fast -DSAN_MODE_INIT -O2 wrapper_san.c -o wrapper_initcheck.out
AFL_SAN_NO_INST=1 ../../Tools/AFLplusplus/afl-clang-fast -DSAN_MODE_RACE -O2 wrapper_san.c -o wrapper_racecheck.out
AFL_SAN_NO_INST=1 ../../Tools/AFLplusplus/afl-clang-fast -DSAN_MODE_ASAN -O2 wrapper_san.c -o wrapper_asan.out
Dopo aver compilato cuFuzz, avvia il fuzzing usando il seguente comando:
CUFUZZ_MAP_SIZE=65536 AFL_SKIP_CPUFREQ=1 AFL_PRELOAD=/PATH/TO/cufuzz_cov.so \
./Tools/AFLplusplus/afl-fuzz -x sample.dict -i input_samples/ -o output_dir/ \
-t 1000000 ./cuda_app.out @@
| Variabile | Descrizione | Esempio |
|---|---|---|
AFL_SKIP_CPUFREQ | Salta il controllo della policy di scaling della CPU | AFL_SKIP_CPUFREQ=1 |
AFL_PRELOAD | Percorso dello strumento di copertura NVBit | AFL_PRELOAD=/path/to/cufuzz_cov.so |
| Variabile | Descrizione | Esempio |
|---|---|---|
CUFUZZ_MAP_SIZE | Dimensione della mappa di copertura in byte | CUFUZZ_MAP_SIZE=65536 |
COV_PERSISTENT | Abilita il supporto alla modalità persistente di AFL (0=no, 1=sì) | COV_PERSISTENT=1 |
GPU_ARCH | Architettura GPU di destinazione per le build | GPU_ARCH=sm_86 |
| Variabile | Descrizione | Esempio |
|---|---|---|
ORIGINAL_APP | Percorso dell'applicazione vanilla (non strumentata) | ORIGINAL_APP=./cuda_app |
SANITIZER_PATH | Percorso del binario compute-sanitizer | SANITIZER_PATH=/usr/local/cuda/bin/compute-sanitizer |
SANITIZER_ARG | Argomenti per il sanitizer memcheck | SANITIZER_ARG="--tool=memcheck --error-exitcode 99" |
SANITIZER_ARG_RACE | Argomenti per il sanitizer racecheck | SANITIZER_ARG_RACE="--tool=racecheck --error-exitcode 99" |
SANITIZER_ARG_INIT | Argomenti per il sanitizer initcheck | SANITIZER_ARG_INIT="--tool=initcheck --error-exitcode 99" |
La variabile AFL_SAN_ABSTRACTION controlla quali input vengono inviati ai sanitizer:
| Valore | Descrizione | Sensibilità | Prestazioni |
|---|---|---|---|
all_trace | Invia tutti gli input ai sanitizer | Massima | Più lenta |
simplify_trace | Invia gli input con percorsi di esecuzione unici | Alta | Bilanciata |
unique_trace | Invia gli input con firme di copertura uniche | Media | Più veloce |
coverage_increase | Invia solo gli input che causano un aumento della copertura | Minima | Più rapida |
Consigliato: AFL_SAN_ABSTRACTION=simplify_trace (predefinito)
In questa modalità, cuFuzz usa la copertura lato device e esegue compute sanitizer su un sottoinsieme di input (input con tracce uniche). Questa modalità sfrutta la funzionalità SAND di AFL++ per disaccoppiare la raccolta della copertura dalla sanitizzazione.
cd src/cufuzz_sand
# Build sanitizer wrappers
AFL_SAN_NO_INST=1 ../../Tools/AFLplusplus/afl-clang-fast -O2 wrapper_san.c -o wrapper_memcheck.out
AFL_SAN_NO_INST=1 ../../Tools/AFLplusplus/afl-clang-fast -DSAN_MODE_INIT -O2 wrapper_san.c -o wrapper_initcheck.out
AFL_SAN_NO_INST=1 ../../Tools/AFLplusplus/afl-clang-fast -DSAN_MODE_RACE -O2 wrapper_san.c -o wrapper_racecheck.out
AFL_SAN_NO_INST=1 ../../Tools/AFLplusplus/afl-clang-fast -DSAN_MODE_ASAN -O2 wrapper_san.c -o wrapper_asan.out
cd ../../targets/sampleApp/
export PATH=/usr/local/cuda/bin/:$PATH
export GPU_ARCH=sm_86 # Adjust for your GPU
# Build vanilla version (for sanitizer)
nvcc sampleApp.cu -I/usr/local/cuda/include/ -O2 --ptxas-options "-v" \
--gpu-architecture=$GPU_ARCH -o sampleApp-vanilla.out
# Build instrumented version (for fuzzing)
nvcc sampleApp.cu -I/usr/local/cuda/include/ -O2 --ptxas-options "-v" \
--gpu-architecture=$GPU_ARCH --compiler-bindir ../../Tools/AFLplusplus/afl-clang-fast++ \
-o sampleApp.out
# Run cuFuzz
ORIGINAL_APP=./sampleApp-vanilla.out \
SANITIZER_PATH=/usr/local/cuda/bin/compute-sanitizer \
SANITIZER_ARG="--tool=memcheck --report-api-errors=no --error-exitcode 99" \
SANITIZER_ARG_RACE="--tool=racecheck --report-api-errors=no --error-exitcode 99" \
SANITIZER_ARG_INIT="--tool=initcheck --report-api-errors=no --error-exitcode 99" \
CUFUZZ_MAP_SIZE=65536 \
AFL_SKIP_CPUFREQ=1 \
AFL_PRELOAD=../../src/cufuzz_cov_nvbit/cufuzz_cov.so \
../../Tools/AFLplusplus/afl-fuzz -x sample.dict -i in/ -o out/ \
-w ../../src/cufuzz_sand/wrapper_memcheck.out \
-w ../../src/cufuzz_sand/wrapper_racecheck.out \
-w ../../src/cufuzz_sand/wrapper_initcheck.out \
-t 1000000 ./sampleApp.out @@

Esecuzione senza sanitizer (non consigliata): rimuovi gli argomenti -w e le variabili SANITIZER_*.
Esecuzione senza copertura lato device (opzionale): rimuovi AFL_PRELOAD=...cufuzz_cov.so.
In questa modalità, cuFuzz sfrutta la modalità persistente di AFL++, in cui più input vengono testati all'interno di un singolo processo. Questo migliora significativamente il throughput ammortizzando l'overhead di inizializzazione di CUDA.
La modalità persistente richiede modifiche al codice sorgente dell'harness di fuzzing. Consulta la documentazione sulla modalità persistente di AFL++ per i dettagli.
cd targets/sampleApp/
export PATH=/usr/local/cuda/bin/:$PATH
export GPU_ARCH=sm_86 # Adjust for your GPU
# Build persistent mode binary
nvcc sampleApp_persistent.cu -I/usr/local/cuda/include/ -O2 --ptxas-options "-v" \
--gpu-architecture=$GPU_ARCH --compiler-bindir ../../Tools/AFLplusplus/afl-clang-fast++ \
-o sampleApp_persistent.out
# Run cuFuzz in persistent mode
COV_PERSISTENT=1 \
CUFUZZ_MAP_SIZE=65536 \
AFL_SKIP_CPUFREQ=1 \
AFL_PRELOAD=../../src/cufuzz_cov_nvbit/cufuzz_cov.so \
./../../Tools/AFLplusplus/afl-fuzz -x sample.dict -i in/ -o out/ \
-t 1000000 ./sampleApp_persistent.out @@

La modalità persistente supporta anche le opzioni dei sanitizer usando: src/cufuzz_sand/wrapper_persistent_san.c
nvidia-smi funzioniGPU_ARCH in base alla compute capability della tua GPUAccogliamo con piacere i contributi! Consulta CONTRIBUTING.md per le linee guida su come contribuire, tra cui:
Se utilizzi cuFuzz nella tua ricerca, ti preghiamo di citare il nostro articolo OOPSLA 2026:
@article{cufuzz2026,
title={Hunting CUDA Bugs at Scale with cuFuzz},
author={Mohamed Tarek Ibn Ziad and Christos Kozyrakis},
journal={Proceedings of the ACM on Programming Languages},
volume={10},
number={OOPSLA1},
article={123},
month={4},
year={2026},
doi={10.1145/3798231}
}
Questo progetto è concesso in licenza secondo i termini della Apache License 2.0 - consulta il file LICENSE per i dettagli.
Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Questo progetto utilizza i seguenti componenti di terze parti:
| Componente | Licenza | File di licenza |
|---|---|---|
| AFL++ | Apache License 2.0 | third-party-licenses/LICENSE_from_aflplusplus |
| NVBit | NVIDIA EULA | third-party-licenses/LICENSE_from_nvbit |