Commit message: None
CVE: CVE-2016-2506
CWE: CWE-119
Vulnerability description: DRMExtractor.cpp in libstagefright in mediaserver in Android 4.x before 4.4.4, 5.0.x before 5.0.2, 5.1.x before 5.1.1, and 6.x before 2016-07-01 does not validate a certain offset value, which allows remote attackers to execute arbitrary code or cause a denial of service (memory corruption) via a crafted media file, aka internal bug 28175045.

Project: Android

DRMExtractor::DRMExtractor(const sp<DataSource> &source, const char* mime)
 : mDataSource(source),
      mDecryptHandle(NULL),
      mDrmManagerClient(NULL) {
    mOriginalExtractor = MediaExtractor::Create(source, mime);
    mOriginalExtractor->setDrmFlag(true);
    mOriginalExtractor->getMetaData()->setInt32(kKeyIsDRM, 1);

    source->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
}

Project: Android

DRMSource::DRMSource(const sp<MediaSource> &mediaSource,
 const sp<DecryptHandle> &decryptHandle,
 DrmManagerClient *managerClient,
 int32_t trackId, DrmBuffer *ipmpBox)
 : mOriginalMediaSource(mediaSource),
      mDecryptHandle(decryptHandle),
      mDrmManagerClient(managerClient),
      mTrackId(trackId),
      mNALLengthSize(0),
      mWantsNALFragments(false) {
    CHECK(mDrmManagerClient);
    mDrmManagerClient->initializeDecryptUnit(
            mDecryptHandle, trackId, ipmpBox);

 const char *mime;
 bool success = getFormat()->findCString(kKeyMIMEType, &mime);
    CHECK(success);

 if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
 uint32_t type;
 const void *data;
 size_t size;
        CHECK(getFormat()->findData(kKeyAVCC, &type, &data, &size));

 const uint8_t *ptr = (const uint8_t *)data;

        CHECK(size >= 7);
        CHECK_EQ(ptr[0], 1); // configurationVersion == 1

        mNALLengthSize = 1 + (ptr[4] & 3);
 }
}

Project: Android

bool SniffDRM(
 const sp<DataSource> &source, String8 *mimeType, float *confidence,
        sp<AMessage> *) {
    sp<DecryptHandle> decryptHandle = source->DrmInitialization();

 if (decryptHandle != NULL) {
 if (decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED) {
 *mimeType = String8("drm+container_based+") + decryptHandle->mimeType;
 *confidence = 10.0f;
 } else if (decryptHandle->decryptApiType == DecryptApiType::ELEMENTARY_STREAM_BASED) {
 *mimeType = String8("drm+es_based+") + decryptHandle->mimeType;
 *confidence = 10.0f;
 } else {
 return false;
 }

 return true;
 }

 return false;
}

Project: Android

size_t DRMExtractor::countTracks() {
 return mOriginalExtractor->countTracks();
}

Project: Android

sp<MetaData> DRMSource::getFormat() {
 return mOriginalMediaSource->getFormat();
}

Project: Android

sp<MetaData> DRMExtractor::getMetaData() {
 return mOriginalExtractor->getMetaData();
}

Project: Android

status_t DRMSource::start(MetaData *params) {
 int32_t val;
 if (params && params->findInt32(kKeyWantsNALFragments, &val)
 && val != 0) {
        mWantsNALFragments = true;
 } else {
        mWantsNALFragments = false;
 }

 return mOriginalMediaSource->start(params);
}

Project: Android

status_t DRMSource::stop() {
 return mOriginalMediaSource->stop();
}

Project: Android

DRMExtractor::~DRMExtractor() {
}

Project: Android

DRMSource::~DRMSource() {
 Mutex::Autolock autoLock(mDRMLock);
    mDrmManagerClient->finalizeDecryptUnit(mDecryptHandle, mTrackId);
}