Loading include/binder/Parcel.h +2 −0 Original line number Diff line number Diff line Loading @@ -375,6 +375,7 @@ private: void freeDataNoInit(); void initState(); void scanForFds() const; status_t validateReadData(size_t len) const; template<class T> status_t readAligned(T *pArg) const; Loading Loading @@ -421,6 +422,7 @@ private: size_t mObjectsSize; size_t mObjectsCapacity; mutable size_t mNextObjectHint; mutable bool mObjectsSorted; mutable bool mFdsKnown; mutable bool mHasFds; Loading libs/binder/Parcel.cpp +73 −0 Original line number Diff line number Diff line Loading @@ -459,6 +459,7 @@ void Parcel::setDataPosition(size_t pos) const mDataPos = pos; mNextObjectHint = 0; mObjectsSorted = false; } status_t Parcel::setDataCapacity(size_t size) Loading Loading @@ -1363,6 +1364,59 @@ void Parcel::remove(size_t /*start*/, size_t /*amt*/) LOG_ALWAYS_FATAL("Parcel::remove() not yet implemented!"); } status_t Parcel::validateReadData(size_t upperBound) const { // Don't allow non-object reads on object data if (mObjectsSorted || mObjectsSize <= 1) { data_sorted: // Expect to check only against the next object if (mNextObjectHint < mObjectsSize && upperBound > mObjects[mNextObjectHint]) { // For some reason the current read position is greater than the next object // hint. Iterate until we find the right object size_t nextObject = mNextObjectHint; do { if (mDataPos < mObjects[nextObject] + sizeof(flat_binder_object)) { // Requested info overlaps with an object ALOGE("Attempt to read from protected data in Parcel %p", this); return PERMISSION_DENIED; } nextObject++; } while (nextObject < mObjectsSize && upperBound > mObjects[nextObject]); mNextObjectHint = nextObject; } return NO_ERROR; } // Quickly determine if mObjects is sorted. binder_size_t* currObj = mObjects + mObjectsSize - 1; binder_size_t* prevObj = currObj; while (currObj > mObjects) { prevObj--; if(*prevObj > *currObj) { goto data_unsorted; } currObj--; } mObjectsSorted = true; goto data_sorted; data_unsorted: // Insertion Sort mObjects // Great for mostly sorted lists. If randomly sorted or reverse ordered mObjects become common, // switch to std::sort(mObjects, mObjects + mObjectsSize); for (binder_size_t* iter0 = mObjects + 1; iter0 < mObjects + mObjectsSize; iter0++) { binder_size_t temp = *iter0; binder_size_t* iter1 = iter0 - 1; while (iter1 >= mObjects && *iter1 > temp) { *(iter1 + 1) = *iter1; iter1--; } *(iter1 + 1) = temp; } mNextObjectHint = 0; mObjectsSorted = true; goto data_sorted; } status_t Parcel::read(void* outData, size_t len) const { if (len > INT32_MAX) { Loading @@ -1373,6 +1427,10 @@ status_t Parcel::read(void* outData, size_t len) const if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize && len <= pad_size(len)) { if (mObjectsSize > 0) { status_t err = validateReadData(mDataPos + pad_size(len)); if(err != NO_ERROR) return err; } memcpy(outData, mData+mDataPos, len); mDataPos += pad_size(len); ALOGV("read Setting data pos of %p to %zu", this, mDataPos); Loading @@ -1391,6 +1449,11 @@ const void* Parcel::readInplace(size_t len) const if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize && len <= pad_size(len)) { if (mObjectsSize > 0) { status_t err = validateReadData(mDataPos + pad_size(len)); if(err != NO_ERROR) return NULL; } const void* data = mData+mDataPos; mDataPos += pad_size(len); ALOGV("readInplace Setting data pos of %p to %zu", this, mDataPos); Loading @@ -1404,6 +1467,11 @@ status_t Parcel::readAligned(T *pArg) const { COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T)); if ((mDataPos+sizeof(T)) <= mDataSize) { if (mObjectsSize > 0) { status_t err = validateReadData(mDataPos + sizeof(T)); if(err != NO_ERROR) return err; } const void* data = mData+mDataPos; mDataPos += sizeof(T); *pArg = *reinterpret_cast<const T*>(data); Loading Loading @@ -2206,6 +2274,7 @@ void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize, mObjects = const_cast<binder_size_t*>(objects); mObjectsSize = mObjectsCapacity = objectsCount; mNextObjectHint = 0; mObjectsSorted = false; mOwner = relFunc; mOwnerCookie = relCookie; for (size_t i = 0; i < mObjectsSize; i++) { Loading Loading @@ -2364,6 +2433,7 @@ status_t Parcel::restartWrite(size_t desired) mObjects = NULL; mObjectsSize = mObjectsCapacity = 0; mNextObjectHint = 0; mObjectsSorted = false; mHasFds = false; mFdsKnown = true; mAllowFds = true; Loading Loading @@ -2450,6 +2520,7 @@ status_t Parcel::continueWrite(size_t desired) mDataCapacity = desired; mObjectsSize = mObjectsCapacity = objectsSize; mNextObjectHint = 0; mObjectsSorted = false; } else if (mData) { if (objectsSize < mObjectsSize) { Loading @@ -2471,6 +2542,7 @@ status_t Parcel::continueWrite(size_t desired) } mObjectsSize = objectsSize; mNextObjectHint = 0; mObjectsSorted = false; } // We own the data, so we can just do a realloc(). Loading Loading @@ -2543,6 +2615,7 @@ void Parcel::initState() mObjectsSize = 0; mObjectsCapacity = 0; mNextObjectHint = 0; mObjectsSorted = false; mHasFds = false; mFdsKnown = true; mAllowFds = true; Loading Loading
include/binder/Parcel.h +2 −0 Original line number Diff line number Diff line Loading @@ -375,6 +375,7 @@ private: void freeDataNoInit(); void initState(); void scanForFds() const; status_t validateReadData(size_t len) const; template<class T> status_t readAligned(T *pArg) const; Loading Loading @@ -421,6 +422,7 @@ private: size_t mObjectsSize; size_t mObjectsCapacity; mutable size_t mNextObjectHint; mutable bool mObjectsSorted; mutable bool mFdsKnown; mutable bool mHasFds; Loading
libs/binder/Parcel.cpp +73 −0 Original line number Diff line number Diff line Loading @@ -459,6 +459,7 @@ void Parcel::setDataPosition(size_t pos) const mDataPos = pos; mNextObjectHint = 0; mObjectsSorted = false; } status_t Parcel::setDataCapacity(size_t size) Loading Loading @@ -1363,6 +1364,59 @@ void Parcel::remove(size_t /*start*/, size_t /*amt*/) LOG_ALWAYS_FATAL("Parcel::remove() not yet implemented!"); } status_t Parcel::validateReadData(size_t upperBound) const { // Don't allow non-object reads on object data if (mObjectsSorted || mObjectsSize <= 1) { data_sorted: // Expect to check only against the next object if (mNextObjectHint < mObjectsSize && upperBound > mObjects[mNextObjectHint]) { // For some reason the current read position is greater than the next object // hint. Iterate until we find the right object size_t nextObject = mNextObjectHint; do { if (mDataPos < mObjects[nextObject] + sizeof(flat_binder_object)) { // Requested info overlaps with an object ALOGE("Attempt to read from protected data in Parcel %p", this); return PERMISSION_DENIED; } nextObject++; } while (nextObject < mObjectsSize && upperBound > mObjects[nextObject]); mNextObjectHint = nextObject; } return NO_ERROR; } // Quickly determine if mObjects is sorted. binder_size_t* currObj = mObjects + mObjectsSize - 1; binder_size_t* prevObj = currObj; while (currObj > mObjects) { prevObj--; if(*prevObj > *currObj) { goto data_unsorted; } currObj--; } mObjectsSorted = true; goto data_sorted; data_unsorted: // Insertion Sort mObjects // Great for mostly sorted lists. If randomly sorted or reverse ordered mObjects become common, // switch to std::sort(mObjects, mObjects + mObjectsSize); for (binder_size_t* iter0 = mObjects + 1; iter0 < mObjects + mObjectsSize; iter0++) { binder_size_t temp = *iter0; binder_size_t* iter1 = iter0 - 1; while (iter1 >= mObjects && *iter1 > temp) { *(iter1 + 1) = *iter1; iter1--; } *(iter1 + 1) = temp; } mNextObjectHint = 0; mObjectsSorted = true; goto data_sorted; } status_t Parcel::read(void* outData, size_t len) const { if (len > INT32_MAX) { Loading @@ -1373,6 +1427,10 @@ status_t Parcel::read(void* outData, size_t len) const if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize && len <= pad_size(len)) { if (mObjectsSize > 0) { status_t err = validateReadData(mDataPos + pad_size(len)); if(err != NO_ERROR) return err; } memcpy(outData, mData+mDataPos, len); mDataPos += pad_size(len); ALOGV("read Setting data pos of %p to %zu", this, mDataPos); Loading @@ -1391,6 +1449,11 @@ const void* Parcel::readInplace(size_t len) const if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize && len <= pad_size(len)) { if (mObjectsSize > 0) { status_t err = validateReadData(mDataPos + pad_size(len)); if(err != NO_ERROR) return NULL; } const void* data = mData+mDataPos; mDataPos += pad_size(len); ALOGV("readInplace Setting data pos of %p to %zu", this, mDataPos); Loading @@ -1404,6 +1467,11 @@ status_t Parcel::readAligned(T *pArg) const { COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T)); if ((mDataPos+sizeof(T)) <= mDataSize) { if (mObjectsSize > 0) { status_t err = validateReadData(mDataPos + sizeof(T)); if(err != NO_ERROR) return err; } const void* data = mData+mDataPos; mDataPos += sizeof(T); *pArg = *reinterpret_cast<const T*>(data); Loading Loading @@ -2206,6 +2274,7 @@ void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize, mObjects = const_cast<binder_size_t*>(objects); mObjectsSize = mObjectsCapacity = objectsCount; mNextObjectHint = 0; mObjectsSorted = false; mOwner = relFunc; mOwnerCookie = relCookie; for (size_t i = 0; i < mObjectsSize; i++) { Loading Loading @@ -2364,6 +2433,7 @@ status_t Parcel::restartWrite(size_t desired) mObjects = NULL; mObjectsSize = mObjectsCapacity = 0; mNextObjectHint = 0; mObjectsSorted = false; mHasFds = false; mFdsKnown = true; mAllowFds = true; Loading Loading @@ -2450,6 +2520,7 @@ status_t Parcel::continueWrite(size_t desired) mDataCapacity = desired; mObjectsSize = mObjectsCapacity = objectsSize; mNextObjectHint = 0; mObjectsSorted = false; } else if (mData) { if (objectsSize < mObjectsSize) { Loading @@ -2471,6 +2542,7 @@ status_t Parcel::continueWrite(size_t desired) } mObjectsSize = objectsSize; mNextObjectHint = 0; mObjectsSorted = false; } // We own the data, so we can just do a realloc(). Loading Loading @@ -2543,6 +2615,7 @@ void Parcel::initState() mObjectsSize = 0; mObjectsCapacity = 0; mNextObjectHint = 0; mObjectsSorted = false; mHasFds = false; mFdsKnown = true; mAllowFds = true; Loading