Loading libs/binder/tests/parcel_fuzzer/binder.cpp +120 −0 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,8 @@ #include <binder/ParcelableHolder.h> #include <binder/ParcelableHolder.h> #include <binder/PersistableBundle.h> #include <binder/PersistableBundle.h> #include <binder/Status.h> #include <binder/Status.h> #include <fuzzbinder/random_binder.h> #include <fuzzbinder/random_fd.h> #include <utils/Flattenable.h> #include <utils/Flattenable.h> #include "../../Utils.h" #include "../../Utils.h" Loading Loading @@ -404,5 +406,123 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { FUZZ_LOG() << " toString() result: " << toString; FUZZ_LOG() << " toString() result: " << toString; }, }, }; }; std::vector<ParcelWrite<::android::Parcel>> BINDER_PARCEL_WRITE_FUNCTIONS { [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call setDataSize"; size_t len = provider.ConsumeIntegralInRange<size_t>(0, 1024); p.setDataSize(len); }, [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call setDataCapacity"; size_t len = provider.ConsumeIntegralInRange<size_t>(0, 1024); p.setDataCapacity(len); }, [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call setData"; size_t len = provider.ConsumeIntegralInRange<size_t>(0, 1024); std::vector<uint8_t> bytes = provider.ConsumeBytes<uint8_t>(len); p.setData(bytes.data(), bytes.size()); }, [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* options) { FUZZ_LOG() << "about to call appendFrom"; std::vector<uint8_t> bytes = provider.ConsumeBytes<uint8_t>(provider.ConsumeIntegralInRange<size_t>(0, 4096)); ::android::Parcel p2; fillRandomParcel(&p2, FuzzedDataProvider(bytes.data(), bytes.size()), options); int32_t start = provider.ConsumeIntegral<int32_t>(); int32_t len = provider.ConsumeIntegral<int32_t>(); p.appendFrom(&p2, start, len); }, [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call setData"; size_t len = provider.ConsumeIntegralInRange<size_t>(0, 1024); std::vector<uint8_t> bytes = provider.ConsumeBytes<uint8_t>(len); p.setData(bytes.data(), bytes.size()); }, [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call pushAllowFds"; bool val = provider.ConsumeBool(); p.pushAllowFds(val); }, [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call restoreAllowFds"; bool val = provider.ConsumeBool(); p.restoreAllowFds(val); }, // markForBinder - covered by fillRandomParcel, aborts if called multiple times // markForRpc - covered by fillRandomParcel, aborts if called multiple times [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call writeInterfaceToken"; std::string interface = provider.ConsumeRandomLengthString(); p.writeInterfaceToken(android::String16(interface.c_str())); }, [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call setEnforceNoDataAvail"; p.setEnforceNoDataAvail(provider.ConsumeBool()); }, [] (::android::Parcel& p, FuzzedDataProvider& /* provider */, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call setServiceFuzzing"; p.setServiceFuzzing(); }, [] (::android::Parcel& p, FuzzedDataProvider& /* provider */, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call freeData"; p.freeData(); }, [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call write"; size_t len = provider.ConsumeIntegralInRange<size_t>(0, 256); std::vector<uint8_t> bytes = provider.ConsumeBytes<uint8_t>(len); p.write(bytes.data(), bytes.size()); }, // write* - write functions all implemented by calling 'write' itself. [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* options) { FUZZ_LOG() << "about to call writeStrongBinder"; // TODO: this logic is somewhat duplicated with random parcel android::sp<android::IBinder> binder; if (provider.ConsumeBool() && options->extraBinders.size() > 0) { binder = options->extraBinders.at( provider.ConsumeIntegralInRange<size_t>(0, options->extraBinders.size() - 1)); } else { binder = android::getRandomBinder(&provider); options->extraBinders.push_back(binder); } p.writeStrongBinder(binder); }, [] (::android::Parcel& p, FuzzedDataProvider& /* provider */, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call writeFileDescriptor (no ownership)"; p.writeFileDescriptor(STDERR_FILENO, false /* takeOwnership */); }, [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* options) { FUZZ_LOG() << "about to call writeFileDescriptor (take ownership)"; std::vector<unique_fd> fds = android::getRandomFds(&provider); if (fds.size() == 0) return; p.writeDupFileDescriptor(fds.at(0).get()); options->extraFds.insert(options->extraFds.end(), std::make_move_iterator(fds.begin() + 1), std::make_move_iterator(fds.end())); }, // TODO: writeBlob // TODO: writeDupImmutableBlobFileDescriptor // TODO: writeObject (or make the API private more likely) [] (::android::Parcel& p, FuzzedDataProvider& /* provider */, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call writeNoException"; p.writeNoException(); }, [] (::android::Parcel& p, FuzzedDataProvider& /* provider */, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call closeFileDescriptors"; p.closeFileDescriptors(); }, [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call replaceCallingWorkSourceUid"; uid_t uid = provider.ConsumeIntegral<uid_t>(); p.replaceCallingWorkSourceUid(uid); }, }; // clang-format on // clang-format on #pragma clang diagnostic pop #pragma clang diagnostic pop libs/binder/tests/parcel_fuzzer/binder.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -21,3 +21,4 @@ #include "parcel_fuzzer.h" #include "parcel_fuzzer.h" extern std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS; extern std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS; extern std::vector<ParcelWrite<::android::Parcel>> BINDER_PARCEL_WRITE_FUNCTIONS; libs/binder/tests/parcel_fuzzer/binder_ndk.cpp +46 −8 Original line number Original line Diff line number Diff line Loading @@ -20,8 +20,11 @@ #include "aidl/parcelables/GenericDataParcelable.h" #include "aidl/parcelables/GenericDataParcelable.h" #include "aidl/parcelables/SingleDataParcelable.h" #include "aidl/parcelables/SingleDataParcelable.h" #include <android/binder_libbinder.h> #include <android/binder_parcel_utils.h> #include <android/binder_parcel_utils.h> #include <android/binder_parcelable_utils.h> #include <android/binder_parcelable_utils.h> #include <fuzzbinder/random_binder.h> #include <fuzzbinder/random_fd.h> #include "util.h" #include "util.h" Loading Loading @@ -211,16 +214,51 @@ std::vector<ParcelRead<NdkParcelAdapter>> BINDER_NDK_PARCEL_READ_FUNCTIONS{ binder_status_t status = AParcel_marshal(p.aParcel(), buffer, start, len); binder_status_t status = AParcel_marshal(p.aParcel(), buffer, start, len); FUZZ_LOG() << "status: " << status; FUZZ_LOG() << "status: " << status; }, }, [](const NdkParcelAdapter& /*p*/, FuzzedDataProvider& provider) { }; FUZZ_LOG() << "about to unmarshal AParcel"; std::vector<ParcelWrite<NdkParcelAdapter>> BINDER_NDK_PARCEL_WRITE_FUNCTIONS{ [] (NdkParcelAdapter& p, FuzzedDataProvider& provider, android::RandomParcelOptions* options) { FUZZ_LOG() << "about to call AParcel_writeStrongBinder"; // TODO: this logic is somewhat duplicated with random parcel android::sp<android::IBinder> binder; if (provider.ConsumeBool() && options->extraBinders.size() > 0) { binder = options->extraBinders.at( provider.ConsumeIntegralInRange<size_t>(0, options->extraBinders.size() - 1)); } else { binder = android::getRandomBinder(&provider); options->extraBinders.push_back(binder); } ndk::SpAIBinder abinder = ndk::SpAIBinder(AIBinder_fromPlatformBinder(binder)); AParcel_writeStrongBinder(p.aParcel(), abinder.get()); }, [] (NdkParcelAdapter& p, FuzzedDataProvider& provider, android::RandomParcelOptions* options) { FUZZ_LOG() << "about to call AParcel_writeParcelFileDescriptor"; auto fds = android::getRandomFds(&provider); if (fds.size() == 0) return; AParcel_writeParcelFileDescriptor(p.aParcel(), fds.at(0).get()); options->extraFds.insert(options->extraFds.end(), std::make_move_iterator(fds.begin() + 1), std::make_move_iterator(fds.end())); }, // all possible data writes can be done as a series of 4-byte reads [] (NdkParcelAdapter& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call AParcel_writeInt32"; int32_t val = provider.ConsumeIntegral<int32_t>(); AParcel_writeInt32(p.aParcel(), val); }, [] (NdkParcelAdapter& p, FuzzedDataProvider& /* provider */, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call AParcel_reset"; AParcel_reset(p.aParcel()); }, [](NdkParcelAdapter& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call AParcel_unmarshal"; size_t len = provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes()); size_t len = provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes()); std::vector<uint8_t> parcelData = provider.ConsumeBytes<uint8_t>(len); std::vector<uint8_t> data = provider.ConsumeBytes<uint8_t>(len); const uint8_t* buffer = parcelData.data(); binder_status_t status = AParcel_unmarshal(p.aParcel(), data.data(), data.size()); const size_t bufferLen = parcelData.size(); NdkParcelAdapter adapter; binder_status_t status = AParcel_unmarshal(adapter.aParcel(), buffer, bufferLen); FUZZ_LOG() << "status: " << status; FUZZ_LOG() << "status: " << status; }, }, }; }; // clang-format on // clang-format on libs/binder/tests/parcel_fuzzer/binder_ndk.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -50,3 +50,4 @@ private: }; }; extern std::vector<ParcelRead<NdkParcelAdapter>> BINDER_NDK_PARCEL_READ_FUNCTIONS; extern std::vector<ParcelRead<NdkParcelAdapter>> BINDER_NDK_PARCEL_READ_FUNCTIONS; extern std::vector<ParcelWrite<NdkParcelAdapter>> BINDER_NDK_PARCEL_WRITE_FUNCTIONS; libs/binder/tests/parcel_fuzzer/main.cpp +28 −18 Original line number Original line Diff line number Diff line Loading @@ -80,6 +80,7 @@ void doTransactFuzz(const char* backend, const sp<B>& binder, FuzzedDataProvider (void)binder->transact(code, data, &reply, flag); (void)binder->transact(code, data, &reply, flag); } } // start with a Parcel full of data (e.g. like you get from another process) template <typename P> template <typename P> void doReadFuzz(const char* backend, const std::vector<ParcelRead<P>>& reads, void doReadFuzz(const char* backend, const std::vector<ParcelRead<P>>& reads, FuzzedDataProvider&& provider) { FuzzedDataProvider&& provider) { Loading @@ -98,7 +99,7 @@ void doReadFuzz(const char* backend, const std::vector<ParcelRead<P>>& reads, fillRandomParcel(&p, std::move(provider), &options); fillRandomParcel(&p, std::move(provider), &options); // since we are only using a byte to index // since we are only using a byte to index CHECK(reads.size() <= 255) << reads.size(); CHECK_LE(reads.size(), 255u) << reads.size(); FUZZ_LOG() << "backend: " << backend; FUZZ_LOG() << "backend: " << backend; FUZZ_LOG() << "input: " << HexString(p.data(), p.dataSize()); FUZZ_LOG() << "input: " << HexString(p.data(), p.dataSize()); Loading @@ -115,26 +116,31 @@ void doReadFuzz(const char* backend, const std::vector<ParcelRead<P>>& reads, } } } } // Append two random parcels. template <typename P> template <typename P> void doAppendFuzz(const char* backend, FuzzedDataProvider&& provider) { void doReadWriteFuzz(const char* backend, const std::vector<ParcelRead<P>>& reads, int32_t start = provider.ConsumeIntegral<int32_t>(); const std::vector<ParcelWrite<P>>& writes, FuzzedDataProvider&& provider) { int32_t len = provider.ConsumeIntegral<int32_t>(); std::vector<uint8_t> bytes = provider.ConsumeBytes<uint8_t>( provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes())); // same options so that FDs and binders could be shared in both Parcels RandomParcelOptions options; RandomParcelOptions options; P p0, p1; P p; fillRandomParcel(&p0, FuzzedDataProvider(bytes.data(), bytes.size()), &options); fillRandomParcel(&p, std::move(provider), &options); fillRandomParcel(&p1, std::move(provider), &options); // since we are only using a byte to index CHECK_LE(reads.size() + writes.size(), 255u) << reads.size(); FUZZ_LOG() << "backend: " << backend; FUZZ_LOG() << "backend: " << backend; FUZZ_LOG() << "start: " << start << " len: " << len; p0.appendFrom(&p1, start, len); while (provider.remaining_bytes() > 0) { uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, reads.size() + writes.size() - 1); FUZZ_LOG() << "Instruction " << idx << " avail: " << p.dataAvail() << " pos: " << p.dataPosition() << " cap: " << p.dataCapacity(); if (idx < reads.size()) { reads.at(idx)(p, provider); } else { writes.at(idx - reads.size())(p, provider, &options); } } } } void* NothingClass_onCreate(void* args) { void* NothingClass_onCreate(void* args) { Loading Loading @@ -187,10 +193,14 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { std::move(provider)); std::move(provider)); }, }, [](FuzzedDataProvider&& provider) { [](FuzzedDataProvider&& provider) { doAppendFuzz<::android::Parcel>("binder", std::move(provider)); doReadWriteFuzz<::android::Parcel>("binder", BINDER_PARCEL_READ_FUNCTIONS, BINDER_PARCEL_WRITE_FUNCTIONS, std::move(provider)); }, }, [](FuzzedDataProvider&& provider) { [](FuzzedDataProvider&& provider) { doAppendFuzz<NdkParcelAdapter>("binder_ndk", std::move(provider)); doReadWriteFuzz<NdkParcelAdapter>("binder_ndk", BINDER_NDK_PARCEL_READ_FUNCTIONS, BINDER_NDK_PARCEL_WRITE_FUNCTIONS, std::move(provider)); }, }, }; }; Loading Loading
libs/binder/tests/parcel_fuzzer/binder.cpp +120 −0 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,8 @@ #include <binder/ParcelableHolder.h> #include <binder/ParcelableHolder.h> #include <binder/PersistableBundle.h> #include <binder/PersistableBundle.h> #include <binder/Status.h> #include <binder/Status.h> #include <fuzzbinder/random_binder.h> #include <fuzzbinder/random_fd.h> #include <utils/Flattenable.h> #include <utils/Flattenable.h> #include "../../Utils.h" #include "../../Utils.h" Loading Loading @@ -404,5 +406,123 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { FUZZ_LOG() << " toString() result: " << toString; FUZZ_LOG() << " toString() result: " << toString; }, }, }; }; std::vector<ParcelWrite<::android::Parcel>> BINDER_PARCEL_WRITE_FUNCTIONS { [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call setDataSize"; size_t len = provider.ConsumeIntegralInRange<size_t>(0, 1024); p.setDataSize(len); }, [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call setDataCapacity"; size_t len = provider.ConsumeIntegralInRange<size_t>(0, 1024); p.setDataCapacity(len); }, [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call setData"; size_t len = provider.ConsumeIntegralInRange<size_t>(0, 1024); std::vector<uint8_t> bytes = provider.ConsumeBytes<uint8_t>(len); p.setData(bytes.data(), bytes.size()); }, [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* options) { FUZZ_LOG() << "about to call appendFrom"; std::vector<uint8_t> bytes = provider.ConsumeBytes<uint8_t>(provider.ConsumeIntegralInRange<size_t>(0, 4096)); ::android::Parcel p2; fillRandomParcel(&p2, FuzzedDataProvider(bytes.data(), bytes.size()), options); int32_t start = provider.ConsumeIntegral<int32_t>(); int32_t len = provider.ConsumeIntegral<int32_t>(); p.appendFrom(&p2, start, len); }, [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call setData"; size_t len = provider.ConsumeIntegralInRange<size_t>(0, 1024); std::vector<uint8_t> bytes = provider.ConsumeBytes<uint8_t>(len); p.setData(bytes.data(), bytes.size()); }, [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call pushAllowFds"; bool val = provider.ConsumeBool(); p.pushAllowFds(val); }, [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call restoreAllowFds"; bool val = provider.ConsumeBool(); p.restoreAllowFds(val); }, // markForBinder - covered by fillRandomParcel, aborts if called multiple times // markForRpc - covered by fillRandomParcel, aborts if called multiple times [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call writeInterfaceToken"; std::string interface = provider.ConsumeRandomLengthString(); p.writeInterfaceToken(android::String16(interface.c_str())); }, [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call setEnforceNoDataAvail"; p.setEnforceNoDataAvail(provider.ConsumeBool()); }, [] (::android::Parcel& p, FuzzedDataProvider& /* provider */, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call setServiceFuzzing"; p.setServiceFuzzing(); }, [] (::android::Parcel& p, FuzzedDataProvider& /* provider */, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call freeData"; p.freeData(); }, [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call write"; size_t len = provider.ConsumeIntegralInRange<size_t>(0, 256); std::vector<uint8_t> bytes = provider.ConsumeBytes<uint8_t>(len); p.write(bytes.data(), bytes.size()); }, // write* - write functions all implemented by calling 'write' itself. [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* options) { FUZZ_LOG() << "about to call writeStrongBinder"; // TODO: this logic is somewhat duplicated with random parcel android::sp<android::IBinder> binder; if (provider.ConsumeBool() && options->extraBinders.size() > 0) { binder = options->extraBinders.at( provider.ConsumeIntegralInRange<size_t>(0, options->extraBinders.size() - 1)); } else { binder = android::getRandomBinder(&provider); options->extraBinders.push_back(binder); } p.writeStrongBinder(binder); }, [] (::android::Parcel& p, FuzzedDataProvider& /* provider */, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call writeFileDescriptor (no ownership)"; p.writeFileDescriptor(STDERR_FILENO, false /* takeOwnership */); }, [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* options) { FUZZ_LOG() << "about to call writeFileDescriptor (take ownership)"; std::vector<unique_fd> fds = android::getRandomFds(&provider); if (fds.size() == 0) return; p.writeDupFileDescriptor(fds.at(0).get()); options->extraFds.insert(options->extraFds.end(), std::make_move_iterator(fds.begin() + 1), std::make_move_iterator(fds.end())); }, // TODO: writeBlob // TODO: writeDupImmutableBlobFileDescriptor // TODO: writeObject (or make the API private more likely) [] (::android::Parcel& p, FuzzedDataProvider& /* provider */, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call writeNoException"; p.writeNoException(); }, [] (::android::Parcel& p, FuzzedDataProvider& /* provider */, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call closeFileDescriptors"; p.closeFileDescriptors(); }, [] (::android::Parcel& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call replaceCallingWorkSourceUid"; uid_t uid = provider.ConsumeIntegral<uid_t>(); p.replaceCallingWorkSourceUid(uid); }, }; // clang-format on // clang-format on #pragma clang diagnostic pop #pragma clang diagnostic pop
libs/binder/tests/parcel_fuzzer/binder.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -21,3 +21,4 @@ #include "parcel_fuzzer.h" #include "parcel_fuzzer.h" extern std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS; extern std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS; extern std::vector<ParcelWrite<::android::Parcel>> BINDER_PARCEL_WRITE_FUNCTIONS;
libs/binder/tests/parcel_fuzzer/binder_ndk.cpp +46 −8 Original line number Original line Diff line number Diff line Loading @@ -20,8 +20,11 @@ #include "aidl/parcelables/GenericDataParcelable.h" #include "aidl/parcelables/GenericDataParcelable.h" #include "aidl/parcelables/SingleDataParcelable.h" #include "aidl/parcelables/SingleDataParcelable.h" #include <android/binder_libbinder.h> #include <android/binder_parcel_utils.h> #include <android/binder_parcel_utils.h> #include <android/binder_parcelable_utils.h> #include <android/binder_parcelable_utils.h> #include <fuzzbinder/random_binder.h> #include <fuzzbinder/random_fd.h> #include "util.h" #include "util.h" Loading Loading @@ -211,16 +214,51 @@ std::vector<ParcelRead<NdkParcelAdapter>> BINDER_NDK_PARCEL_READ_FUNCTIONS{ binder_status_t status = AParcel_marshal(p.aParcel(), buffer, start, len); binder_status_t status = AParcel_marshal(p.aParcel(), buffer, start, len); FUZZ_LOG() << "status: " << status; FUZZ_LOG() << "status: " << status; }, }, [](const NdkParcelAdapter& /*p*/, FuzzedDataProvider& provider) { }; FUZZ_LOG() << "about to unmarshal AParcel"; std::vector<ParcelWrite<NdkParcelAdapter>> BINDER_NDK_PARCEL_WRITE_FUNCTIONS{ [] (NdkParcelAdapter& p, FuzzedDataProvider& provider, android::RandomParcelOptions* options) { FUZZ_LOG() << "about to call AParcel_writeStrongBinder"; // TODO: this logic is somewhat duplicated with random parcel android::sp<android::IBinder> binder; if (provider.ConsumeBool() && options->extraBinders.size() > 0) { binder = options->extraBinders.at( provider.ConsumeIntegralInRange<size_t>(0, options->extraBinders.size() - 1)); } else { binder = android::getRandomBinder(&provider); options->extraBinders.push_back(binder); } ndk::SpAIBinder abinder = ndk::SpAIBinder(AIBinder_fromPlatformBinder(binder)); AParcel_writeStrongBinder(p.aParcel(), abinder.get()); }, [] (NdkParcelAdapter& p, FuzzedDataProvider& provider, android::RandomParcelOptions* options) { FUZZ_LOG() << "about to call AParcel_writeParcelFileDescriptor"; auto fds = android::getRandomFds(&provider); if (fds.size() == 0) return; AParcel_writeParcelFileDescriptor(p.aParcel(), fds.at(0).get()); options->extraFds.insert(options->extraFds.end(), std::make_move_iterator(fds.begin() + 1), std::make_move_iterator(fds.end())); }, // all possible data writes can be done as a series of 4-byte reads [] (NdkParcelAdapter& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call AParcel_writeInt32"; int32_t val = provider.ConsumeIntegral<int32_t>(); AParcel_writeInt32(p.aParcel(), val); }, [] (NdkParcelAdapter& p, FuzzedDataProvider& /* provider */, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call AParcel_reset"; AParcel_reset(p.aParcel()); }, [](NdkParcelAdapter& p, FuzzedDataProvider& provider, android::RandomParcelOptions* /*options*/) { FUZZ_LOG() << "about to call AParcel_unmarshal"; size_t len = provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes()); size_t len = provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes()); std::vector<uint8_t> parcelData = provider.ConsumeBytes<uint8_t>(len); std::vector<uint8_t> data = provider.ConsumeBytes<uint8_t>(len); const uint8_t* buffer = parcelData.data(); binder_status_t status = AParcel_unmarshal(p.aParcel(), data.data(), data.size()); const size_t bufferLen = parcelData.size(); NdkParcelAdapter adapter; binder_status_t status = AParcel_unmarshal(adapter.aParcel(), buffer, bufferLen); FUZZ_LOG() << "status: " << status; FUZZ_LOG() << "status: " << status; }, }, }; }; // clang-format on // clang-format on
libs/binder/tests/parcel_fuzzer/binder_ndk.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -50,3 +50,4 @@ private: }; }; extern std::vector<ParcelRead<NdkParcelAdapter>> BINDER_NDK_PARCEL_READ_FUNCTIONS; extern std::vector<ParcelRead<NdkParcelAdapter>> BINDER_NDK_PARCEL_READ_FUNCTIONS; extern std::vector<ParcelWrite<NdkParcelAdapter>> BINDER_NDK_PARCEL_WRITE_FUNCTIONS;
libs/binder/tests/parcel_fuzzer/main.cpp +28 −18 Original line number Original line Diff line number Diff line Loading @@ -80,6 +80,7 @@ void doTransactFuzz(const char* backend, const sp<B>& binder, FuzzedDataProvider (void)binder->transact(code, data, &reply, flag); (void)binder->transact(code, data, &reply, flag); } } // start with a Parcel full of data (e.g. like you get from another process) template <typename P> template <typename P> void doReadFuzz(const char* backend, const std::vector<ParcelRead<P>>& reads, void doReadFuzz(const char* backend, const std::vector<ParcelRead<P>>& reads, FuzzedDataProvider&& provider) { FuzzedDataProvider&& provider) { Loading @@ -98,7 +99,7 @@ void doReadFuzz(const char* backend, const std::vector<ParcelRead<P>>& reads, fillRandomParcel(&p, std::move(provider), &options); fillRandomParcel(&p, std::move(provider), &options); // since we are only using a byte to index // since we are only using a byte to index CHECK(reads.size() <= 255) << reads.size(); CHECK_LE(reads.size(), 255u) << reads.size(); FUZZ_LOG() << "backend: " << backend; FUZZ_LOG() << "backend: " << backend; FUZZ_LOG() << "input: " << HexString(p.data(), p.dataSize()); FUZZ_LOG() << "input: " << HexString(p.data(), p.dataSize()); Loading @@ -115,26 +116,31 @@ void doReadFuzz(const char* backend, const std::vector<ParcelRead<P>>& reads, } } } } // Append two random parcels. template <typename P> template <typename P> void doAppendFuzz(const char* backend, FuzzedDataProvider&& provider) { void doReadWriteFuzz(const char* backend, const std::vector<ParcelRead<P>>& reads, int32_t start = provider.ConsumeIntegral<int32_t>(); const std::vector<ParcelWrite<P>>& writes, FuzzedDataProvider&& provider) { int32_t len = provider.ConsumeIntegral<int32_t>(); std::vector<uint8_t> bytes = provider.ConsumeBytes<uint8_t>( provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes())); // same options so that FDs and binders could be shared in both Parcels RandomParcelOptions options; RandomParcelOptions options; P p0, p1; P p; fillRandomParcel(&p0, FuzzedDataProvider(bytes.data(), bytes.size()), &options); fillRandomParcel(&p, std::move(provider), &options); fillRandomParcel(&p1, std::move(provider), &options); // since we are only using a byte to index CHECK_LE(reads.size() + writes.size(), 255u) << reads.size(); FUZZ_LOG() << "backend: " << backend; FUZZ_LOG() << "backend: " << backend; FUZZ_LOG() << "start: " << start << " len: " << len; p0.appendFrom(&p1, start, len); while (provider.remaining_bytes() > 0) { uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, reads.size() + writes.size() - 1); FUZZ_LOG() << "Instruction " << idx << " avail: " << p.dataAvail() << " pos: " << p.dataPosition() << " cap: " << p.dataCapacity(); if (idx < reads.size()) { reads.at(idx)(p, provider); } else { writes.at(idx - reads.size())(p, provider, &options); } } } } void* NothingClass_onCreate(void* args) { void* NothingClass_onCreate(void* args) { Loading Loading @@ -187,10 +193,14 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { std::move(provider)); std::move(provider)); }, }, [](FuzzedDataProvider&& provider) { [](FuzzedDataProvider&& provider) { doAppendFuzz<::android::Parcel>("binder", std::move(provider)); doReadWriteFuzz<::android::Parcel>("binder", BINDER_PARCEL_READ_FUNCTIONS, BINDER_PARCEL_WRITE_FUNCTIONS, std::move(provider)); }, }, [](FuzzedDataProvider&& provider) { [](FuzzedDataProvider&& provider) { doAppendFuzz<NdkParcelAdapter>("binder_ndk", std::move(provider)); doReadWriteFuzz<NdkParcelAdapter>("binder_ndk", BINDER_NDK_PARCEL_READ_FUNCTIONS, BINDER_NDK_PARCEL_WRITE_FUNCTIONS, std::move(provider)); }, }, }; }; Loading