Il fuzzing di Rust è supportato tramite la crate libfuzzer-sys
, che fornisce
binding al motore di fuzzing libFuzzer di LLVM. Per ulteriori informazioni, consulta il repository libfuzzer-sys e la pagina del progetto LLVM libFuzzer.
Il modulo rust_fuzz
produce un binario fuzzer che inizia il fuzzing quando viene
eseguito (in modo simile ai moduli cc_fuzz
). Poiché il fuzzer utilizza il motore di fuzzing libFuzzer
, può accettare una serie di argomenti per controllare il fuzzing. Questi sono
elencati nella documentazione di libFuzzer.
I moduli rust_fuzz
sono un'estensione dei moduli rust_binary
e, in quanto tali, condividono
le stesse proprietà e considerazioni. Inoltre, implementano molte delle stesse proprietà e funzionalità dei moduli cc_fuzz
.
Durante la creazione dei moduli rust_fuzz
, viene generato il flag --cfg fuzzing
, che può essere utilizzato per supportare la compilazione condizionale del codice della libreria per migliorare il fuzzing.
Scrivere un fuzzer Rust di base
Puoi definire un modulo di fuzzing 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 di fuzzing chiamato dal motore libFuzzer
. L'argomento data
è
una sequenza di byte fornita dal motore libFuzzer
da manipolare come input
per il fuzzing della funzione di destinazione.
In questo esempio di fuzzer, viene controllata solo la lunghezza dei dati per determinare se chiamare la funzione heap_oob
, la cui chiamata comporta una lettura fuori dai limiti. libFuzzer
è un fuzzer guidato dalla copertura, quindi converge rapidamente sulla
lunghezza problematica, in quanto determina che i primi 326 B di dati non
comportano nuovi percorsi di esecuzione.
Trova questo esempio in-tree all'indirizzo tools/security/fuzzing/example_rust_fuzzer/.
Per visualizzare un esempio leggermente più complesso di un altro fuzzer (che esegue il fuzzing di una dipendenza rustlib
in-tree), consulta legacy_blob_fuzzer.
Per indicazioni su come scrivere fuzzing di Rust che tengano conto della struttura, consulta il libro Rust Fuzz, la documentazione ufficiale del progetto Rust Fuzz.