diff options
| -rw-r--r-- | libs/binder/Parcel.cpp | 41 | ||||
| -rw-r--r-- | libs/binder/include/binder/Parcel.h | 2 | ||||
| -rw-r--r-- | libs/binder/tests/parcel_fuzzer/binder.cpp | 8 |
3 files changed, 41 insertions, 10 deletions
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index 41ca60564a..dee5309602 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -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; @@ -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; } diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h index 3e172d3474..cf30f17015 100644 --- a/libs/binder/include/binder/Parcel.h +++ b/libs/binder/include/binder/Parcel.h @@ -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. @@ -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: diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp index f1fe164c76..55eb847436 100644 --- a/libs/binder/tests/parcel_fuzzer/binder.cpp +++ b/libs/binder/tests/parcel_fuzzer/binder.cpp @@ -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 |