Fuzz-Module

Rust-Fuzzing wird über den libfuzzer-sys-Crate unterstützt, der Bindungen zur Fuzzing-Engine libFuzzer von LLVM bereitstellt. Weitere Informationen finden Sie im Repository libfuzzer-sys und auf der LLVM libFuzzer-Projektseite.

Das rust_fuzz-Modul generiert einen Fuzzer-Binärcode, der beim Ausführen mit dem Fuzzing beginnt (ähnlich wie bei cc_fuzz-Modulen). Da der Fuzzer die libFuzzer-Fuzzing-Engine nutzt, kann es eine Reihe von Argumenten erfordern, um das Fuzzing zu steuern. Diese werden in der libFuzzer-Dokumentation aufgeführt.

rust_fuzz-Module sind eine Erweiterung von rust_binary-Modulen und haben daher dieselben Eigenschaften und Überlegungen. Außerdem werden viele derselben Properties und Funktionen wie in den cc_fuzz-Modulen implementiert.

Beim Erstellen von rust_fuzz-Modulen wird das Flag --cfg fuzzing ausgegeben, das zur Unterstützung der bedingten Kompilierung von Bibliothekscode zur Verbesserung des Fuzzing verwendet werden kann.

Einen einfachen Rust-Fuzzer schreiben

Sie können ein Fuzz-Modul in einer Android.bp-Builddatei mit diesem Code definieren:

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

Die Datei fuzzer.rs enthält einen einfachen 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();
    }
});

Hier definiert fuzz_target!(|data: &[u8]| { /* fuzz using data here */ }); den Fuzz-Ziel-Einstiegspunkt, der von der libFuzzer-Engine aufgerufen wird. Das data-Argument ist eine Bytefolge, die von der libFuzzer-Engine bereitgestellt wird und als Eingabe manipuliert werden kann, um die Zielfunktion zu fuzzen.

In diesem Beispiel-Fuzzer wird nur die Länge der Daten geprüft, um zu ermitteln, ob die Funktion heap_oob aufgerufen werden soll, deren Aufruf zu einem Lesefehler führt. libFuzzer ist ein abdeckungsbasierter Fuzzer, der schnell auf die problematische Länge konvergiert, da er feststellt, dass die ersten 326 B Daten nicht zu neuen Ausführungspfaden führen.

Dieses Beispiel finden Sie im Verzeichnisbaum unter tools/security/fuzzing/example_rust_fuzzer/. Ein etwas komplexeres Beispiel für einen anderen Fuzzer (der eine rustlib-Abhängigkeit in einem Verzeichnis fuzzt) finden Sie unter legacy_blob_fuzzer.

Eine Anleitung zum Erstellen struktursensitiver Rust-Fuzzer finden Sie im Rust Fuzz-Buch, der offiziellen Dokumentation für das Rust Fuzz-Projekt.