Loading libs/binder/Parcel.cpp +47 −14 Original line number Diff line number Diff line Loading @@ -947,7 +947,10 @@ bool Parcel::enforceInterface(const char16_t* interface, threadState->setCallingWorkSourceUidWithoutPropagation(workSource); // vendor header int32_t header = readInt32(); if (header != kHeader) { // fuzzers skip this check, because it is for protecting the underlying ABI, but // we don't want it to reduce our coverage if (header != kHeader && !mServiceFuzzing) { ALOGE("Expecting header 0x%x but found 0x%x. Mixing copies of libbinder?", kHeader, header); return false; Loading @@ -965,6 +968,13 @@ bool Parcel::enforceInterface(const char16_t* interface, if (len == parcel_interface_len && (!len || !memcmp(parcel_interface, interface, len * sizeof (char16_t)))) { return true; } else { if (mServiceFuzzing) { // ignore. Theoretically, this could cause a few false positives, because // people could assume things about getInterfaceDescriptor if they pass // this point, but it would be extremely fragile. It's more important that // we fuzz with the above things read from the Parcel. return true; } else { ALOGW("**** enforceInterface() expected '%s' but read '%s'", String8(interface, len).string(), Loading @@ -972,11 +982,16 @@ bool Parcel::enforceInterface(const char16_t* interface, return false; } } } void Parcel::setEnforceNoDataAvail(bool enforceNoDataAvail) { mEnforceNoDataAvail = enforceNoDataAvail; } void Parcel::setServiceFuzzing() { mServiceFuzzing = true; } binder::Status Parcel::enforceNoDataAvail() const { if (!mEnforceNoDataAvail) { return binder::Status::ok(); Loading Loading @@ -1722,7 +1737,9 @@ status_t Parcel::validateReadData(size_t upperBound) const do { if (mDataPos < kernelFields->mObjects[nextObject] + sizeof(flat_binder_object)) { // Requested info overlaps with an object if (!mServiceFuzzing) { ALOGE("Attempt to read from protected data in Parcel %p", this); } return PERMISSION_DENIED; } nextObject++; Loading Loading @@ -2092,7 +2109,11 @@ String8 Parcel::readString8() const size_t len; const char* str = readString8Inplace(&len); if (str) return String8(str, len); if (!mServiceFuzzing) { ALOGE("Reading a NULL string not supported here."); } return String8(); } Loading Loading @@ -2132,7 +2153,11 @@ String16 Parcel::readString16() const size_t len; const char16_t* str = readString16Inplace(&len); if (str) return String16(str, len); if (!mServiceFuzzing) { ALOGE("Reading a NULL string not supported here."); } return String16(); } Loading Loading @@ -2172,7 +2197,9 @@ status_t Parcel::readStrongBinder(sp<IBinder>* val) const { status_t status = readNullableStrongBinder(val); if (status == OK && !val->get()) { if (!mServiceFuzzing) { ALOGW("Expecting binder but got null!"); } status = UNEXPECTED_NULL; } return status; Loading Loading @@ -2237,9 +2264,11 @@ int Parcel::readFileDescriptor() const { if (const auto* rpcFields = maybeRpcFields()) { if (!std::binary_search(rpcFields->mObjectPositions.begin(), rpcFields->mObjectPositions.end(), mDataPos)) { ALOGW("Attempt to read file descriptor from Parcel %p at offset %zu that is not in the " "object list", if (!mServiceFuzzing) { ALOGW("Attempt to read file descriptor from Parcel %p at offset %zu that is not in " "the object list", this, mDataPos); } return BAD_TYPE; } Loading Loading @@ -2497,9 +2526,12 @@ const flat_binder_object* Parcel::readObject(bool nullMetaData) const return obj; } } ALOGW("Attempt to read object from Parcel %p at offset %zu that is not in the object list", if (!mServiceFuzzing) { ALOGW("Attempt to read object from Parcel %p at offset %zu that is not in the object " "list", this, DPOS); } } return nullptr; } #endif // BINDER_WITH_KERNEL_IPC Loading Loading @@ -3093,6 +3125,7 @@ void Parcel::initState() mDeallocZero = false; mOwner = nullptr; mEnforceNoDataAvail = true; mServiceFuzzing = false; } void Parcel::scanForFds() const { Loading libs/binder/include/binder/Parcel.h +5 −0 Original line number Diff line number Diff line Loading @@ -149,6 +149,10 @@ public: // This Api is used by fuzzers to skip dataAvail checks. void setEnforceNoDataAvail(bool enforceNoDataAvail); // When fuzzing, we want to remove certain ABI checks that cause significant // lost coverage, and we also want to avoid logs that cost too much to write. void setServiceFuzzing(); void freeData(); size_t objectsCount() const; Loading Loading @@ -1330,6 +1334,7 @@ private: // Set this to false to skip dataAvail checks. bool mEnforceNoDataAvail; bool mServiceFuzzing; release_func mOwner; Loading libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -52,7 +52,8 @@ void fuzzService(const std::vector<sp<IBinder>>& binders, FuzzedDataProvider&& p uint32_t flags = provider.ConsumeIntegral<uint32_t>(); Parcel data; // for increased fuzz coverage data.setEnforceNoDataAvail(provider.ConsumeBool()); data.setEnforceNoDataAvail(false); data.setServiceFuzzing(); sp<IBinder> target = options.extraBinders.at( provider.ConsumeIntegralInRange<size_t>(0, Loading @@ -73,7 +74,8 @@ void fuzzService(const std::vector<sp<IBinder>>& binders, FuzzedDataProvider&& p Parcel reply; // for increased fuzz coverage reply.setEnforceNoDataAvail(provider.ConsumeBool()); reply.setEnforceNoDataAvail(false); reply.setServiceFuzzing(); (void)target->transact(code, data, &reply, flags); // feed back in binders and fds that are returned from the service, so that Loading Loading
libs/binder/Parcel.cpp +47 −14 Original line number Diff line number Diff line Loading @@ -947,7 +947,10 @@ bool Parcel::enforceInterface(const char16_t* interface, threadState->setCallingWorkSourceUidWithoutPropagation(workSource); // vendor header int32_t header = readInt32(); if (header != kHeader) { // fuzzers skip this check, because it is for protecting the underlying ABI, but // we don't want it to reduce our coverage if (header != kHeader && !mServiceFuzzing) { ALOGE("Expecting header 0x%x but found 0x%x. Mixing copies of libbinder?", kHeader, header); return false; Loading @@ -965,6 +968,13 @@ bool Parcel::enforceInterface(const char16_t* interface, if (len == parcel_interface_len && (!len || !memcmp(parcel_interface, interface, len * sizeof (char16_t)))) { return true; } else { if (mServiceFuzzing) { // ignore. Theoretically, this could cause a few false positives, because // people could assume things about getInterfaceDescriptor if they pass // this point, but it would be extremely fragile. It's more important that // we fuzz with the above things read from the Parcel. return true; } else { ALOGW("**** enforceInterface() expected '%s' but read '%s'", String8(interface, len).string(), Loading @@ -972,11 +982,16 @@ bool Parcel::enforceInterface(const char16_t* interface, return false; } } } void Parcel::setEnforceNoDataAvail(bool enforceNoDataAvail) { mEnforceNoDataAvail = enforceNoDataAvail; } void Parcel::setServiceFuzzing() { mServiceFuzzing = true; } binder::Status Parcel::enforceNoDataAvail() const { if (!mEnforceNoDataAvail) { return binder::Status::ok(); Loading Loading @@ -1722,7 +1737,9 @@ status_t Parcel::validateReadData(size_t upperBound) const do { if (mDataPos < kernelFields->mObjects[nextObject] + sizeof(flat_binder_object)) { // Requested info overlaps with an object if (!mServiceFuzzing) { ALOGE("Attempt to read from protected data in Parcel %p", this); } return PERMISSION_DENIED; } nextObject++; Loading Loading @@ -2092,7 +2109,11 @@ String8 Parcel::readString8() const size_t len; const char* str = readString8Inplace(&len); if (str) return String8(str, len); if (!mServiceFuzzing) { ALOGE("Reading a NULL string not supported here."); } return String8(); } Loading Loading @@ -2132,7 +2153,11 @@ String16 Parcel::readString16() const size_t len; const char16_t* str = readString16Inplace(&len); if (str) return String16(str, len); if (!mServiceFuzzing) { ALOGE("Reading a NULL string not supported here."); } return String16(); } Loading Loading @@ -2172,7 +2197,9 @@ status_t Parcel::readStrongBinder(sp<IBinder>* val) const { status_t status = readNullableStrongBinder(val); if (status == OK && !val->get()) { if (!mServiceFuzzing) { ALOGW("Expecting binder but got null!"); } status = UNEXPECTED_NULL; } return status; Loading Loading @@ -2237,9 +2264,11 @@ int Parcel::readFileDescriptor() const { if (const auto* rpcFields = maybeRpcFields()) { if (!std::binary_search(rpcFields->mObjectPositions.begin(), rpcFields->mObjectPositions.end(), mDataPos)) { ALOGW("Attempt to read file descriptor from Parcel %p at offset %zu that is not in the " "object list", if (!mServiceFuzzing) { ALOGW("Attempt to read file descriptor from Parcel %p at offset %zu that is not in " "the object list", this, mDataPos); } return BAD_TYPE; } Loading Loading @@ -2497,9 +2526,12 @@ const flat_binder_object* Parcel::readObject(bool nullMetaData) const return obj; } } ALOGW("Attempt to read object from Parcel %p at offset %zu that is not in the object list", if (!mServiceFuzzing) { ALOGW("Attempt to read object from Parcel %p at offset %zu that is not in the object " "list", this, DPOS); } } return nullptr; } #endif // BINDER_WITH_KERNEL_IPC Loading Loading @@ -3093,6 +3125,7 @@ void Parcel::initState() mDeallocZero = false; mOwner = nullptr; mEnforceNoDataAvail = true; mServiceFuzzing = false; } void Parcel::scanForFds() const { Loading
libs/binder/include/binder/Parcel.h +5 −0 Original line number Diff line number Diff line Loading @@ -149,6 +149,10 @@ public: // This Api is used by fuzzers to skip dataAvail checks. void setEnforceNoDataAvail(bool enforceNoDataAvail); // When fuzzing, we want to remove certain ABI checks that cause significant // lost coverage, and we also want to avoid logs that cost too much to write. void setServiceFuzzing(); void freeData(); size_t objectsCount() const; Loading Loading @@ -1330,6 +1334,7 @@ private: // Set this to false to skip dataAvail checks. bool mEnforceNoDataAvail; bool mServiceFuzzing; release_func mOwner; Loading
libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -52,7 +52,8 @@ void fuzzService(const std::vector<sp<IBinder>>& binders, FuzzedDataProvider&& p uint32_t flags = provider.ConsumeIntegral<uint32_t>(); Parcel data; // for increased fuzz coverage data.setEnforceNoDataAvail(provider.ConsumeBool()); data.setEnforceNoDataAvail(false); data.setServiceFuzzing(); sp<IBinder> target = options.extraBinders.at( provider.ConsumeIntegralInRange<size_t>(0, Loading @@ -73,7 +74,8 @@ void fuzzService(const std::vector<sp<IBinder>>& binders, FuzzedDataProvider&& p Parcel reply; // for increased fuzz coverage reply.setEnforceNoDataAvail(provider.ConsumeBool()); reply.setEnforceNoDataAvail(false); reply.setServiceFuzzing(); (void)target->transact(code, data, &reply, flags); // feed back in binders and fds that are returned from the service, so that Loading