Moduli fuzz

Il fuzzing di Rust è supportato tramite il crate libfuzzer-sys , che fornisce collegamenti al motore fuzzing libFuzzer di LLVM. Per ulteriori informazioni, consultare il repository libfuzzer-sys e la pagina del progetto libFuzzer di LLVM .

Il modulo rust_fuzz produce un binario fuzzer che inizia a eseguire il fuzz quando viene eseguito (simile ai moduli cc_fuzz ). Poiché il fuzzer sfrutta il motore di fuzzing libFuzzer , possono essere necessari numerosi argomenti per controllare il fuzzing. Questi sono elencati nella documentazione di libFuzzer .

I moduli rust_fuzz sono un'estensione dei moduli rust_binary e come tali condividono le stesse proprietà e considerazioni. Inoltre, implementano molte delle stesse proprietà e funzionalità dei moduli cc_fuzz .

Quando si creano moduli rust_fuzz , viene emesso il flag --cfg fuzzing che può essere utilizzato per supportare la compilazione condizionale del codice della libreria per migliorare il fuzzing.

Scrivi un fuzzer di Rust di base

Puoi definire un modulo fuzz in un file di build Android.bp con questo codice:

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",
}

Il file fuzzer.rs contiene un semplice fuzzer:

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();
    }
});

Qui fuzz_target!(|data: &[u8]| { /* fuzz using data here */ }); definisce il punto di ingresso fuzz-target chiamato dal motore libFuzzer . L'argomento data è una sequenza di byte fornita dal motore libFuzzer da manipolare come input per fuzz la funzione mirata.

In questo fuzzer di esempio, viene controllata solo la lunghezza dei dati per determinare se chiamare la funzione heap_oob , la cui chiamata risulta in una lettura fuori dai limiti. libFuzzer è un fuzzer guidato dalla copertura, quindi converge rapidamente sulla lunghezza problematica poiché determina che i primi 326 B di dati non danno luogo a nuovi percorsi di esecuzione.

Individua questo esempio, nell'albero, in tools/security/fuzzing/example_rust_fuzzer/ . Per visualizzare un esempio leggermente più complesso di un altro fuzzer (che sfuma una dipendenza rustlib ) nell'albero, vedere legacy_blob_fuzzer .

Per indicazioni su come scrivere fuzzer Rust sensibili alla struttura , consultare il libro Rust Fuzz , la documentazione ufficiale del progetto Rust Fuzz.