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

Commit bf628da1 authored by Chong Zhang's avatar Chong Zhang
Browse files

DRM: more fixes for heap base mapping

Heap base for the same heap could be mapped to different values
after they go across binder to CryptoHal. So we can't use heapbase
to index the heaps.

Since each ACodec instance allocates all its shared memory buffers
from the same memory dealer, we let CryptoHal assign a sequence
number to the ACodec when it calls setHeap. In subsequent calls
to CryptoHal::decrypt, reference the heap by the seq num, and ignore
the heap base address.

Bug: 36479980
Bug: 36209723
Bug: 36660223

Test: the above bugs don't repro

Change-Id: I2f519a689a5891447385d1bf9d6e668bb3b4dbe2
parent 6aa5c066
Loading
Loading
Loading
Loading
+25 −16
Original line number Diff line number Diff line
@@ -105,7 +105,8 @@ static String8 toString8(hidl_string hString) {
CryptoHal::CryptoHal()
    : mFactories(makeCryptoFactories()),
      mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT),
      mNextBufferId(0) {
      mNextBufferId(0),
      mHeapSeqNum(0) {
}

CryptoHal::~CryptoHal() {
@@ -225,30 +226,37 @@ bool CryptoHal::requiresSecureDecoderComponent(const char *mime) const {
 * size.  Once the heap base is established, shared memory buffers
 * are sent by providing an offset into the heap and a buffer size.
 */
void CryptoHal::setHeapBase(const sp<IMemoryHeap>& heap) {
int32_t CryptoHal::setHeapBase(const sp<IMemoryHeap>& heap) {
    if (heap == NULL) {
        ALOGE("setHeapBase(): heap is NULL");
        return -1;
    }
    native_handle_t* nativeHandle = native_handle_create(1, 0);
    if (!nativeHandle) {
        ALOGE("setHeapBase(), failed to create native handle");
        return;
    }
    if (heap == NULL) {
        ALOGE("setHeapBase(): heap is NULL");
        return;
        return -1;
    }

    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(heap->getBase(), mNextBufferId);
    mHeapBases.add(seqNum, mNextBufferId);
    Return<void> hResult = mPlugin->setSharedBufferBase(hidlMemory, mNextBufferId++);
    ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
    return seqNum;
}

void CryptoHal::clearHeapBase(const sp<IMemoryHeap>& heap) {
    mHeapBases.removeItem(heap->getBase());
void CryptoHal::clearHeapBase(int32_t seqNum) {
    Mutex::Autolock autoLock(mLock);

    mHeapBases.removeItem(seqNum);
}

status_t CryptoHal::toSharedBuffer(const sp<IMemory>& memory, ::SharedBuffer* buffer) {
status_t CryptoHal::toSharedBuffer(const sp<IMemory>& memory, int32_t seqNum, ::SharedBuffer* buffer) {
    ssize_t offset;
    size_t size;

@@ -262,9 +270,9 @@ status_t CryptoHal::toSharedBuffer(const sp<IMemory>& memory, ::SharedBuffer* bu
    }

    // memory must be in the declared heap
    CHECK(mHeapBases.indexOfKey(heap->getBase()) >= 0);
    CHECK(mHeapBases.indexOfKey(seqNum) >= 0);

    buffer->bufferId = mHeapBases.valueFor(heap->getBase());
    buffer->bufferId = mHeapBases.valueFor(seqNum);
    buffer->offset = offset >= 0 ? offset : 0;
    buffer->size = size;
    return OK;
@@ -272,7 +280,7 @@ status_t CryptoHal::toSharedBuffer(const sp<IMemory>& memory, ::SharedBuffer* bu

ssize_t CryptoHal::decrypt(const uint8_t keyId[16], const uint8_t iv[16],
        CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
        const sp<IMemory> &source, size_t offset,
        const ICrypto::SourceBuffer &source, size_t offset,
        const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
        const ICrypto::DestinationBuffer &destination, AString *errorDetailMsg) {
    Mutex::Autolock autoLock(mLock);
@@ -312,11 +320,12 @@ ssize_t CryptoHal::decrypt(const uint8_t keyId[16], const uint8_t iv[16],
    }
    auto hSubSamples = hidl_vec<SubSample>(stdSubSamples);

    int32_t heapSeqNum = source.mHeapSeqNum;
    bool secure;
    ::DestinationBuffer hDestination;
    if (destination.mType == kDestinationTypeSharedMemory) {
        hDestination.type = BufferType::SHARED_MEMORY;
        status_t status = toSharedBuffer(destination.mSharedMemory,
        status_t status = toSharedBuffer(destination.mSharedMemory, heapSeqNum,
                &hDestination.nonsecureMemory);
        if (status != OK) {
            return status;
@@ -329,7 +338,7 @@ ssize_t CryptoHal::decrypt(const uint8_t keyId[16], const uint8_t iv[16],
    }

    ::SharedBuffer hSource;
    status_t status = toSharedBuffer(source, &hSource);
    status_t status = toSharedBuffer(source.mSharedMemory, heapSeqNum, &hSource);
    if (status != OK) {
        return status;
    }
+27 −15
Original line number Diff line number Diff line
@@ -98,7 +98,7 @@ struct BpCrypto : public BpInterface<ICrypto> {

    virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
            CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
            const sp<IMemory> &source, size_t offset,
            const SourceBuffer &source, size_t offset,
            const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
            const DestinationBuffer &destination, AString *errorDetailMsg) {
        Parcel data, reply;
@@ -127,7 +127,8 @@ struct BpCrypto : public BpInterface<ICrypto> {
        }

        data.writeInt32(totalSize);
        data.writeStrongBinder(IInterface::asBinder(source));
        data.writeStrongBinder(IInterface::asBinder(source.mSharedMemory));
        data.writeInt32(source.mHeapSeqNum);
        data.writeInt32(offset);

        data.writeInt32(numSubSamples);
@@ -179,18 +180,25 @@ struct BpCrypto : public BpInterface<ICrypto> {
        return reply.readInt32();
    }

    virtual void setHeap(const sp<IMemoryHeap> &heap) {
    virtual int32_t setHeap(const sp<IMemoryHeap> &heap) {
        Parcel data, reply;
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
        data.writeStrongBinder(IInterface::asBinder(heap));
        remote()->transact(SET_HEAP, data, &reply);
        return;
        status_t err = remote()->transact(SET_HEAP, data, &reply);
        if (err != NO_ERROR) {
            return -1;
        }
        int32_t seqNum;
        if (reply.readInt32(&seqNum) != NO_ERROR) {
            return -1;
        }
        return seqNum;
    }

    virtual void unsetHeap(const sp<IMemoryHeap>& heap) {
    virtual void unsetHeap(int32_t seqNum) {
        Parcel data, reply;
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
        data.writeStrongBinder(IInterface::asBinder(heap));
        data.writeInt32(seqNum);
        remote()->transact(UNSET_HEAP, data, &reply);
        return;
    }
@@ -314,12 +322,17 @@ status_t BnCrypto::onTransact(
            data.read(iv, sizeof(iv));

            size_t totalSize = data.readInt32();
            sp<IMemory> source =

            SourceBuffer source;

            source.mSharedMemory =
                interface_cast<IMemory>(data.readStrongBinder());
            if (source == NULL) {
            if (source.mSharedMemory == NULL) {
                reply->writeInt32(BAD_VALUE);
                return OK;
            }
            source.mHeapSeqNum = data.readInt32();

            int32_t offset = data.readInt32();

            int32_t numSubSamples = data.readInt32();
@@ -372,9 +385,9 @@ status_t BnCrypto::onTransact(

            if (overflow || sumSubsampleSizes != totalSize) {
                result = -EINVAL;
            } else if (totalSize > source->size()) {
            } else if (totalSize > source.mSharedMemory->size()) {
                result = -EINVAL;
            } else if ((size_t)offset > source->size() - totalSize) {
            } else if ((size_t)offset > source.mSharedMemory->size() - totalSize) {
                result = -EINVAL;
            } else {
                result = decrypt(key, iv, mode, pattern, source, offset,
@@ -428,16 +441,15 @@ status_t BnCrypto::onTransact(
            CHECK_INTERFACE(ICrypto, data, reply);
            sp<IMemoryHeap> heap =
                interface_cast<IMemoryHeap>(data.readStrongBinder());
            setHeap(heap);
            reply->writeInt32(setHeap(heap));
            return OK;
        }

        case UNSET_HEAP:
        {
            CHECK_INTERFACE(ICrypto, data, reply);
            sp<IMemoryHeap> heap =
                interface_cast<IMemoryHeap>(data.readStrongBinder());
            unsetHeap(heap);
            int32_t seqNum = data.readInt32();
            unsetHeap(seqNum);
            return OK;
        }

+10 −7
Original line number Diff line number Diff line
@@ -55,13 +55,15 @@ struct CryptoHal : public BnCrypto {

    virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
            CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
            const sp<IMemory> &source, size_t offset,
            const ICrypto::SourceBuffer &source, size_t offset,
            const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
            const ICrypto::DestinationBuffer &destination,
            AString *errorDetailMsg);

    virtual void setHeap(const sp<IMemoryHeap>& heap) { setHeapBase(heap); }
    virtual void unsetHeap(const sp<IMemoryHeap>& heap) { clearHeapBase(heap); }
    virtual int32_t setHeap(const sp<IMemoryHeap>& heap) {
        return setHeapBase(heap);
    }
    virtual void unsetHeap(int32_t seqNum) { clearHeapBase(seqNum); }

private:
    mutable Mutex mLock;
@@ -77,17 +79,18 @@ private:
     */
    status_t mInitCheck;

    KeyedVector<void *, uint32_t> mHeapBases;
    KeyedVector<int32_t, uint32_t> mHeapBases;
    uint32_t mNextBufferId;
    int32_t mHeapSeqNum;

    Vector<sp<ICryptoFactory>> makeCryptoFactories();
    sp<ICryptoPlugin> makeCryptoPlugin(const sp<ICryptoFactory>& factory,
            const uint8_t uuid[16], const void *initData, size_t size);

    void setHeapBase(const sp<IMemoryHeap>& heap);
    void clearHeapBase(const sp<IMemoryHeap>& heap);
    int32_t setHeapBase(const sp<IMemoryHeap>& heap);
    void clearHeapBase(int32_t seqNum);

    status_t toSharedBuffer(const sp<IMemory>& memory, ::SharedBuffer* buffer);
    status_t toSharedBuffer(const sp<IMemory>& memory, int32_t seqNum, ::SharedBuffer* buffer);

    DISALLOW_EVIL_CONSTRUCTORS(CryptoHal);
};
+11 −4
Original line number Diff line number Diff line
@@ -48,6 +48,11 @@ struct ICrypto : public IInterface {

    virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) = 0;

    struct SourceBuffer {
        sp<IMemory> mSharedMemory;
        int32_t mHeapSeqNum;
    };

    enum DestinationType {
        kDestinationTypeSharedMemory, // non-secure
        kDestinationTypeNativeHandle  // secure
@@ -61,16 +66,18 @@ struct ICrypto : public IInterface {

    virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
            CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
            const sp<IMemory> &source, size_t offset,
            const SourceBuffer &source, size_t offset,
            const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
            const DestinationBuffer &destination, AString *errorDetailMsg) = 0;

    /**
     * Declare the heap that the shared memory source buffers passed
     * to decrypt will be allocated from.
     * to decrypt will be allocated from. Returns a sequence number
     * that subsequent decrypt calls can use to refer to the heap,
     * with -1 indicating failure.
     */
    virtual void setHeap(const sp<IMemoryHeap>& heap) = 0;
    virtual void unsetHeap(const sp<IMemoryHeap>& heap) = 0;
    virtual int32_t setHeap(const sp<IMemoryHeap>& heap) = 0;
    virtual void unsetHeap(int32_t seqNum) = 0;

private:
    DISALLOW_EVIL_CONSTRUCTORS(ICrypto);
+20 −8
Original line number Diff line number Diff line
@@ -40,8 +40,8 @@ using BufferInfo = ACodecBufferChannel::BufferInfo;
using BufferInfoIterator = std::vector<const BufferInfo>::const_iterator;

ACodecBufferChannel::~ACodecBufferChannel() {
    if (mCrypto != nullptr && mDealer != nullptr) {
        mCrypto->unsetHeap(mDealer->getMemoryHeap());
    if (mCrypto != nullptr && mDealer != nullptr && mHeapSeqNum >= 0) {
        mCrypto->unsetHeap(mHeapSeqNum);
    }
}

@@ -77,7 +77,8 @@ ACodecBufferChannel::BufferInfo::BufferInfo(
ACodecBufferChannel::ACodecBufferChannel(
        const sp<AMessage> &inputBufferFilled, const sp<AMessage> &outputBufferDrained)
    : mInputBufferFilled(inputBufferFilled),
      mOutputBufferDrained(outputBufferDrained) {
      mOutputBufferDrained(outputBufferDrained),
      mHeapSeqNum(-1) {
}

status_t ACodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffer) {
@@ -128,10 +129,14 @@ status_t ACodecBufferChannel::queueSecureInputBuffer(
        destination.mSharedMemory = mDecryptDestination;
    }

    ICrypto::SourceBuffer source;
    source.mSharedMemory = it->mSharedEncryptedBuffer;
    source.mHeapSeqNum = mHeapSeqNum;

    ssize_t result = -1;
    if (mCrypto != NULL) {
        result = mCrypto->decrypt(key, iv, mode, pattern,
                    it->mSharedEncryptedBuffer, it->mClientBuffer->offset(),
                source, it->mClientBuffer->offset(),
                subSamples, numSubSamples, destination, errorDetailMsg);
    } else {
        DescrambleInfo descrambleInfo;
@@ -262,12 +267,19 @@ void ACodecBufferChannel::getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *arr

sp<MemoryDealer> ACodecBufferChannel::makeMemoryDealer(size_t heapSize) {
    sp<MemoryDealer> dealer;
    if (mDealer != nullptr && mCrypto != nullptr) {
        mCrypto->unsetHeap(mDealer->getMemoryHeap());
    if (mDealer != nullptr && mCrypto != nullptr && mHeapSeqNum >= 0) {
        mCrypto->unsetHeap(mHeapSeqNum);
    }
    dealer = new MemoryDealer(heapSize, "ACodecBufferChannel");
    if (mCrypto != nullptr) {
        mCrypto->setHeap(dealer->getMemoryHeap());
        int32_t seqNum = mCrypto->setHeap(dealer->getMemoryHeap());
        if (seqNum >= 0) {
            mHeapSeqNum = seqNum;
            ALOGD("setHeap returned mHeapSeqNum=%d", mHeapSeqNum);
        } else {
            mHeapSeqNum = -1;
            ALOGD("setHeap failed, setting mHeapSeqNum=-1");
        }
    }
    return dealer;
}
Loading