AIDL Fuzzing

The fuzzer behaves as a client for the remote service by importing/invoking it through the generated stub:

Using 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;
}

Using 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);
});

Using Java API:

import com.code_intelligence.jazzer.api.FuzzedDataProvider;

import randomparcel.FuzzBinder;

public class ServiceFuzzer {

    static {
        // Initialize fuzzService and JNI dependencies
        FuzzBinder.init();
    }

    public static void fuzzerTestOneInput(FuzzedDataProvider data) {
        TestService service = new TestService();
        FuzzBinder.fuzzService(service, data.consumeRemainingAsBytes());
    }
}

For build setup, refer to Java Binder Service Fuzzer.

Framework to fuzz AIDL services

As shown in the example above, fuzzService is called in the fuzzer and takes in an IBinder (Service) and dataProvider as input parameters. It first initializes a random Parcel object using the data provider and call the transact method on the remote service by using the input parcel, and finally get the reply into a reply parcel.

The build system checks whether every AOSP binder service has a fuzzer entry in service fuzzer bindings. The Fuzzer binding test checks that every service in service_contexts has a fuzzer. If a fuzzer/exception isn't found for a new service, there's a build error.

An automatic C++ service fuzzer can be written by adding the following (Java and Rust fuzzers are not yet supported):

  • A cc_fuzz entry in Android.bp to define the fuzzer module. The cc_default module service_fuzzer_defaults has dependencies required for fuzzService.
  • Service-specific dependencies should be added as a library or as sources.
  • A main file that constructs your service and calls fuzzService

For detailed instructions on using cc_fuzz, see the Fuzzing with libFuzzer documentation. To resolve build error, update bindings with the new service and fuzzer names. For Java/Rust services, the fuzzer list can be empty.