퍼지 모듈

Rust 퍼징은 LLVM의 libFuzzer 퍼징 엔진으로의 바인딩을 제공하는 libfuzzer-sys 크리에이트를 통해 지원됩니다. 자세한 내용은 libfuzzer-sys 저장소 및 LLVM libFuzzer 프로젝트 페이지를 참고하세요.

rust_fuzz 모듈은 (cc_fuzz 모듈과 비슷하게) 실행되면 퍼징을 시작하는 퍼저 바이너리를 생성합니다. 퍼저는 libFuzzer 퍼징 엔진을 사용하므로 여러 인수를 받아서 퍼징을 제어할 수 있습니다. 인수는 libFuzzer 도움말에 나와 있습니다.

rust_fuzz 모듈은 rust_binary 모듈의 확장이기 때문에 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는 커버리지 기반 퍼저이므로 데이터의 처음 326B의 결과로 새로운 실행 결과가 생성되지 않는다는 사실을 확인하면 문제가 되는 길이로 빠르게 수렴합니다.

이 예는 tools/security/fuzzing/example_rust_fuzzer/의 트리에서 확인할 수 있습니다. 트리에서 (rustlib 종속 항목을 퍼징하는) 다른 퍼저의 보다 복잡한 예를 보려면 legacy_blob_fuzzer를 참고하세요.

구조 인식 Rust 퍼저를 작성하는 방법을 알아보려면 Rust Fuzz 프로젝트 공식 도움말인 Rust Fuzz 북을 참고하세요.