diff options
author | 2021-10-15 14:54:30 +0100 | |
---|---|---|
committer | 2021-10-20 19:06:27 +0100 | |
commit | bbbd88da9df06775cff60c7809239f17071c7e66 (patch) | |
tree | 1837b1da469a9601615face2d222de13ed9543ce | |
parent | d8b3d5f05695af40955c2d3e1d40c51db437f977 (diff) |
Fix offset check in Parcel::hasFileDescriptorsInRange()
We should throw if the offset is equals to the data size since it's
zero-indexed.
Test: atest -d android.os.cts.ParcelTest
Change-Id: Ie93b6073ed9383ce8e0deeb78ffb50246fb5c3be
-rw-r--r-- | libs/binder/Parcel.cpp | 23 | ||||
-rw-r--r-- | libs/binder/include/binder/Parcel.h | 3 | ||||
-rw-r--r-- | libs/binder/tests/parcel_fuzzer/binder.cpp | 2 |
3 files changed, 12 insertions, 16 deletions
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index dee5309602..7bb4e3e37f 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -547,21 +547,17 @@ bool Parcel::hasFileDescriptors() const return mHasFds; } -status_t Parcel::hasFileDescriptorsInRange(size_t offset, size_t len, bool& result) const { +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) { + size_t limit; + if (__builtin_add_overflow(offset, len, &limit) || limit > mDataSize) { return BAD_VALUE; } - result = hasFileDescriptorsInRangeUnchecked(offset, len); - return NO_ERROR; -} - -bool Parcel::hasFileDescriptorsInRangeUnchecked(size_t offset, size_t len) const { + *result = false; for (size_t i = 0; i < mObjectsSize; i++) { size_t pos = mObjects[i]; if (pos < offset) continue; @@ -571,10 +567,11 @@ bool Parcel::hasFileDescriptorsInRangeUnchecked(size_t offset, size_t len) const } const flat_binder_object* flat = reinterpret_cast<const flat_binder_object*>(mData + pos); if (flat->hdr.type == BINDER_TYPE_FD) { - return true; + *result = true; + break; } } - return false; + return NO_ERROR; } void Parcel::markSensitive() const @@ -2567,9 +2564,9 @@ void Parcel::initState() } } -void Parcel::scanForFds() const -{ - mHasFds = hasFileDescriptorsInRangeUnchecked(0, dataSize()); +void Parcel::scanForFds() const { + status_t status = hasFileDescriptorsInRange(0, dataSize(), &mHasFds); + ALOGE_IF(status != NO_ERROR, "Error %d calling hasFileDescriptorsInRange()", status); mFdsKnown = true; } diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h index cf30f17015..295c194099 100644 --- a/libs/binder/include/binder/Parcel.h +++ b/libs/binder/include/binder/Parcel.h @@ -87,7 +87,7 @@ public: void restoreAllowFds(bool lastValue); bool hasFileDescriptors() const; - status_t hasFileDescriptorsInRange(size_t offset, size_t length, bool& result) 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. @@ -576,7 +576,6 @@ 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 55eb847436..d09af3f408 100644 --- a/libs/binder/tests/parcel_fuzzer/binder.cpp +++ b/libs/binder/tests/parcel_fuzzer/binder.cpp @@ -306,7 +306,7 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { size_t offset = p.readUint32(); size_t length = p.readUint32(); bool result; - status_t status = p.hasFileDescriptorsInRange(offset, length, result); + status_t status = p.hasFileDescriptorsInRange(offset, length, &result); FUZZ_LOG() << " status: " << status << " result: " << result; }, }; |