さびファジングは、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ブックを参照してください。