Módulos Fuzz

Rust fuzzing es compatible a través de la caja libfuzzer-sys , que proporciona enlaces al motor de fuzzing libFuzzer de LLVM. Para obtener más información, consulte el repositorio libfuzzer-sys , así como la página del proyecto LLVM libFuzzer .

El módulo rust_fuzz produce un fuzzer binario que comienza a fuzzear cuando se ejecuta (similar a los módulos cc_fuzz ). Como el fuzzer aprovecha el motor de fuzzing de libFuzzer , puede tomar una serie de argumentos para controlar el fuzzing. Estos se enumeran en la documentación de libFuzzer .

Los módulos rust_fuzz son una extensión de los módulos rust_binary y, como tales, comparten las mismas propiedades y consideraciones. Además, implementan muchas de las mismas propiedades y funciones que los módulos cc_fuzz .

Escribiendo un Rust fuzzer básico

Puede definir un módulo fuzz en un archivo de compilación Android.bp con este código:

rust_fuzz {
    name: "example_rust_fuzzer",
    srcs: ["fuzzer.rs"],

    // Config for running the target on fuzzing infrastructure can be set under
    // fuzz_config. This shares the same properties as cc_fuzz's fuzz_config.
    fuzz_config: {
        fuzz_on_haiku_device: true,
        fuzz_on_haiku_host: false,
    },

    // Path to a corpus of sample inputs, optional. See https://llvm.org/docs/LibFuzzer.html#corpus
    corpus: ["testdata/*"],

    // Path to a dictionary of sample byte sequences, optional. See https://llvm.org/docs/LibFuzzer.html#dictionaries
    dictionary: "example_rust_fuzzer.dict",
}

El archivo fuzzer.rs contiene un fuzzer simple:

fn heap_oob() {
    let xs = vec![0, 1, 2, 3];
    let val = unsafe { *xs.as_ptr().offset(4) };
    println!("Out-of-bounds heap value: {}", val);
}

fuzz_target!(|data: &[u8]| {
    let magic_number = 327;
    if data.len() == magic_number {
        heap_oob();
    }
});

Aquí fuzz_target!(|data: &[u8]| { /* fuzz using data here */ }); define el punto de entrada del objetivo fuzz llamado por el motor libFuzzer . El argumento data es una secuencia de bytes proporcionados por el motor libFuzzer para ser manipulados como entrada para fuzzear la función de destino.

En este fuzzer de ejemplo, solo se comprueba la longitud de los datos para determinar si se debe llamar a la función heap_oob , cuya llamada da como resultado una lectura fuera de los límites. libFuzzer es un fuzzer guiado por cobertura, por lo que converge rápidamente en la longitud problemática al determinar que los primeros 326 B de datos no dan como resultado nuevas rutas de ejecución.

Busque este ejemplo, en el árbol, en tools/security/fuzzing/example_rust_fuzzer/ . Para ver un ejemplo un poco más complejo de otro fuzzer (que rustlib una dependencia de rustlib) en el árbol, consulte legacy_blob_fuzzer .

Para obtener orientación sobre cómo escribir fuzzers de Rust conscientes de la estructura , consulte el libro Rust Fuzz , la documentación oficial del proyecto Rust Fuzz.