
Un fuzzer guiado por cobertura orientado a GPU para aplicaciones CUDA de espacio de usuario.
Este repositorio contiene los artefactos de cuFuzz, un fuzzer guiado por cobertura orientado a GPU para aplicaciones CUDA en espacio de usuario. cuFuzz combina la recopilación de cobertura en el host y en el dispositivo con sanitización para descubrir de forma eficaz errores en programas 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 fue probado con la siguiente configuración de hardware:
| Componente | Especificación |
|---|---|
| GPU | NVIDIA A40 (48 GB de VRAM, Compute Capability 8.6) |
Otras GPU: cuFuzz debería funcionar en otras GPU NVIDIA con Compute Capability ≥ 7.0. Ajusta la variable de entorno GPU_ARCH en consecuencia (consulta Configuración de la Arquitectura de GPU).
La forma más rápida de probar cuFuzz es usar un contenedor de Docker. Nuestro Dockerfile utiliza la imagen oficial de desarrollo 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 ../..
Construye la imagen Docker, especificando la arquitectura de tu GPU:
sudo docker build --build-arg GPU_ARCH=<your_arch> -t cufuzz .
Referencia de arquitectura de GPU:
Para ver la lista completa, consulta: https://developer.nvidia.com/cuda-gpus
Ejemplo para A40/RTX 3090:
sudo docker build --build-arg GPU_ARCH=sm_86 -t cufuzz .
Nota: Este paso puede tardar varios minutos dependiendo de tu máquina y conexión de red.
sudo docker run --rm --gpus all -it -v /:/my_workspace cufuzz bash
Una vez que el contenedor Docker esté en ejecución, verifica la compilación:
root@container:~/cufuzz# ./verify_build.sh
Instala las dependencias requeridas en 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
Configura la variable de entorno GPU_ARCH para tu GPU (consulta la tabla de arquitecturas anterior):
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
Descarga la versión 1.7.5 de NVBit:
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 nuestra herramienta de cobertura 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
Después de compilar cuFuzz, invoca el fuzzing con el siguiente 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 @@
| Variable | Descripción | Ejemplo |
|---|---|---|
AFL_SKIP_CPUFREQ | Omite la comprobación de la política de escalado de CPU | AFL_SKIP_CPUFREQ=1 |
AFL_PRELOAD | Ruta a la herramienta de cobertura NVBit | AFL_PRELOAD=/path/to/cufuzz_cov.so |
La variable AFL_SAN_ABSTRACTION controla qué entradas se envían a los sanitizadores:
Recomendado: AFL_SAN_ABSTRACTION=simplify_trace (por defecto)
En este modo, cuFuzz utiliza la cobertura del lado del dispositivo y ejecuta compute sanitizer en un subconjunto de entradas (entradas con trazas únicas). Este modo aprovecha la funcionalidad SAND de AFL++ para desacoplar la recopilación de cobertura de la sanitización.
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 @@

Ejecutar sin sanitizadores (no recomendado): Elimina los argumentos -w y las variables SANITIZER_*.
Ejecutar sin cobertura del lado del dispositivo (opcional): Elimina AFL_PRELOAD=...cufuzz_cov.so.
En este modo, cuFuzz aprovecha el modo persistente de AFL++, donde se prueban múltiples entradas dentro de un solo proceso. Esto mejora significativamente el rendimiento al amortizar la sobrecarga de inicialización de CUDA.
El modo persistente requiere modificaciones en el código fuente del harness de fuzzing. Consulta la documentación del modo persistente de AFL++ para más detalles.
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 @@

El modo persistente también soporta opciones de sanitizador usando: src/cufuzz_sand/wrapper_persistent_san.c
nvidia-smi funcioneGPU_ARCH para que coincida con la capacidad de cómputo de tu GPU¡Agradecemos las contribuciones! Consulta CONTRIBUTING.md para conocer las pautas sobre cómo contribuir, incluyendo:
Si utilizas cuFuzz en tu investigación, por favor cita nuestro artículo de 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}
}
Este proyecto está licenciado bajo la Apache License 2.0 - consulta el archivo LICENSE para más detalles.
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
Este proyecto utiliza los siguientes componentes de terceros:
| Componente | Licencia | Archivo de Licencia |
|---|---|---|
| AFL++ | Apache License 2.0 | third-party-licenses/LICENSE_from_aflplusplus |
| NVBit | NVIDIA EULA | third-party-licenses/LICENSE_from_nvbit |
| Intel Xeon Platinum 8362 (64 núcleos, 2 hilos/núcleo) |
| Memoria | 120 GB+ de RAM recomendados |
| Almacenamiento | 50 GB+ de espacio libre para la imagen Docker y las salidas del fuzzing |
| Componente | Versión |
|---|
| Ubuntu | 22.04 LTS |
| NVIDIA Driver | 570.144 o compatible |
| CUDA Toolkit | 12.9 |
| Docker | 20.10+ (recomendado) |
| nvidia-container-toolkit | Necesario para el soporte del flag --gpus |
| clang | 14 |
| Familia de GPU | Arquitectura | Ejemplos |
|---|
| Ampere (Centro de datos) | sm_80 | A100 |
| Ampere (Consumo/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 |
| Variable | Descripción | Ejemplo |
|---|
CUFUZZ_MAP_SIZE | Tamaño del mapa de cobertura en bytes | CUFUZZ_MAP_SIZE=65536 |
COV_PERSISTENT | Habilita el soporte del modo persistente de AFL (0=no, 1=sí) | COV_PERSISTENT=1 |
GPU_ARCH | Arquitectura de GPU objetivo para las compilaciones | GPU_ARCH=sm_86 |
| Variable | Descripción | Ejemplo |
|---|
ORIGINAL_APP | Ruta a la aplicación vanilla (sin instrumentar) | ORIGINAL_APP=./cuda_app |
SANITIZER_PATH | Ruta al binario de compute-sanitizer | SANITIZER_PATH=/usr/local/cuda/bin/compute-sanitizer |
SANITIZER_ARG | Argumentos para el sanitizador memcheck | SANITIZER_ARG="--tool=memcheck --error-exitcode 99" |
SANITIZER_ARG_RACE | Argumentos para el sanitizador racecheck | SANITIZER_ARG_RACE="--tool=racecheck --error-exitcode 99" |
SANITIZER_ARG_INIT | Argumentos para el sanitizador initcheck | SANITIZER_ARG_INIT="--tool=initcheck --error-exitcode 99" |
| Valor | Descripción | Sensibilidad | Rendimiento |
|---|
all_trace | Enviar todas las entradas a los sanitizadores | Máxima | El más lento |
simplify_trace | Enviar entradas con rutas de ejecución únicas | Alta | Equilibrado |
unique_trace | Enviar entradas con firmas de cobertura únicas | Media | Más rápido |
coverage_increase | Enviar solo entradas que causan aumento de cobertura | Baja | El más rápido |