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

Commit de722e56 authored by Christopher Ferris's avatar Christopher Ferris
Browse files

Fix write past end of memory.

The computed flattened size of the blob does not match the size used by the
flatten function when the last cached entry size is not 4 byte aligned.

Bug: 17873145
Change-Id: I9f9fc102d4bde4681ae977b6de5f263aaaf56708
parent c263e671
Loading
Loading
Loading
Loading
+9 −9
Original line number Original line Diff line number Diff line
@@ -31,7 +31,7 @@ namespace android {
static const uint32_t blobCacheMagic = ('_' << 24) + ('B' << 16) + ('b' << 8) + '$';
static const uint32_t blobCacheMagic = ('_' << 24) + ('B' << 16) + ('b' << 8) + '$';


// BlobCache::Header::mBlobCacheVersion value
// BlobCache::Header::mBlobCacheVersion value
static const uint32_t blobCacheVersion = 1;
static const uint32_t blobCacheVersion = 2;


// BlobCache::Header::mDeviceVersion value
// BlobCache::Header::mDeviceVersion value
static const uint32_t blobCacheDeviceVersion = 1;
static const uint32_t blobCacheDeviceVersion = 1;
@@ -165,14 +165,13 @@ static inline size_t align4(size_t size) {
}
}


size_t BlobCache::getFlattenedSize() const {
size_t BlobCache::getFlattenedSize() const {
    size_t size = sizeof(Header);
    size_t size = align4(sizeof(Header));
    for (size_t i = 0; i < mCacheEntries.size(); i++) {
    for (size_t i = 0; i < mCacheEntries.size(); i++) {
        const CacheEntry& e(mCacheEntries[i]);
        const CacheEntry& e(mCacheEntries[i]);
        sp<Blob> keyBlob = e.getKey();
        sp<Blob> keyBlob = e.getKey();
        sp<Blob> valueBlob = e.getValue();
        sp<Blob> valueBlob = e.getValue();
        size = align4(size);
        size += align4(sizeof(EntryHeader) + keyBlob->getSize() +
        size += sizeof(EntryHeader) + keyBlob->getSize() +
                       valueBlob->getSize());
                valueBlob->getSize();
    }
    }
    return size;
    return size;
}
}
@@ -200,7 +199,8 @@ status_t BlobCache::flatten(void* buffer, size_t size) const {
        size_t valueSize = valueBlob->getSize();
        size_t valueSize = valueBlob->getSize();


        size_t entrySize = sizeof(EntryHeader) + keySize + valueSize;
        size_t entrySize = sizeof(EntryHeader) + keySize + valueSize;
        if (byteOffset + entrySize > size) {
        size_t totalSize = align4(entrySize);
        if (byteOffset + totalSize > size) {
            ALOGE("flatten: not enough room for cache entries");
            ALOGE("flatten: not enough room for cache entries");
            return BAD_VALUE;
            return BAD_VALUE;
        }
        }
@@ -213,7 +213,6 @@ status_t BlobCache::flatten(void* buffer, size_t size) const {
        memcpy(eheader->mData, keyBlob->getData(), keySize);
        memcpy(eheader->mData, keyBlob->getData(), keySize);
        memcpy(eheader->mData + keySize, valueBlob->getData(), valueSize);
        memcpy(eheader->mData + keySize, valueBlob->getData(), valueSize);


        size_t totalSize = align4(entrySize);
        if (totalSize > entrySize) {
        if (totalSize > entrySize) {
            // We have padding bytes. Those will get written to storage, and contribute to the CRC,
            // We have padding bytes. Those will get written to storage, and contribute to the CRC,
            // so make sure we zero-them to have reproducible results.
            // so make sure we zero-them to have reproducible results.
@@ -263,7 +262,8 @@ status_t BlobCache::unflatten(void const* buffer, size_t size) {
        size_t valueSize = eheader->mValueSize;
        size_t valueSize = eheader->mValueSize;
        size_t entrySize = sizeof(EntryHeader) + keySize + valueSize;
        size_t entrySize = sizeof(EntryHeader) + keySize + valueSize;


        if (byteOffset + entrySize > size) {
        size_t totalSize = align4(entrySize);
        if (byteOffset + totalSize > size) {
            mCacheEntries.clear();
            mCacheEntries.clear();
            ALOGE("unflatten: not enough room for cache entry headers");
            ALOGE("unflatten: not enough room for cache entry headers");
            return BAD_VALUE;
            return BAD_VALUE;
@@ -272,7 +272,7 @@ status_t BlobCache::unflatten(void const* buffer, size_t size) {
        const uint8_t* data = eheader->mData;
        const uint8_t* data = eheader->mData;
        set(data, keySize, data + keySize, valueSize);
        set(data, keySize, data + keySize, valueSize);


        byteOffset += align4(entrySize);
        byteOffset += totalSize;
    }
    }


    return OK;
    return OK;