Testowanie z użyciem AIDL

Fuzzer zachowuje się jak klient usługi zdalnej, importując ją lub wywołując za pomocą wygenerowanej atrapy:

Korzystanie z interfejsu C++ API:

#include <fuzzbinder/libbinder_ndk_driver.h>
#include <fuzzer/FuzzedDataProvider.h>

#include <android-base/logging.h>
#include <android/binder_interface_utils.h>

using android::fuzzService;
using ndk::SharedRefBase;

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    auto binder = ndk::SharedRefBase::make<MyService>(...);

    fuzzService(binder->asBinder().get(), FuzzedDataProvider(data, size));

    return 0;
}

Korzystanie z interfejsu Rust API:

#![allow(missing_docs)]
#![no_main]
#[macro_use]
extern crate libfuzzer_sys;

use binder::{self, BinderFeatures, Interface};
use binder_random_parcel_rs::fuzz_service;

fuzz_target!(|data: &[u8]| {
    let service = BnTestService::new_binder(MyService, BinderFeatures::default());
    fuzz_service(&mut service.as_binder(), data);
});

Framework do fuzzingu usług AIDL

Jak pokazano w przykładzie powyżej, w fuzzerze wywoływana jest funkcja fuzzService, która przyjmuje jako parametry wejściowe IBinder (Service) i dataProvider. Najpierw inicjuje losowy obiekt Parcel za pomocą dostawcy danych i wywołuje metodę transact w usłudze zdalnej, używając wejściowego obiektu Parcel, a na koniec pobiera odpowiedź do obiektu Parcel odpowiedzi.

Tworzenie i uruchamianie narzędzi do fuzzingu

Fuzzery są domyślnie tworzone z uwzględnieniem pokrycia.

Do wykrywania problemów z pamięcią zalecamy te narzędzia: hwaddress narzędzia do oczyszczania działają tylko w architekturze arm:

SANITIZE_HOST=address SANITIZE_TARGET=hwaddress

Podczas uruchamiania z parametrem libFuzzer w pliku Android.bp można określić korpus, czyli katalog, i przekazać go do fuzzera. Niektóre narzędzia do testowania fuzzingowego określają też dictionary: w pliku Android.bp, a możesz przekazać go do libFuzzer za pomocą -dict path/to/dict. Więcej opcji znajdziesz w oficjalnej dokumentacji libFuzzer.

Aby uruchomić fuzzery na urządzeniu, wpisz adb sync data, a potem adb shell data/fuzz/arch/name/name. Aby uruchomić narzędzia fuzzing na hoście, uruchom polecenie $ANDROID_HOST_OUT/fuzz/arch/name/name.

System kompilacji sprawdza, czy każdy binder AOSP ma wpis fuzzera w powiązaniach fuzzerów usług. Test wiązania Fuzzer sprawdza, czy każda usługa w service_contexts ma narzędzie do testowania fuzzingowego. Jeśli w przypadku nowej usługi nie zostanie znaleziony fuzzer ani wyjątek, wystąpi błąd kompilacji.

Automatyczny fuzzer usług C++ można utworzyć, dodając te elementy (fuzzery w językach Java i Rust nie są jeszcze obsługiwane):

  • Wpis cc_fuzzAndroid.bp, aby zdefiniować moduł fuzzera. Moduł cc_default service_fuzzer_defaults ma zależności wymagane w przypadku fuzzService.
  • Zależności specyficzne dla usługi należy dodać jako bibliotekę lub źródła.
  • główny plik, który tworzy usługę i wywołuje fuzzService;

Szczegółowe instrukcje korzystania z cc_fuzz znajdziesz w dokumentacji Fuzzing with libFuzzer. Aby rozwiązać błąd kompilacji, zaktualizuj powiązania, podając nowe nazwy usługi i fuzzera. W przypadku usług w językach Java lub Rust lista fuzzera może być pusta.