diff options
author | 2022-03-16 01:03:02 +0000 | |
---|---|---|
committer | 2022-03-16 01:05:44 +0000 | |
commit | 9711ad3d0e9792eb7073cc8525eaaefe49285b9c (patch) | |
tree | fef24e9b39b89c7ceefa3dd6738a4ee21fa56af3 | |
parent | 8a2607c4aa1519e68f2e99529d6f5036a5b2c5dc (diff) |
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
3 files changed, 25 insertions, 3 deletions
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 <binder/Parcel.h> #include <fuzzer/FuzzedDataProvider.h> +#include <functional> + 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<void(Parcel* p, FuzzedDataProvider& provider)> 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<IBinder>& binder, FuzzedDataProvider&& provider) { std::vector<uint8_t> subData = provider.ConsumeBytes<uint8_t>( provider.ConsumeIntegralInRange<size_t>(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<void(Parcel* p, FuzzedDataProvider& provider)> 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<const std::function<void()>>({ // write data |