Commit message: None
CVE: CVE-2015-3834
CWE: CWE-189
Vulnerability description: Multiple integer overflows in the BnHDCP::onTransact function in media/libmedia/IHDCP.cpp in libstagefright in Android before 5.1.1 LMY48I allow attackers to execute arbitrary code via a crafted application that uses HDCP encryption, leading to a heap-based buffer overflow, aka internal bug 20222489.

Project: Android

 BpHDCP(const sp<IBinder> &impl)
 : BpInterface<IHDCP>(impl) {
 }

Project: Android

 BpHDCPObserver(const sp<IBinder> &impl)
 : BpInterface<IHDCPObserver>(impl) {
 }

Project: Android

 virtual status_t decrypt(
 const void *inData, size_t size,
 uint32_t streamCTR, uint64_t inputCTR,
 void *outData) {
 Parcel data, reply;
        data.writeInterfaceToken(IHDCP::getInterfaceDescriptor());
        data.writeInt32(size);
        data.write(inData, size);
        data.writeInt32(streamCTR);
        data.writeInt64(inputCTR);
        remote()->transact(HDCP_DECRYPT, data, &reply);

 status_t err = reply.readInt32();

 if (err != OK) {
 return err;
 }

        reply.read(outData, size);

 return err;
 }

Project: Android

 virtual status_t encrypt(
 const void *inData, size_t size, uint32_t streamCTR,
 uint64_t *outInputCTR, void *outData) {
 Parcel data, reply;
        data.writeInterfaceToken(IHDCP::getInterfaceDescriptor());
        data.writeInt32(size);
        data.write(inData, size);
        data.writeInt32(streamCTR);
        remote()->transact(HDCP_ENCRYPT, data, &reply);

 status_t err = reply.readInt32();

 if (err != OK) {
 *outInputCTR = 0;

 return err;
 }

 *outInputCTR = reply.readInt64();
        reply.read(outData, size);

 return err;
 }

Project: Android

 virtual status_t encryptNative(
 const sp<GraphicBuffer> &graphicBuffer,
 size_t offset, size_t size, uint32_t streamCTR,
 uint64_t *outInputCTR, void *outData) {
 Parcel data, reply;
        data.writeInterfaceToken(IHDCP::getInterfaceDescriptor());
        data.write(*graphicBuffer);
        data.writeInt32(offset);
        data.writeInt32(size);
        data.writeInt32(streamCTR);
        remote()->transact(HDCP_ENCRYPT_NATIVE, data, &reply);

 status_t err = reply.readInt32();

 if (err != OK) {
 *outInputCTR = 0;
 return err;
 }

 *outInputCTR = reply.readInt64();
        reply.read(outData, size);

 return err;
 }

Project: Android

 virtual uint32_t getCaps() {
 Parcel data, reply;
        data.writeInterfaceToken(IHDCP::getInterfaceDescriptor());
        remote()->transact(HDCP_GET_CAPS, data, &reply);
 return reply.readInt32();
 }

Project: Android

 virtual status_t initAsync(const char *host, unsigned port) {
 Parcel data, reply;
        data.writeInterfaceToken(IHDCP::getInterfaceDescriptor());
        data.writeCString(host);
        data.writeInt32(port);
        remote()->transact(HDCP_INIT_ASYNC, data, &reply);
 return reply.readInt32();
 }

Project: Android

 virtual void notify(
 int msg, int ext1, int ext2, const Parcel *obj) {
 Parcel data, reply;
        data.writeInterfaceToken(IHDCPObserver::getInterfaceDescriptor());
        data.writeInt32(msg);
        data.writeInt32(ext1);
        data.writeInt32(ext2);
 if (obj && obj->dataSize() > 0) {
            data.appendFrom(const_cast<Parcel *>(obj), 0, obj->dataSize());
 }
        remote()->transact(OBSERVER_NOTIFY, data, &reply, IBinder::FLAG_ONEWAY);
 }

Project: Android

status_t BnHDCPObserver::onTransact(
 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
 switch (code) {
 case OBSERVER_NOTIFY:
 {
            CHECK_INTERFACE(IHDCPObserver, data, reply);

 int msg = data.readInt32();
 int ext1 = data.readInt32();
 int ext2 = data.readInt32();

 Parcel obj;
 if (data.dataAvail() > 0) {
                obj.appendFrom(
 const_cast<Parcel *>(&data),
                        data.dataPosition(),
                        data.dataAvail());
 }

            notify(msg, ext1, ext2, &obj);

 return OK;
 }

 default:
 return BBinder::onTransact(code, data, reply, flags);
 }
}

Project: Android

 virtual status_t shutdownAsync() {
 Parcel data, reply;
        data.writeInterfaceToken(IHDCP::getInterfaceDescriptor());
        remote()->transact(HDCP_SHUTDOWN_ASYNC, data, &reply);
 return reply.readInt32();
 }