Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 981dcd46 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Disallow reading object data from Parcels with non-object reads"

parents 88f5ccab f9619dec
Loading
Loading
Loading
Loading
+73 −0
Original line number Diff line number Diff line
@@ -433,6 +433,7 @@ void Parcel::setDataPosition(size_t pos) const

    mDataPos = pos;
    mNextObjectHint = 0;
    mObjectsSorted = false;
}

status_t Parcel::setDataCapacity(size_t size)
@@ -1469,6 +1470,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) {
@@ -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
            && 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);
@@ -1497,6 +1555,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);
@@ -1510,6 +1573,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);
@@ -2366,6 +2434,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++) {
@@ -2524,6 +2593,7 @@ status_t Parcel::restartWrite(size_t desired)
    mObjects = NULL;
    mObjectsSize = mObjectsCapacity = 0;
    mNextObjectHint = 0;
    mObjectsSorted = false;
    mHasFds = false;
    mFdsKnown = true;
    mAllowFds = true;
@@ -2610,6 +2680,7 @@ status_t Parcel::continueWrite(size_t desired)
        mDataCapacity = desired;
        mObjectsSize = mObjectsCapacity = objectsSize;
        mNextObjectHint = 0;
        mObjectsSorted = false;

    } else if (mData) {
        if (objectsSize < mObjectsSize) {
@@ -2631,6 +2702,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().
@@ -2703,6 +2775,7 @@ void Parcel::initState()
    mObjectsSize = 0;
    mObjectsCapacity = 0;
    mNextObjectHint = 0;
    mObjectsSorted = false;
    mHasFds = false;
    mFdsKnown = true;
    mAllowFds = true;
+2 −0
Original line number Diff line number Diff line
@@ -417,6 +417,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;
@@ -463,6 +464,7 @@ private:
    size_t              mObjectsSize;
    size_t              mObjectsCapacity;
    mutable size_t      mNextObjectHint;
    mutable bool        mObjectsSorted;

    mutable bool        mFdsKnown;
    mutable bool        mHasFds;