Commit message: None
CVE: CVE-2016-0804
CWE: CWE-119
Vulnerability description: The NuPlayer::GenericSource::notifyPreparedAndCleanup function in media/libmediaplayerservice/nuplayer/GenericSource.cpp in mediaserver in Android 5.x before 5.1.1 LMY49G and 6.x before 2016-02-01 improperly manages mDrmManagerClient objects, which allows remote attackers to execute arbitrary code or cause a denial of service (memory corruption) via a crafted media file, aka internal bug 25070434.

Project: Android

sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) {
    sp<AMessage> msg = new AMessage(kWhatGetFormat, id());
    msg->setInt32("audio", audio);

    sp<AMessage> response;
 void *format;
 status_t err = msg->postAndAwaitResponse(&response);
 if (err == OK && response != NULL) {
        CHECK(response->findPointer("format", &format));
 return (MetaData *)format;
 } else {
 return NULL;
 }
}

Project: Android

status_t NuPlayer::GenericSource::initFromDataSource() {
    sp<MediaExtractor> extractor;

    CHECK(mDataSource != NULL);

 if (mIsWidevine) {
 String8 mimeType;
 float confidence;
        sp<AMessage> dummy;
 bool success;

        success = SniffWVM(mDataSource, &mimeType, &confidence, &dummy);
 if (!success
 || strcasecmp(
                    mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
            ALOGE("unsupported widevine mime: %s", mimeType.string());
 return UNKNOWN_ERROR;
 }

        mWVMExtractor = new WVMExtractor(mDataSource);
        mWVMExtractor->setAdaptiveStreamingMode(true);
 if (mUIDValid) {
            mWVMExtractor->setUID(mUID);
 }
        extractor = mWVMExtractor;
 } else {
        extractor = MediaExtractor::Create(mDataSource,
                mSniffedMIME.empty() ? NULL: mSniffedMIME.c_str());
 }

 if (extractor == NULL) {
 return UNKNOWN_ERROR;
 }

 if (extractor->getDrmFlag()) {
        checkDrmStatus(mDataSource);
 }

    mFileMeta = extractor->getMetaData();
 if (mFileMeta != NULL) {
 int64_t duration;
 if (mFileMeta->findInt64(kKeyDuration, &duration)) {
            mDurationUs = duration;
 }
 }

 int32_t totalBitrate = 0;

 size_t numtracks = extractor->countTracks();
 if (numtracks == 0) {
 return UNKNOWN_ERROR;
 }

 for (size_t i = 0; i < numtracks; ++i) {
        sp<MediaSource> track = extractor->getTrack(i);

        sp<MetaData> meta = extractor->getTrackMetaData(i);

 const char *mime;
        CHECK(meta->findCString(kKeyMIMEType, &mime));

 if (!strncasecmp(mime, "audio/", 6)) {
 if (mAudioTrack.mSource == NULL) {
                mAudioTrack.mIndex = i;
                mAudioTrack.mSource = track;
                mAudioTrack.mPackets =
 new AnotherPacketSource(mAudioTrack.mSource->getFormat());

 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
                    mAudioIsVorbis = true;
 } else {
                    mAudioIsVorbis = false;
 }
 }
 } else if (!strncasecmp(mime, "video/", 6)) {
 if (mVideoTrack.mSource == NULL) {
                mVideoTrack.mIndex = i;
                mVideoTrack.mSource = track;
                mVideoTrack.mPackets =
 new AnotherPacketSource(mVideoTrack.mSource->getFormat());

 int32_t secure;
 if (meta->findInt32(kKeyRequiresSecureBuffers, &secure)
 && secure) {
                    mIsWidevine = true;
 if (mUIDValid) {
                        extractor->setUID(mUID);
 }
 }
 }
 }

 if (track != NULL) {
            mSources.push(track);
 int64_t durationUs;
 if (meta->findInt64(kKeyDuration, &durationUs)) {
 if (durationUs > mDurationUs) {
                    mDurationUs = durationUs;
 }
 }

 int32_t bitrate;
 if (totalBitrate >= 0 && meta->findInt32(kKeyBitRate, &bitrate)) {
                totalBitrate += bitrate;
 } else {
                totalBitrate = -1;
 }
 }
 }

    mBitrate = totalBitrate;

 return OK;
}