From fdc01250e0ffbb44a9a93e1807742e855acd766e Mon Sep 17 00:00:00 2001 From: Jeff Tinker Date: Thu, 19 Apr 2018 16:23:21 -0700 Subject: [PATCH] Fix security vulnerability in CryptoHal CryptoHal was not checking that the memory heap set by setHeap was the same one that was actually used for the decrypt call, allowing the caller to spoof the decrypt call into accessing arbitrary memory. bug:76221123 test: mediadrmserverpoc included in the bug & GTS media tests Change-Id: I35214a1a6d0a4b864123e147d1a1adc2377bfbc5 Merged-in: I4ae6d1080be406bf53e3617c59c75206cc5066c6 (cherry picked from commit 9a9c3ab4d76f03f3abb3756bca9cdfe55c74326a) --- drm/libmediadrm/CryptoHal.cpp | 25 +++++++++++++++++++++---- media/libmedia/include/media/CryptoHal.h | 15 ++++++++++++++- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp index 1fdc6e1954..5dd25639ca 100644 --- a/drm/libmediadrm/CryptoHal.cpp +++ b/drm/libmediadrm/CryptoHal.cpp @@ -240,11 +240,12 @@ int32_t CryptoHal::setHeapBase(const sp& heap) { Mutex::Autolock autoLock(mLock); int32_t seqNum = mHeapSeqNum++; + int fd = heap->getHeapID(); nativeHandle->data[0] = fd; auto hidlHandle = hidl_handle(nativeHandle); auto hidlMemory = hidl_memory("ashmem", hidlHandle, heap->getSize()); - mHeapBases.add(seqNum, mNextBufferId); + mHeapBases.add(seqNum, HeapBase(mNextBufferId, heap->getSize())); Return hResult = mPlugin->setSharedBufferBase(hidlMemory, mNextBufferId++); ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed"); return seqNum; @@ -269,10 +270,26 @@ status_t CryptoHal::toSharedBuffer(const sp& memory, int32_t seqNum, :: return UNEXPECTED_NULL; } - // memory must be in the declared heap - CHECK(mHeapBases.indexOfKey(seqNum) >= 0); + // memory must be in one of the heaps that have been set + if (mHeapBases.indexOfKey(seqNum) < 0) { + return UNKNOWN_ERROR; + } + + // heap must be the same size as the one that was set in setHeapBase + if (mHeapBases.valueFor(seqNum).getSize() != heap->getSize()) { + android_errorWriteLog(0x534e4554, "76221123"); + return UNKNOWN_ERROR; + } + + // memory must be within the address space of the heap + if (memory->pointer() != static_cast(heap->getBase()) + memory->offset() || + heap->getSize() < memory->offset() + memory->size() || + SIZE_MAX - memory->offset() < memory->size()) { + android_errorWriteLog(0x534e4554, "76221123"); + return UNKNOWN_ERROR; + } - buffer->bufferId = mHeapBases.valueFor(seqNum); + buffer->bufferId = mHeapBases.valueFor(seqNum).getBufferId(); buffer->offset = offset >= 0 ? offset : 0; buffer->size = size; return OK; diff --git a/media/libmedia/include/media/CryptoHal.h b/media/libmedia/include/media/CryptoHal.h index a5d8b43aec..80e181e57b 100644 --- a/media/libmedia/include/media/CryptoHal.h +++ b/media/libmedia/include/media/CryptoHal.h @@ -79,7 +79,20 @@ private: */ status_t mInitCheck; - KeyedVector mHeapBases; + struct HeapBase { + HeapBase() : mBufferId(0), mSize(0) {} + HeapBase(uint32_t bufferId, size_t size) : + mBufferId(bufferId), mSize(size) {} + + uint32_t getBufferId() const {return mBufferId;} + size_t getSize() const {return mSize;} + + private: + uint32_t mBufferId; + size_t mSize; + }; + + KeyedVector mHeapBases; uint32_t mNextBufferId; int32_t mHeapSeqNum; -- 2.11.0