Loading libs/binder/Parcel.cpp +31 −10 Original line number Diff line number Diff line Loading @@ -547,6 +547,36 @@ bool Parcel::hasFileDescriptors() const return mHasFds; } status_t Parcel::hasFileDescriptorsInRange(size_t offset, size_t len, bool& result) const { if (len > INT32_MAX || offset > INT32_MAX) { // Don't accept size_t values which may have come from an inadvertent conversion from a // negative int. return BAD_VALUE; } size_t limit = offset + len; if (offset > mDataSize || len > mDataSize || limit > mDataSize || offset > limit) { return BAD_VALUE; } result = hasFileDescriptorsInRangeUnchecked(offset, len); return NO_ERROR; } bool Parcel::hasFileDescriptorsInRangeUnchecked(size_t offset, size_t len) const { for (size_t i = 0; i < mObjectsSize; i++) { size_t pos = mObjects[i]; if (pos < offset) continue; if (pos + sizeof(flat_binder_object) > offset + len) { if (mObjectsSorted) break; else continue; } const flat_binder_object* flat = reinterpret_cast<const flat_binder_object*>(mData + pos); if (flat->hdr.type == BINDER_TYPE_FD) { return true; } } return false; } void Parcel::markSensitive() const { mDeallocZero = true; Loading Loading @@ -2539,16 +2569,7 @@ void Parcel::initState() void Parcel::scanForFds() const { bool hasFds = false; for (size_t i=0; i<mObjectsSize; i++) { const flat_binder_object* flat = reinterpret_cast<const flat_binder_object*>(mData + mObjects[i]); if (flat->hdr.type == BINDER_TYPE_FD) { hasFds = true; break; } } mHasFds = hasFds; mHasFds = hasFileDescriptorsInRangeUnchecked(0, dataSize()); mFdsKnown = true; } Loading libs/binder/include/binder/Parcel.h +2 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,7 @@ public: void restoreAllowFds(bool lastValue); bool hasFileDescriptors() const; status_t hasFileDescriptorsInRange(size_t offset, size_t length, bool& result) const; // Zeros data when reallocating. Other mitigations may be added // in the future. Loading Loading @@ -575,6 +576,7 @@ private: status_t writeRawNullableParcelable(const Parcelable* parcelable); bool hasFileDescriptorsInRangeUnchecked(size_t offset, size_t length) const; //----------------------------------------------------------------------------- // Generic type read and write methods for Parcel: Loading libs/binder/tests/parcel_fuzzer/binder.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -301,6 +301,14 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { FUZZ_LOG() << "ParcelableHolder status: " << status; }, PARCEL_READ_WITH_STATUS(android::os::PersistableBundle, readParcelable), [] (const ::android::Parcel& p, uint8_t /* data */) { FUZZ_LOG() << "about to call hasFileDescriptorsInRange() with status"; size_t offset = p.readUint32(); size_t length = p.readUint32(); bool result; status_t status = p.hasFileDescriptorsInRange(offset, length, result); FUZZ_LOG() << " status: " << status << " result: " << result; }, }; // clang-format on #pragma clang diagnostic pop Loading
libs/binder/Parcel.cpp +31 −10 Original line number Diff line number Diff line Loading @@ -547,6 +547,36 @@ bool Parcel::hasFileDescriptors() const return mHasFds; } status_t Parcel::hasFileDescriptorsInRange(size_t offset, size_t len, bool& result) const { if (len > INT32_MAX || offset > INT32_MAX) { // Don't accept size_t values which may have come from an inadvertent conversion from a // negative int. return BAD_VALUE; } size_t limit = offset + len; if (offset > mDataSize || len > mDataSize || limit > mDataSize || offset > limit) { return BAD_VALUE; } result = hasFileDescriptorsInRangeUnchecked(offset, len); return NO_ERROR; } bool Parcel::hasFileDescriptorsInRangeUnchecked(size_t offset, size_t len) const { for (size_t i = 0; i < mObjectsSize; i++) { size_t pos = mObjects[i]; if (pos < offset) continue; if (pos + sizeof(flat_binder_object) > offset + len) { if (mObjectsSorted) break; else continue; } const flat_binder_object* flat = reinterpret_cast<const flat_binder_object*>(mData + pos); if (flat->hdr.type == BINDER_TYPE_FD) { return true; } } return false; } void Parcel::markSensitive() const { mDeallocZero = true; Loading Loading @@ -2539,16 +2569,7 @@ void Parcel::initState() void Parcel::scanForFds() const { bool hasFds = false; for (size_t i=0; i<mObjectsSize; i++) { const flat_binder_object* flat = reinterpret_cast<const flat_binder_object*>(mData + mObjects[i]); if (flat->hdr.type == BINDER_TYPE_FD) { hasFds = true; break; } } mHasFds = hasFds; mHasFds = hasFileDescriptorsInRangeUnchecked(0, dataSize()); mFdsKnown = true; } Loading
libs/binder/include/binder/Parcel.h +2 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,7 @@ public: void restoreAllowFds(bool lastValue); bool hasFileDescriptors() const; status_t hasFileDescriptorsInRange(size_t offset, size_t length, bool& result) const; // Zeros data when reallocating. Other mitigations may be added // in the future. Loading Loading @@ -575,6 +576,7 @@ private: status_t writeRawNullableParcelable(const Parcelable* parcelable); bool hasFileDescriptorsInRangeUnchecked(size_t offset, size_t length) const; //----------------------------------------------------------------------------- // Generic type read and write methods for Parcel: Loading
libs/binder/tests/parcel_fuzzer/binder.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -301,6 +301,14 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { FUZZ_LOG() << "ParcelableHolder status: " << status; }, PARCEL_READ_WITH_STATUS(android::os::PersistableBundle, readParcelable), [] (const ::android::Parcel& p, uint8_t /* data */) { FUZZ_LOG() << "about to call hasFileDescriptorsInRange() with status"; size_t offset = p.readUint32(); size_t length = p.readUint32(); bool result; status_t status = p.hasFileDescriptorsInRange(offset, length, result); FUZZ_LOG() << " status: " << status << " result: " << result; }, }; // clang-format on #pragma clang diagnostic pop