ファズモジュール

さびファジングは、LLVMのlibFuzzerファジングエンジンへのバインディングを提供するlibfuzzer-sysクレートを介してサポートされます。詳細については、 libfuzzer-sysリポジトリおよびLLVMlibFuzzerプロジェクトページを参照してください。

rust_fuzzモジュールは、実行時にファジングを開始するファザーバイナリを生成します( cc_fuzzモジュールと同様)。ファザーはlibFuzzerファジングエンジンを利用するため、ファジングを制御するために多くの引数を取ることができます。これらは、 libFuzzerのドキュメントに列挙されています。

rust_fuzzモジュールはrust_binaryモジュールの拡張であり、そのため、同じプロパティと考慮事項を共有します。さらに、 cc_fuzzモジュールと同じプロパティと機能の多くを実装します。

基本的な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エンジンによって呼び出されるfuzz-targetエントリポイントを定義します。 data引数は、 libFuzzerエンジンによって提供される一連のバイトであり、ターゲット関数をファズするための入力として操作されます。

この例のファザーでは、データの長さのみがチェックされ、 heap_oob関数を呼び出すかどうかが決定されます。この関数を呼び出すと、範囲外の読み取りが行われます。 libFuzzerはカバレッジガイド付きファザーであるため、データの最初の326 Bが新しい実行パスをもたらさないと判断すると、問題のある長さにすばやく収束します。

この例をツリー内のtools / security / fuzzing / example_rust_fuzzer /で見つけます。ツリー内の別のファザー( rustlib依存関係をファジングする)のもう少し複雑な例を表示するには、 legacy_blob_fuzzerを参照してください。

構造に対応したRustファザーの作成方法のガイダンスについては、RustFuzzプロジェクトの公式ドキュメントであるRustFuzzブックを参照してください。