Loading libs/binder/tests/parcel_fuzzer/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -84,6 +84,7 @@ cc_library_static { }, }, srcs: [ "random_binder.cpp", "random_fd.cpp", "random_parcel.cpp", "libbinder_driver.cpp", Loading libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_binder.h 0 → 100644 +29 −0 Original line number Diff line number Diff line /* * 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 libs/binder/tests/parcel_fuzzer/random_binder.cpp 0 → 100644 +95 −0 Original line number Diff line number Diff line /* * 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 libs/binder/tests/parcel_fuzzer/random_parcel.cpp +11 −36 Original line number Diff line number Diff line Loading @@ -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())); Loading Loading @@ -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> { sp<IBinder> binder; if (options->extraBinders.size() > 0 && provider.ConsumeBool()) { return options->extraBinders.at( provider.ConsumeIntegralInRange< size_t>(0, options->extraBinders.size() - 1)); binder = options->extraBinders.at( provider.ConsumeIntegralInRange<size_t>(0, options->extraBinders .size() - 1)); } else { return nullptr; binder = getRandomBinder(&provider); } }, }); sp<IBinder> binder = makeFunc(); CHECK(OK == p->writeStrongBinder(binder)); }, }); Loading Loading
libs/binder/tests/parcel_fuzzer/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -84,6 +84,7 @@ cc_library_static { }, }, srcs: [ "random_binder.cpp", "random_fd.cpp", "random_parcel.cpp", "libbinder_driver.cpp", Loading
libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_binder.h 0 → 100644 +29 −0 Original line number Diff line number Diff line /* * 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
libs/binder/tests/parcel_fuzzer/random_binder.cpp 0 → 100644 +95 −0 Original line number Diff line number Diff line /* * 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
libs/binder/tests/parcel_fuzzer/random_parcel.cpp +11 −36 Original line number Diff line number Diff line Loading @@ -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())); Loading Loading @@ -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> { sp<IBinder> binder; if (options->extraBinders.size() > 0 && provider.ConsumeBool()) { return options->extraBinders.at( provider.ConsumeIntegralInRange< size_t>(0, options->extraBinders.size() - 1)); binder = options->extraBinders.at( provider.ConsumeIntegralInRange<size_t>(0, options->extraBinders .size() - 1)); } else { return nullptr; binder = getRandomBinder(&provider); } }, }); sp<IBinder> binder = makeFunc(); CHECK(OK == p->writeStrongBinder(binder)); }, }); Loading