Модули фаззинга

Поддержка фаззинга в Rust обеспечивается библиотекой libfuzzer-sys , которая предоставляет привязки к механизму фаззинга libFuzzer от LLVM. Для получения дополнительной информации см. репозиторий libfuzzer-sys , а также страницу проекта libFuzzer в LLVM .

Модуль rust_fuzz создает исполняемый файл фаззера, который начинает фаззинг при запуске (аналогично модулям cc_fuzz ). Поскольку фаззер использует механизм фаззинга libFuzzer , он может принимать ряд аргументов для управления фаззингом. Они перечислены в документации libFuzzer .

Модули rust_fuzz являются расширением модулей rust_binary и, следовательно, обладают теми же свойствами и функциями. Кроме того, они реализуют многие из тех же свойств и функций, что и модули cc_fuzz .

При сборке модулей rust_fuzz генерируется флаг --cfg fuzzing , который можно использовать для поддержки условной компиляции кода библиотеки с целью улучшения фаззинга.

Напишите простой фаззер на Rust.

Модуль фаззинга можно определить в файле сборки Android.bp с помощью следующего кода:

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

Файл fuzzer.rs содержит простой фаззер:

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

Здесь fuzz_target!(|data: &[u8]| { /* fuzz using data here */ }); определяет точку входа для фаззинга, вызываемую механизмом libFuzzer . Аргумент data представляет собой последовательность байтов, предоставляемых механизмом libFuzzer для обработки в качестве входных данных для фаззинга целевой функции.

В этом примере фаззера проверяется только длина данных, чтобы определить, следует ли вызывать функцию heap_oob , вызов которой приводит к выходу за пределы допустимого диапазона чтения. libFuzzer — это фаззер, управляемый покрытием кода, поэтому он быстро сходится к проблемной длине, поскольку определяет, что первые 326 байт данных не приводят к новым путям выполнения.

Этот пример можно найти в репозитории, в папке tools/security/fuzzing/example_rust_fuzzer/ . Более сложный пример другого фаззера (который фаззирует зависимость rustlib ) можно посмотреть в репозитории legacy_blob_fuzzer .

Рекомендации по написанию фаззеров на Rust с учетом структуры данных см. в книге Rust Fuzz , официальной документации проекта Rust Fuzz.