Loading libs/binder/Parcel.cpp +73 −0 Original line number Original line Diff line number Diff line Loading @@ -433,6 +433,7 @@ void Parcel::setDataPosition(size_t pos) const mDataPos = pos; mDataPos = pos; mNextObjectHint = 0; mNextObjectHint = 0; mObjectsSorted = false; } } status_t Parcel::setDataCapacity(size_t size) status_t Parcel::setDataCapacity(size_t size) Loading Loading @@ -1469,6 +1470,59 @@ void Parcel::remove(size_t /*start*/, size_t /*amt*/) LOG_ALWAYS_FATAL("Parcel::remove() not yet implemented!"); 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 status_t Parcel::read(void* outData, size_t len) const { { if (len > INT32_MAX) { if (len > INT32_MAX) { Loading @@ -1479,6 +1533,10 @@ status_t Parcel::read(void* outData, size_t len) const if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize && len <= pad_size(len)) { && 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); memcpy(outData, mData+mDataPos, len); mDataPos += pad_size(len); mDataPos += pad_size(len); ALOGV("read Setting data pos of %p to %zu", this, mDataPos); ALOGV("read Setting data pos of %p to %zu", this, mDataPos); Loading @@ -1497,6 +1555,11 @@ const void* Parcel::readInplace(size_t len) const if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize && len <= pad_size(len)) { && 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; const void* data = mData+mDataPos; mDataPos += pad_size(len); mDataPos += pad_size(len); ALOGV("readInplace Setting data pos of %p to %zu", this, mDataPos); ALOGV("readInplace Setting data pos of %p to %zu", this, mDataPos); Loading @@ -1510,6 +1573,11 @@ status_t Parcel::readAligned(T *pArg) const { COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T)); COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T)); if ((mDataPos+sizeof(T)) <= mDataSize) { 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; const void* data = mData+mDataPos; mDataPos += sizeof(T); mDataPos += sizeof(T); *pArg = *reinterpret_cast<const T*>(data); *pArg = *reinterpret_cast<const T*>(data); Loading Loading @@ -2366,6 +2434,7 @@ void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize, mObjects = const_cast<binder_size_t*>(objects); mObjects = const_cast<binder_size_t*>(objects); mObjectsSize = mObjectsCapacity = objectsCount; mObjectsSize = mObjectsCapacity = objectsCount; mNextObjectHint = 0; mNextObjectHint = 0; mObjectsSorted = false; mOwner = relFunc; mOwner = relFunc; mOwnerCookie = relCookie; mOwnerCookie = relCookie; for (size_t i = 0; i < mObjectsSize; i++) { for (size_t i = 0; i < mObjectsSize; i++) { Loading Loading @@ -2524,6 +2593,7 @@ status_t Parcel::restartWrite(size_t desired) mObjects = NULL; mObjects = NULL; mObjectsSize = mObjectsCapacity = 0; mObjectsSize = mObjectsCapacity = 0; mNextObjectHint = 0; mNextObjectHint = 0; mObjectsSorted = false; mHasFds = false; mHasFds = false; mFdsKnown = true; mFdsKnown = true; mAllowFds = true; mAllowFds = true; Loading Loading @@ -2610,6 +2680,7 @@ status_t Parcel::continueWrite(size_t desired) mDataCapacity = desired; mDataCapacity = desired; mObjectsSize = mObjectsCapacity = objectsSize; mObjectsSize = mObjectsCapacity = objectsSize; mNextObjectHint = 0; mNextObjectHint = 0; mObjectsSorted = false; } else if (mData) { } else if (mData) { if (objectsSize < mObjectsSize) { if (objectsSize < mObjectsSize) { Loading @@ -2631,6 +2702,7 @@ status_t Parcel::continueWrite(size_t desired) } } mObjectsSize = objectsSize; mObjectsSize = objectsSize; mNextObjectHint = 0; mNextObjectHint = 0; mObjectsSorted = false; } } // We own the data, so we can just do a realloc(). // We own the data, so we can just do a realloc(). Loading Loading @@ -2703,6 +2775,7 @@ void Parcel::initState() mObjectsSize = 0; mObjectsSize = 0; mObjectsCapacity = 0; mObjectsCapacity = 0; mNextObjectHint = 0; mNextObjectHint = 0; mObjectsSorted = false; mHasFds = false; mHasFds = false; mFdsKnown = true; mFdsKnown = true; mAllowFds = true; mAllowFds = true; Loading libs/binder/include/binder/Parcel.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -417,6 +417,7 @@ private: void freeDataNoInit(); void freeDataNoInit(); void initState(); void initState(); void scanForFds() const; void scanForFds() const; status_t validateReadData(size_t len) const; template<class T> template<class T> status_t readAligned(T *pArg) const; status_t readAligned(T *pArg) const; Loading Loading @@ -463,6 +464,7 @@ private: size_t mObjectsSize; size_t mObjectsSize; size_t mObjectsCapacity; size_t mObjectsCapacity; mutable size_t mNextObjectHint; mutable size_t mNextObjectHint; mutable bool mObjectsSorted; mutable bool mFdsKnown; mutable bool mFdsKnown; mutable bool mHasFds; mutable bool mHasFds; Loading Loading
libs/binder/Parcel.cpp +73 −0 Original line number Original line Diff line number Diff line Loading @@ -433,6 +433,7 @@ void Parcel::setDataPosition(size_t pos) const mDataPos = pos; mDataPos = pos; mNextObjectHint = 0; mNextObjectHint = 0; mObjectsSorted = false; } } status_t Parcel::setDataCapacity(size_t size) status_t Parcel::setDataCapacity(size_t size) Loading Loading @@ -1469,6 +1470,59 @@ void Parcel::remove(size_t /*start*/, size_t /*amt*/) LOG_ALWAYS_FATAL("Parcel::remove() not yet implemented!"); 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 status_t Parcel::read(void* outData, size_t len) const { { if (len > INT32_MAX) { if (len > INT32_MAX) { Loading @@ -1479,6 +1533,10 @@ status_t Parcel::read(void* outData, size_t len) const if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize && len <= pad_size(len)) { && 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); memcpy(outData, mData+mDataPos, len); mDataPos += pad_size(len); mDataPos += pad_size(len); ALOGV("read Setting data pos of %p to %zu", this, mDataPos); ALOGV("read Setting data pos of %p to %zu", this, mDataPos); Loading @@ -1497,6 +1555,11 @@ const void* Parcel::readInplace(size_t len) const if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize && len <= pad_size(len)) { && 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; const void* data = mData+mDataPos; mDataPos += pad_size(len); mDataPos += pad_size(len); ALOGV("readInplace Setting data pos of %p to %zu", this, mDataPos); ALOGV("readInplace Setting data pos of %p to %zu", this, mDataPos); Loading @@ -1510,6 +1573,11 @@ status_t Parcel::readAligned(T *pArg) const { COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T)); COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T)); if ((mDataPos+sizeof(T)) <= mDataSize) { 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; const void* data = mData+mDataPos; mDataPos += sizeof(T); mDataPos += sizeof(T); *pArg = *reinterpret_cast<const T*>(data); *pArg = *reinterpret_cast<const T*>(data); Loading Loading @@ -2366,6 +2434,7 @@ void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize, mObjects = const_cast<binder_size_t*>(objects); mObjects = const_cast<binder_size_t*>(objects); mObjectsSize = mObjectsCapacity = objectsCount; mObjectsSize = mObjectsCapacity = objectsCount; mNextObjectHint = 0; mNextObjectHint = 0; mObjectsSorted = false; mOwner = relFunc; mOwner = relFunc; mOwnerCookie = relCookie; mOwnerCookie = relCookie; for (size_t i = 0; i < mObjectsSize; i++) { for (size_t i = 0; i < mObjectsSize; i++) { Loading Loading @@ -2524,6 +2593,7 @@ status_t Parcel::restartWrite(size_t desired) mObjects = NULL; mObjects = NULL; mObjectsSize = mObjectsCapacity = 0; mObjectsSize = mObjectsCapacity = 0; mNextObjectHint = 0; mNextObjectHint = 0; mObjectsSorted = false; mHasFds = false; mHasFds = false; mFdsKnown = true; mFdsKnown = true; mAllowFds = true; mAllowFds = true; Loading Loading @@ -2610,6 +2680,7 @@ status_t Parcel::continueWrite(size_t desired) mDataCapacity = desired; mDataCapacity = desired; mObjectsSize = mObjectsCapacity = objectsSize; mObjectsSize = mObjectsCapacity = objectsSize; mNextObjectHint = 0; mNextObjectHint = 0; mObjectsSorted = false; } else if (mData) { } else if (mData) { if (objectsSize < mObjectsSize) { if (objectsSize < mObjectsSize) { Loading @@ -2631,6 +2702,7 @@ status_t Parcel::continueWrite(size_t desired) } } mObjectsSize = objectsSize; mObjectsSize = objectsSize; mNextObjectHint = 0; mNextObjectHint = 0; mObjectsSorted = false; } } // We own the data, so we can just do a realloc(). // We own the data, so we can just do a realloc(). Loading Loading @@ -2703,6 +2775,7 @@ void Parcel::initState() mObjectsSize = 0; mObjectsSize = 0; mObjectsCapacity = 0; mObjectsCapacity = 0; mNextObjectHint = 0; mNextObjectHint = 0; mObjectsSorted = false; mHasFds = false; mHasFds = false; mFdsKnown = true; mFdsKnown = true; mAllowFds = true; mAllowFds = true; Loading
libs/binder/include/binder/Parcel.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -417,6 +417,7 @@ private: void freeDataNoInit(); void freeDataNoInit(); void initState(); void initState(); void scanForFds() const; void scanForFds() const; status_t validateReadData(size_t len) const; template<class T> template<class T> status_t readAligned(T *pArg) const; status_t readAligned(T *pArg) const; Loading Loading @@ -463,6 +464,7 @@ private: size_t mObjectsSize; size_t mObjectsSize; size_t mObjectsCapacity; size_t mObjectsCapacity; mutable size_t mNextObjectHint; mutable size_t mNextObjectHint; mutable bool mObjectsSorted; mutable bool mFdsKnown; mutable bool mFdsKnown; mutable bool mHasFds; mutable bool mHasFds; Loading