From 9711ad3d0e9792eb7073cc8525eaaefe49285b9c Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Wed, 16 Mar 2022 01:03:02 +0000 Subject: libbinder_random_parcel: driver writes iface token It's really hard for the fuzzer to guess the interface token, so rather than generating corpus or dictionaries for these for every fuzzer, have the driver do this. As a follow-up, we should have the driver keep track of binder objects which are returned inside of the reply Parcel and also fuzz these objects as well as send them back into the service. Bug: 224646709 Test: vibrator example fuzzer instantly hits code inside of the vibrator service when fuzzing. Change-Id: Idf1970439b87a01b44df1904605858c98a49e81a --- .../include_random_parcel/fuzzbinder/random_parcel.h | 11 ++++++++++- libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp | 9 ++++++++- libs/binder/tests/parcel_fuzzer/random_parcel.cpp | 8 +++++++- 3 files changed, 25 insertions(+), 3 deletions(-) (limited to 'libs') diff --git a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h index db35e39108..633626ca44 100644 --- a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h +++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h @@ -19,9 +19,18 @@ #include #include +#include + namespace android { /** * Fill parcel data, including some random binder objects and FDs + * + * p - the Parcel to fill + * provider - takes ownership and completely consumes provider + * writeHeader - optional function to write a specific header once the format of the parcel is + * picked (for instance, to write an interface header) */ -void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider); +void fillRandomParcel( + Parcel* p, FuzzedDataProvider&& provider, + std::function writeHeader = nullptr); } // namespace android diff --git a/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp index e849c9bbce..be39bb9195 100644 --- a/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp +++ b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp @@ -27,7 +27,14 @@ void fuzzService(const sp& binder, FuzzedDataProvider&& provider) { std::vector subData = provider.ConsumeBytes( provider.ConsumeIntegralInRange(0, provider.remaining_bytes())); - fillRandomParcel(&data, FuzzedDataProvider(subData.data(), subData.size())); + fillRandomParcel(&data, FuzzedDataProvider(subData.data(), subData.size()), + [&binder](Parcel* p, FuzzedDataProvider& provider) { + // most code will be behind checks that the head of the Parcel + // is exactly this, so make it easier for fuzzers to reach this + if (provider.ConsumeBool()) { + p->writeInterfaceToken(binder->getInterfaceDescriptor()); + } + }); Parcel reply; (void)binder->transact(code, data, &reply, flags); diff --git a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp index 89eadae981..cfabc1e6b5 100644 --- a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp +++ b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp @@ -39,15 +39,21 @@ static void fillRandomParcelData(Parcel* p, FuzzedDataProvider&& provider) { CHECK(OK == p->write(data.data(), data.size())); } -void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider) { +void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider, + std::function writeHeader) { if (provider.ConsumeBool()) { auto session = RpcSession::make(RpcTransportCtxFactoryRaw::make()); CHECK_EQ(OK, session->addNullDebuggingClient()); p->markForRpc(session); + + writeHeader(p, provider); + fillRandomParcelData(p, std::move(provider)); return; } + writeHeader(p, provider); + while (provider.remaining_bytes() > 0) { auto fillFunc = provider.PickValueInArray>({ // write data -- cgit v1.2.3-59-g8ed1b