diff options
4 files changed, 136 insertions, 36 deletions
diff --git a/libs/binder/tests/parcel_fuzzer/Android.bp b/libs/binder/tests/parcel_fuzzer/Android.bp index 0210237ed8..3904e1d4cc 100644 --- a/libs/binder/tests/parcel_fuzzer/Android.bp +++ b/libs/binder/tests/parcel_fuzzer/Android.bp @@ -84,6 +84,7 @@ cc_library_static { }, }, srcs: [ + "random_binder.cpp", "random_fd.cpp", "random_parcel.cpp", "libbinder_driver.cpp", diff --git a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_binder.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_binder.h new file mode 100644 index 0000000000..e57bae6035 --- /dev/null +++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_binder.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <binder/IBinder.h> +#include <fuzzer/FuzzedDataProvider.h> + +namespace android { + +// Get a random binder object for use in fuzzing. +// +// may return multiple FDs (e.g. pipe), but will always return at least one +sp<IBinder> getRandomBinder(FuzzedDataProvider* provider); + +} // namespace android diff --git a/libs/binder/tests/parcel_fuzzer/random_binder.cpp b/libs/binder/tests/parcel_fuzzer/random_binder.cpp new file mode 100644 index 0000000000..8a1fecb212 --- /dev/null +++ b/libs/binder/tests/parcel_fuzzer/random_binder.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <fuzzbinder/random_binder.h> + +#include <fuzzbinder/random_parcel.h> + +#include <android-base/logging.h> +#include <binder/IInterface.h> +#include <binder/IServiceManager.h> + +namespace android { + +class RandomBinder : public BBinder { +public: + RandomBinder(const String16& descriptor, std::vector<uint8_t>&& bytes) + : mDescriptor(descriptor), + mBytes(std::move(bytes)), + mProvider(mBytes.data(), mBytes.size()) {} + const String16& getInterfaceDescriptor() const override { return mDescriptor; } + + status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override { + (void)code; + (void)data; + (void)reply; + (void)flags; // note - for maximum coverage even ignore if oneway + + if (mProvider.ConsumeBool()) { + return mProvider.ConsumeIntegral<status_t>(); + } + + if (reply == nullptr) return OK; + + // TODO: things we could do to increase state space + // - also pull FDs and binders from 'data' + // (optionally combine these into random parcel 'options') + // - also pull FDs and binders from random parcel 'options' + RandomParcelOptions options; + + // random output + std::vector<uint8_t> subData = mProvider.ConsumeBytes<uint8_t>( + mProvider.ConsumeIntegralInRange<size_t>(0, mProvider.remaining_bytes())); + fillRandomParcel(reply, FuzzedDataProvider(subData.data(), subData.size()), &options); + + return OK; + } + +private: + String16 mDescriptor; + + // note may not all be used + std::vector<uint8_t> mBytes; + FuzzedDataProvider mProvider; +}; + +sp<IBinder> getRandomBinder(FuzzedDataProvider* provider) { + auto makeFunc = provider->PickValueInArray<const std::function<sp<IBinder>()>>({ + [&]() { + // descriptor is the length of a class name, e.g. + // "some.package.Foo" + std::string str = provider->ConsumeRandomLengthString(100 /*max length*/); + + // arbitrarily consume remaining data to create a binder that can return + // random results - coverage guided fuzzer should ensure all of the remaining + // data isn't always used + std::vector<uint8_t> bytes = provider->ConsumeBytes<uint8_t>( + provider->ConsumeIntegralInRange<size_t>(0, provider->remaining_bytes())); + + return new RandomBinder(String16(str.c_str()), std::move(bytes)); + }, + []() { + // this is the easiest remote binder to get ahold of, and it + // should be able to handle anything thrown at it, and + // essentially every process can talk to it, so it's a good + // candidate for checking usage of an actual BpBinder + return IInterface::asBinder(defaultServiceManager()); + }, + [&]() -> sp<IBinder> { return nullptr; }, + }); + return makeFunc(); +} + +} // namespace android diff --git a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp index 51cb768d3d..4bb486bef0 100644 --- a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp +++ b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp @@ -17,23 +17,14 @@ #include <fuzzbinder/random_parcel.h> #include <android-base/logging.h> -#include <binder/IServiceManager.h> #include <binder/RpcSession.h> #include <binder/RpcTransportRaw.h> +#include <fuzzbinder/random_binder.h> #include <fuzzbinder/random_fd.h> #include <utils/String16.h> namespace android { -class NamedBinder : public BBinder { -public: - NamedBinder(const String16& descriptor) : mDescriptor(descriptor) {} - const String16& getInterfaceDescriptor() const override { return mDescriptor; } - -private: - String16 mDescriptor; -}; - static void fillRandomParcelData(Parcel* p, FuzzedDataProvider&& provider) { std::vector<uint8_t> data = provider.ConsumeBytes<uint8_t>(provider.remaining_bytes()); CHECK(OK == p->write(data.data(), data.size())); @@ -89,32 +80,16 @@ void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider, RandomParcelOpti }, // write binder [&]() { - auto makeFunc = provider.PickValueInArray<const std::function<sp<IBinder>()>>({ - [&]() { - // descriptor is the length of a class name, e.g. - // "some.package.Foo" - std::string str = - provider.ConsumeRandomLengthString(100 /*max length*/); - return new NamedBinder(String16(str.c_str())); - }, - []() { - // this is the easiest remote binder to get ahold of, and it - // should be able to handle anything thrown at it, and - // essentially every process can talk to it, so it's a good - // candidate for checking usage of an actual BpBinder - return IInterface::asBinder(defaultServiceManager()); - }, - [&]() -> sp<IBinder> { - if (options->extraBinders.size() > 0 && provider.ConsumeBool()) { - return options->extraBinders.at( - provider.ConsumeIntegralInRange< - size_t>(0, options->extraBinders.size() - 1)); - } else { - return nullptr; - } - }, - }); - sp<IBinder> binder = makeFunc(); + sp<IBinder> binder; + if (options->extraBinders.size() > 0 && provider.ConsumeBool()) { + binder = options->extraBinders.at( + provider.ConsumeIntegralInRange<size_t>(0, + options->extraBinders + .size() - + 1)); + } else { + binder = getRandomBinder(&provider); + } CHECK(OK == p->writeStrongBinder(binder)); }, }); |