מודולים של Fuzz

יש תמיכה ב-Rust fuzzing דרך תיבת libfuzzer-sys, שמספקת קשירות למנוע ה-fuzzing של libFuzzer של LLVM. מידע נוסף זמין במאגר libfuzzer-sys ובדף הפרויקט LLVM libFuzzer.

מודול rust_fuzz מייצר קובץ בינארי של fuzzer שמתחיל בבדיקת fuzz כשהוא מופעל (בדומה למודולים של cc_fuzz). הכלי Fuzzer משתמש במנוע libFuzzerfuzzing, ולכן אפשר להשתמש במספר ארגומנטים כדי לשלוט ב-fuzzing. הם מפורטים במסמכי התיעוד של libFuzzer.

מודולים של rust_fuzz הם הרחבה של מודולים של rust_binary, ולכן יש להם את אותן תכונות ושיקולים. בנוסף, הם מטמיעים הרבה מאותן תכונות ופונקציות כמו מודולי cc_fuzz.

כשיוצרים מודולים של rust_fuzz, מופעל הדגל --cfg fuzzing שאפשר להשתמש בו כדי לתמוך בהידור מותנה של קוד הספרייה, וכך לשפר את בדיקת fuzz.

כתיבת כלי בסיסי לבדיקת חוסן של קוד Rust

אפשר להגדיר מודול פאז בקובץ build‏ 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 */ }); מגדיר את נקודת הכניסה של יעד ה-fuzz שנקראת על ידי מנוע libFuzzer. הארגומנט data הוא רצף של בייטים שמסופק על ידי מנוע libFuzzer כדי שיעבור מניפולציה כקלט לטשטוש הפונקציה הממוקדת.

ב-fuzzer הזה, רק האורך של הנתונים נבדק כדי לקבוע אם להפעיל את הפונקציה heap_oob. הפעלת הפונקציה גורמת לקריאה מחוץ לגבולות. ‫libFuzzer הוא כלי fuzzing שמבוסס על כיסוי, ולכן הוא מתכנס במהירות לאורך הבעייתי, כי הוא קובע ש-326 הבתים הראשונים של הנתונים לא מובילים לנתיבי ביצוע חדשים.

אפשר למצוא את הדוגמה הזו בתוך העץ בנתיב tools/security/fuzzing/example_rust_fuzzer/‎. כדי לראות דוגמה קצת יותר מורכבת של כלי אחר ליצירת קלט אקראי (שיוצר קלט אקראי לrustlib תלות) בתוך העץ, אפשר לעיין ב-legacy_blob_fuzzer.

הוראות לכתיבת fuzzers ב-Rust שמודעים למבנה מופיעות בספר Rust Fuzz, התיעוד הרשמי של פרויקט Rust Fuzz.