summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/binder/Parcel.cpp41
-rw-r--r--libs/binder/include/binder/Parcel.h2
-rw-r--r--libs/binder/tests/parcel_fuzzer/binder.cpp8
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