FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_VorbisComment *obj, unsigned length)
{
	FLAC__uint32 i;

	FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input));

 /* read vendor string */
 if (length >= 8) {
		length -= 8; /* vendor string length + num comments entries alone take 8 bytes */
		FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32);
 if (!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->vendor_string.length))
 return false; /* read_callback_ sets the state for us */
 if (obj->vendor_string.length > 0) {
 if (length < obj->vendor_string.length) {
				obj->vendor_string.length = 0;
				obj->vendor_string.entry = 0;
 goto skip;
 }
 else
				length -= obj->vendor_string.length;
 if (0 == (obj->vendor_string.entry = safe_malloc_add_2op_(obj->vendor_string.length, /*+*/1))) {
				decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
 return false;
 }
 if (!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, obj->vendor_string.entry, obj->vendor_string.length))
 return false; /* read_callback_ sets the state for us */
			obj->vendor_string.entry[obj->vendor_string.length] = '\0';
 }
 else
			obj->vendor_string.entry = 0;

 /* read num comments */
		FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN == 32);
 if (!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->num_comments))
 return false; /* read_callback_ sets the state for us */

 /* read comments */
 if (obj->num_comments > 100000) {
 /* Possibly malicious file. */
			obj->num_comments = 0;
 return false;
 }

 		if (obj->num_comments > 0) {
 			if (0 == (obj->comments = safe_malloc_mul_2op_p(obj->num_comments, /*times*/sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) {
 				decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
				obj->num_comments = 0;
 				return false;
 			}
 			for (i = 0; i < obj->num_comments; i++) {
 /* Initialize here just to make sure. */
				obj->comments[i].length = 0;
				obj->comments[i].entry = 0;

				FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32);
 if (length < 4) {
					obj->num_comments = i;
 goto skip;
 }
 else
					length -= 4;
 if (!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->comments[i].length))
 return false; /* read_callback_ sets the state for us */
 if (obj->comments[i].length > 0) {
 if (length < obj->comments[i].length) {
						obj->num_comments = i;
 goto skip;
 }
 else
						length -= obj->comments[i].length;
 if (0 == (obj->comments[i].entry = safe_malloc_add_2op_(obj->comments[i].length, /*+*/1))) {
						decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
 return false;
 }
					memset (obj->comments[i].entry, 0, obj->comments[i].length) ;
 if (!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, obj->comments[i].entry, obj->comments[i].length)) {
						obj->num_comments = i;
 goto skip;
 }
					obj->comments[i].entry[obj->comments[i].length] = '\0';
 }
 else
					obj->comments[i].entry = 0;
 }
 }
 else
			obj->comments = 0;
 }

  skip:
 if (length > 0) {
 /* This will only happen on files with invalid data in comments */
 if(!FLAC__bitreader_skip_byte_block_aligned_no_crc(decoder->private_->input, length))
 return false; /* read_callback_ sets the state for us */
 }

 return true;
}


static int aacDecoder_drcExtractAndMap (
        HANDLE_AAC_DRC  self,
        HANDLE_FDK_BITSTREAM hBs,
 CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
        UCHAR  pceInstanceTag,
        UCHAR  channelMapping[], /* Channel mapping translating drcChannel index to canonical channel index */
 int    validChannels )
{
 CDrcPayload  threadBs[MAX_DRC_THREADS];
 CDrcPayload *validThreadBs[MAX_DRC_THREADS];
 CDrcParams *pParams;
  UINT backupBsPosition;
 int  i, thread, validThreads = 0;
 int  numExcludedChns[MAX_DRC_THREADS];

  FDK_ASSERT(self != NULL);
  FDK_ASSERT(hBs != NULL);
  FDK_ASSERT(pAacDecoderStaticChannelInfo != NULL);

  pParams = &self->params;

  self->numThreads = 0;
  backupBsPosition = FDKgetValidBits(hBs);

 for (i = 0; i < self->numPayloads && self->numThreads < MAX_DRC_THREADS; i++) {
 int bitsParsed;

 /* Init payload data chunk. The memclear is very important because it initializes
       the most values. Without it the module wouldn't work properly or crash. */
 FDKmemclear(&threadBs[self->numThreads], sizeof(CDrcPayload));
    threadBs[self->numThreads].channelData.bandTop[0] = (1024 >> 2) - 1;

 /* Extract payload */
    bitsParsed = aacDecoder_drcParse( hBs,
 &threadBs[self->numThreads],
                                      self->drcPayloadPosition[i] );
 if (bitsParsed > 0) {
      self->numThreads++;
 }

   }
   self->numPayloads = 0;

   if (self->dvbAncDataAvailable)
   { /* Append a DVB heavy compression payload thread if available. */
     int bitsParsed;

 /* Init payload data chunk. The memclear is very important because it initializes
       the most values. Without it the module wouldn't work properly or crash. */
 FDKmemclear(&threadBs[self->numThreads], sizeof(CDrcPayload));
    threadBs[self->numThreads].channelData.bandTop[0] = (1024 >> 2) - 1;

 /* Extract payload */
    bitsParsed = aacDecoder_drcReadCompression( hBs,
 &threadBs[self->numThreads],
                                                self->dvbAncDataPosition );
 if (bitsParsed > 0) {
      self->numThreads++;
 }
 }
  self->dvbAncDataAvailable = 0;

 /* Reset the bitbufffer */
 FDKpushBiDirectional(hBs, FDKgetValidBits(hBs) - backupBsPosition);

 /* calculate number of valid bits in excl_chn_mask */

   /* coupling channels not supported */

   /* check for valid threads */
   for (thread = 0; thread < self->numThreads; thread++) {
     CDrcPayload *pThreadBs = &threadBs[thread];
 int numExclChns = 0;

 switch ((AACDEC_DRC_PAYLOAD_TYPE)pThreadBs->channelData.drcDataType) {
 default:
 continue;
 case MPEG_DRC_EXT_DATA:
 case DVB_DRC_ANC_DATA:
 break;
 }

 if (pThreadBs->pceInstanceTag >= 0) { /* if PCE tag present */
 if (pThreadBs->pceInstanceTag != pceInstanceTag) {
 continue; /* don't accept */
 }
 }

 /* calculate number of excluded channels */
 if (pThreadBs->excludedChnsMask > 0) {
      INT exclMask = pThreadBs->excludedChnsMask;
 int ch;
 for (ch = 0; ch < validChannels; ch++) {
        numExclChns += exclMask & 0x1;
        exclMask >>= 1;
 }
 }
 if (numExclChns < validChannels) {
      validThreadBs[validThreads] = pThreadBs;
      numExcludedChns[validThreads] = numExclChns;
      validThreads++;
 }
 }

 if (validThreads > 1) {
 int ch;

 /* check consistency of excl_chn_mask amongst valid DRC threads */
 for (ch = 0; ch < validChannels; ch++) {
 int present = 0;

 for (thread = 0; thread < validThreads; thread++) {
 CDrcPayload *pThreadBs = validThreadBs[thread];

 /* thread applies to this channel */
 if ( (pThreadBs->channelData.drcDataType == MPEG_DRC_EXT_DATA)
 && ( (numExcludedChns[thread] == 0)
 || (!(pThreadBs->excludedChnsMask & (1<<ch))) ) ) {
          present++;
 }
 }

 if (present > 1) {
 return -1;
 }
 }
 }

 /* map DRC bitstream information onto DRC channel information */
 for (thread = 0; thread < validThreads; thread++)
 {
 CDrcPayload *pThreadBs = validThreadBs[thread];
    INT exclMask = pThreadBs->excludedChnsMask;
    AACDEC_DRC_PAYLOAD_TYPE drcPayloadType = (AACDEC_DRC_PAYLOAD_TYPE)pThreadBs->channelData.drcDataType;
 int ch;

 /* last progRefLevel transmitted is the one that is used
     * (but it should really only be transmitted once per block!)
     */
 if (pThreadBs->progRefLevel >= 0) {
      self->progRefLevel = pThreadBs->progRefLevel;
      self->progRefLevelPresent = 1;
      self->prlExpiryCount = 0; /* Got a new value -> Reset counter */
 }

 if (drcPayloadType == DVB_DRC_ANC_DATA) {
 /* Announce the presentation mode of this valid thread. */
      self->presMode = pThreadBs->presMode;
 }

 /* SCE, CPE and LFE */
 for (ch = 0; ch < validChannels; ch++) {
 int mapedChannel = channelMapping[ch];

 if ( ((exclMask & (1<<mapedChannel)) == 0)
 && ( (drcPayloadType == MPEG_DRC_EXT_DATA)
 || ((drcPayloadType == DVB_DRC_ANC_DATA) && self->params.applyHeavyCompression)
 ) ) {
 /* copy thread to channel */
        pAacDecoderStaticChannelInfo[ch]->drcData = pThreadBs->channelData;
 }
 }
 /* CCEs not supported by now */
 }

 /* Increment and check expiry counter for the program reference level: */
 if ( (pParams->expiryFrame > 0)
 && (self->prlExpiryCount++ > pParams->expiryFrame) )
 { /* The program reference level is too old, so set it back to the target level. */
    self->progRefLevelPresent = 0;
    self->progRefLevel = pParams->targetRefLevel;
    self->prlExpiryCount = 0;
 }

 return 0;
}

libAACdec/src/aacdec_drc.cpp 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-05-01 does not properly limit the number of threads, which allows remote attackers to execute arbitrary code or cause a denial of service (stack memory corruption) via a crafted media file, aka internal bug 26751339.


static int aacDecoder_drcExtractAndMap (
        HANDLE_AAC_DRC  self,
        HANDLE_FDK_BITSTREAM hBs,
 CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
        UCHAR  pceInstanceTag,
        UCHAR  channelMapping[], /* Channel mapping translating drcChannel index to canonical channel index */
 int    validChannels )
{
 CDrcPayload  threadBs[MAX_DRC_THREADS];
 CDrcPayload *validThreadBs[MAX_DRC_THREADS];
 CDrcParams *pParams;
  UINT backupBsPosition;
 int  i, thread, validThreads = 0;
 int  numExcludedChns[MAX_DRC_THREADS];

  FDK_ASSERT(self != NULL);
  FDK_ASSERT(hBs != NULL);
  FDK_ASSERT(pAacDecoderStaticChannelInfo != NULL);

  pParams = &self->params;

  self->numThreads = 0;
  backupBsPosition = FDKgetValidBits(hBs);

 for (i = 0; i < self->numPayloads && self->numThreads < MAX_DRC_THREADS; i++) {
 int bitsParsed;

 /* Init payload data chunk. The memclear is very important because it initializes
       the most values. Without it the module wouldn't work properly or crash. */
 FDKmemclear(&threadBs[self->numThreads], sizeof(CDrcPayload));
    threadBs[self->numThreads].channelData.bandTop[0] = (1024 >> 2) - 1;

 /* Extract payload */
    bitsParsed = aacDecoder_drcParse( hBs,
 &threadBs[self->numThreads],
                                      self->drcPayloadPosition[i] );
 if (bitsParsed > 0) {
      self->numThreads++;
 }

   }
   self->numPayloads = 0;

  if (self->numThreads >= MAX_DRC_THREADS) {
      self->numThreads = MAX_DRC_THREADS - 1;
  }

   if (self->dvbAncDataAvailable)
   { /* Append a DVB heavy compression payload thread if available. */
     int bitsParsed;

 /* Init payload data chunk. The memclear is very important because it initializes
       the most values. Without it the module wouldn't work properly or crash. */
 FDKmemclear(&threadBs[self->numThreads], sizeof(CDrcPayload));
    threadBs[self->numThreads].channelData.bandTop[0] = (1024 >> 2) - 1;

 /* Extract payload */
    bitsParsed = aacDecoder_drcReadCompression( hBs,
 &threadBs[self->numThreads],
                                                self->dvbAncDataPosition );
 if (bitsParsed > 0) {
      self->numThreads++;
 }
 }
  self->dvbAncDataAvailable = 0;

 /* Reset the bitbufffer */
 FDKpushBiDirectional(hBs, FDKgetValidBits(hBs) - backupBsPosition);

 /* calculate number of valid bits in excl_chn_mask */

   /* coupling channels not supported */

  if (self->numThreads >= MAX_DRC_THREADS) {
      self->numThreads = MAX_DRC_THREADS - 1;
  }

   /* check for valid threads */
   for (thread = 0; thread < self->numThreads; thread++) {
     CDrcPayload *pThreadBs = &threadBs[thread];
 int numExclChns = 0;

 switch ((AACDEC_DRC_PAYLOAD_TYPE)pThreadBs->channelData.drcDataType) {
 default:
 continue;
 case MPEG_DRC_EXT_DATA:
 case DVB_DRC_ANC_DATA:
 break;
 }

 if (pThreadBs->pceInstanceTag >= 0) { /* if PCE tag present */
 if (pThreadBs->pceInstanceTag != pceInstanceTag) {
 continue; /* don't accept */
 }
 }

 /* calculate number of excluded channels */
 if (pThreadBs->excludedChnsMask > 0) {
      INT exclMask = pThreadBs->excludedChnsMask;
 int ch;
 for (ch = 0; ch < validChannels; ch++) {
        numExclChns += exclMask & 0x1;
        exclMask >>= 1;
 }
 }
 if (numExclChns < validChannels) {
      validThreadBs[validThreads] = pThreadBs;
      numExcludedChns[validThreads] = numExclChns;
      validThreads++;
 }
 }

 if (validThreads > 1) {
 int ch;

 /* check consistency of excl_chn_mask amongst valid DRC threads */
 for (ch = 0; ch < validChannels; ch++) {
 int present = 0;

 for (thread = 0; thread < validThreads; thread++) {
 CDrcPayload *pThreadBs = validThreadBs[thread];

 /* thread applies to this channel */
 if ( (pThreadBs->channelData.drcDataType == MPEG_DRC_EXT_DATA)
 && ( (numExcludedChns[thread] == 0)
 || (!(pThreadBs->excludedChnsMask & (1<<ch))) ) ) {
          present++;
 }
 }

 if (present > 1) {
 return -1;
 }
 }
 }

 /* map DRC bitstream information onto DRC channel information */
 for (thread = 0; thread < validThreads; thread++)
 {
 CDrcPayload *pThreadBs = validThreadBs[thread];
    INT exclMask = pThreadBs->excludedChnsMask;
    AACDEC_DRC_PAYLOAD_TYPE drcPayloadType = (AACDEC_DRC_PAYLOAD_TYPE)pThreadBs->channelData.drcDataType;
 int ch;

 /* last progRefLevel transmitted is the one that is used
     * (but it should really only be transmitted once per block!)
     */
 if (pThreadBs->progRefLevel >= 0) {
      self->progRefLevel = pThreadBs->progRefLevel;
      self->progRefLevelPresent = 1;
      self->prlExpiryCount = 0; /* Got a new value -> Reset counter */
 }

 if (drcPayloadType == DVB_DRC_ANC_DATA) {
 /* Announce the presentation mode of this valid thread. */
      self->presMode = pThreadBs->presMode;
 }

 /* SCE, CPE and LFE */
 for (ch = 0; ch < validChannels; ch++) {
 int mapedChannel = channelMapping[ch];

 if ( ((exclMask & (1<<mapedChannel)) == 0)
 && ( (drcPayloadType == MPEG_DRC_EXT_DATA)
 || ((drcPayloadType == DVB_DRC_ANC_DATA) && self->params.applyHeavyCompression)
 ) ) {
 /* copy thread to channel */
        pAacDecoderStaticChannelInfo[ch]->drcData = pThreadBs->channelData;
 }
 }
 /* CCEs not supported by now */
 }

 /* Increment and check expiry counter for the program reference level: */
 if ( (pParams->expiryFrame > 0)
 && (self->prlExpiryCount++ > pParams->expiryFrame) )
 { /* The program reference level is too old, so set it back to the target level. */
    self->progRefLevelPresent = 0;
    self->progRefLevel = pParams->targetRefLevel;
    self->prlExpiryCount = 0;
 }

 return 0;
}


char* engrave_tombstone(pid_t pid, pid_t tid, int signal, int original_si_code,
 uintptr_t abort_msg_address, bool dump_sibling_threads,
 bool* detach_failed, int* total_sleep_time_usec) {

 log_t log;

   log.current_tid = tid;
   log.crashed_tid = tid;

  if ((mkdir(TOMBSTONE_DIR, 0755) == -1) && (errno != EEXIST)) {
    _LOG(&log, logtype::ERROR, "failed to create %s: %s\n", TOMBSTONE_DIR, strerror(errno));
  }
  if (chown(TOMBSTONE_DIR, AID_SYSTEM, AID_SYSTEM) == -1) {
    _LOG(&log, logtype::ERROR, "failed to change ownership of %s: %s\n", TOMBSTONE_DIR, strerror(errno));
  }
   int fd = -1;
  char* path = NULL;
  if (selinux_android_restorecon(TOMBSTONE_DIR, 0) == 0) {
    path = find_and_open_tombstone(&fd);
  } else {
    _LOG(&log, logtype::ERROR, "Failed to restore security context, not writing tombstone.\n");
  }

   if (fd < 0) {
     _LOG(&log, logtype::ERROR, "Skipping tombstone write, nothing to do.\n");
 *detach_failed = false;
 return NULL;
 }

  log.tfd = fd;
 int amfd = activity_manager_connect();
  log.amfd = amfd;
 *detach_failed = dump_crash(&log, pid, tid, signal, original_si_code, abort_msg_address,
                              dump_sibling_threads, total_sleep_time_usec);

  ALOGI("\nTombstone written to: %s\n", path);

  close(amfd);
  close(fd);

 return path;
}

rootdir/init.rc in Android 4.x before 4.4.4 does not ensure that the /data/tombstones directory exists for the Debuggerd component, which allows attackers to gain privileges via a crafted application, aka internal bug 26403620.


char* engrave_tombstone(pid_t pid, pid_t tid, int signal, int original_si_code,
 uintptr_t abort_msg_address, bool dump_sibling_threads,
 bool* detach_failed, int* total_sleep_time_usec) {

 log_t log;

   log.current_tid = tid;
   log.crashed_tid = tid;

   int fd = -1;
  char* path = find_and_open_tombstone(&fd);

   if (fd < 0) {
     _LOG(&log, logtype::ERROR, "Skipping tombstone write, nothing to do.\n");
 *detach_failed = false;
 return NULL;
 }

  log.tfd = fd;
 int amfd = activity_manager_connect();
  log.amfd = amfd;
 *detach_failed = dump_crash(&log, pid, tid, signal, original_si_code, abort_msg_address,
                              dump_sibling_threads, total_sleep_time_usec);

  ALOGI("\nTombstone written to: %s\n", path);

  close(amfd);
  close(fd);

 return path;
}


status_t BnDrm::onTransact(
 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
 switch (code) {
 case INIT_CHECK:
 {
            CHECK_INTERFACE(IDrm, data, reply);
            reply->writeInt32(initCheck());
 return OK;
 }

 case IS_CRYPTO_SUPPORTED:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 uint8_t uuid[16];
            data.read(uuid, sizeof(uuid));
 String8 mimeType = data.readString8();
            reply->writeInt32(isCryptoSchemeSupported(uuid, mimeType));

 return OK;
 }

 case CREATE_PLUGIN:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 uint8_t uuid[16];
            data.read(uuid, sizeof(uuid));
            reply->writeInt32(createPlugin(uuid));
 return OK;
 }

 case DESTROY_PLUGIN:
 {
            CHECK_INTERFACE(IDrm, data, reply);
            reply->writeInt32(destroyPlugin());
 return OK;
 }

 case OPEN_SESSION:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId;
 status_t result = openSession(sessionId);
            writeVector(reply, sessionId);
            reply->writeInt32(result);
 return OK;
 }

 case CLOSE_SESSION:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId;
            readVector(data, sessionId);
            reply->writeInt32(closeSession(sessionId));
 return OK;
 }

 case GET_KEY_REQUEST:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId, initData;

            readVector(data, sessionId);
            readVector(data, initData);
 String8 mimeType = data.readString8();
 DrmPlugin::KeyType keyType = (DrmPlugin::KeyType)data.readInt32();

 KeyedVector<String8, String8> optionalParameters;
 uint32_t count = data.readInt32();
 for (size_t i = 0; i < count; ++i) {
 String8 key, value;
                key = data.readString8();
                value = data.readString8();
                optionalParameters.add(key, value);
 }

             Vector<uint8_t> request;
             String8 defaultUrl;
            DrmPlugin::KeyRequestType keyRequestType;

             status_t result = getKeyRequest(sessionId, initData, mimeType,
                     keyType, optionalParameters, request, defaultUrl,
 &keyRequestType);

            writeVector(reply, request);
            reply->writeString8(defaultUrl);
            reply->writeInt32(static_cast<int32_t>(keyRequestType));
            reply->writeInt32(result);
 return OK;
 }

 case PROVIDE_KEY_RESPONSE:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId, response, keySetId;
            readVector(data, sessionId);
            readVector(data, response);
 uint32_t result = provideKeyResponse(sessionId, response, keySetId);
            writeVector(reply, keySetId);
            reply->writeInt32(result);
 return OK;
 }

 case REMOVE_KEYS:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> keySetId;
            readVector(data, keySetId);
            reply->writeInt32(removeKeys(keySetId));
 return OK;
 }

 case RESTORE_KEYS:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId, keySetId;
            readVector(data, sessionId);
            readVector(data, keySetId);
            reply->writeInt32(restoreKeys(sessionId, keySetId));
 return OK;
 }

 case QUERY_KEY_STATUS:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId;
            readVector(data, sessionId);
 KeyedVector<String8, String8> infoMap;
 status_t result = queryKeyStatus(sessionId, infoMap);
 size_t count = infoMap.size();
            reply->writeInt32(count);
 for (size_t i = 0; i < count; ++i) {
                reply->writeString8(infoMap.keyAt(i));
                reply->writeString8(infoMap.valueAt(i));
 }
            reply->writeInt32(result);
 return OK;
 }

 case GET_PROVISION_REQUEST:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 String8 certType = data.readString8();
 String8 certAuthority = data.readString8();

 Vector<uint8_t> request;
 String8 defaultUrl;
 status_t result = getProvisionRequest(certType, certAuthority,
                                                  request, defaultUrl);
            writeVector(reply, request);
            reply->writeString8(defaultUrl);
            reply->writeInt32(result);
 return OK;
 }

 case PROVIDE_PROVISION_RESPONSE:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> response;
 Vector<uint8_t> certificate;
 Vector<uint8_t> wrappedKey;
            readVector(data, response);
 status_t result = provideProvisionResponse(response, certificate, wrappedKey);
            writeVector(reply, certificate);
            writeVector(reply, wrappedKey);
            reply->writeInt32(result);
 return OK;
 }

 case UNPROVISION_DEVICE:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 status_t result = unprovisionDevice();
            reply->writeInt32(result);
 return OK;
 }

 case GET_SECURE_STOPS:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 List<Vector<uint8_t> > secureStops;
 status_t result = getSecureStops(secureStops);
 size_t count = secureStops.size();
            reply->writeInt32(count);
 List<Vector<uint8_t> >::iterator iter = secureStops.begin();
 while(iter != secureStops.end()) {
 size_t size = iter->size();
                reply->writeInt32(size);
                reply->write(iter->array(), iter->size());
                iter++;
 }
            reply->writeInt32(result);
 return OK;
 }

 case GET_SECURE_STOP:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> ssid, secureStop;
            readVector(data, ssid);
 status_t result = getSecureStop(ssid, secureStop);
            writeVector(reply, secureStop);
            reply->writeInt32(result);
 return OK;
 }

 case RELEASE_SECURE_STOPS:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> ssRelease;
            readVector(data, ssRelease);
            reply->writeInt32(releaseSecureStops(ssRelease));
 return OK;
 }

 case RELEASE_ALL_SECURE_STOPS:
 {
            CHECK_INTERFACE(IDrm, data, reply);
            reply->writeInt32(releaseAllSecureStops());
 return OK;
 }

 case GET_PROPERTY_STRING:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 String8 name = data.readString8();
 String8 value;
 status_t result = getPropertyString(name, value);
            reply->writeString8(value);
            reply->writeInt32(result);
 return OK;
 }

 case GET_PROPERTY_BYTE_ARRAY:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 String8 name = data.readString8();
 Vector<uint8_t> value;
 status_t result = getPropertyByteArray(name, value);
            writeVector(reply, value);
            reply->writeInt32(result);
 return OK;
 }

 case SET_PROPERTY_STRING:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 String8 name = data.readString8();
 String8 value = data.readString8();
            reply->writeInt32(setPropertyString(name, value));
 return OK;
 }

 case SET_PROPERTY_BYTE_ARRAY:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 String8 name = data.readString8();
 Vector<uint8_t> value;
            readVector(data, value);
            reply->writeInt32(setPropertyByteArray(name, value));
 return OK;
 }

 case SET_CIPHER_ALGORITHM:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId;
            readVector(data, sessionId);
 String8 algorithm = data.readString8();
            reply->writeInt32(setCipherAlgorithm(sessionId, algorithm));
 return OK;
 }

 case SET_MAC_ALGORITHM:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId;
            readVector(data, sessionId);
 String8 algorithm = data.readString8();
            reply->writeInt32(setMacAlgorithm(sessionId, algorithm));
 return OK;
 }

 case ENCRYPT:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId, keyId, input, iv, output;
            readVector(data, sessionId);
            readVector(data, keyId);
            readVector(data, input);
            readVector(data, iv);
 uint32_t result = encrypt(sessionId, keyId, input, iv, output);
            writeVector(reply, output);
            reply->writeInt32(result);
 return OK;
 }

 case DECRYPT:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId, keyId, input, iv, output;
            readVector(data, sessionId);
            readVector(data, keyId);
            readVector(data, input);
            readVector(data, iv);
 uint32_t result = decrypt(sessionId, keyId, input, iv, output);
            writeVector(reply, output);
            reply->writeInt32(result);
 return OK;
 }

 case SIGN:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId, keyId, message, signature;
            readVector(data, sessionId);
            readVector(data, keyId);
            readVector(data, message);
 uint32_t result = sign(sessionId, keyId, message, signature);
            writeVector(reply, signature);
            reply->writeInt32(result);
 return OK;
 }

 case VERIFY:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId, keyId, message, signature;
            readVector(data, sessionId);
            readVector(data, keyId);
            readVector(data, message);
            readVector(data, signature);
 bool match;
 uint32_t result = verify(sessionId, keyId, message, signature, match);
            reply->writeInt32(match);
            reply->writeInt32(result);
 return OK;
 }

 case SIGN_RSA:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId, message, wrappedKey, signature;
            readVector(data, sessionId);
 String8 algorithm = data.readString8();
            readVector(data, message);
            readVector(data, wrappedKey);
 uint32_t result = signRSA(sessionId, algorithm, message, wrappedKey, signature);
            writeVector(reply, signature);
            reply->writeInt32(result);
 return OK;
 }

 case SET_LISTENER: {
        CHECK_INTERFACE(IDrm, data, reply);
        sp<IDrmClient> listener =
            interface_cast<IDrmClient>(data.readStrongBinder());
        reply->writeInt32(setListener(listener));
 return NO_ERROR;
 } break;

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

media/libmedia/IDrm.cpp in mediaserver in Android 6.x before 2016-04-01 does not initialize a certain key-request data structure, which allows attackers to obtain sensitive information from process memory, and consequently bypass an unspecified protection mechanism, via unspecified vectors, as demonstrated by obtaining Signature or SignatureOrSystem access, aka internal bug 26323455.


status_t BnDrm::onTransact(
 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
 switch (code) {
 case INIT_CHECK:
 {
            CHECK_INTERFACE(IDrm, data, reply);
            reply->writeInt32(initCheck());
 return OK;
 }

 case IS_CRYPTO_SUPPORTED:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 uint8_t uuid[16];
            data.read(uuid, sizeof(uuid));
 String8 mimeType = data.readString8();
            reply->writeInt32(isCryptoSchemeSupported(uuid, mimeType));

 return OK;
 }

 case CREATE_PLUGIN:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 uint8_t uuid[16];
            data.read(uuid, sizeof(uuid));
            reply->writeInt32(createPlugin(uuid));
 return OK;
 }

 case DESTROY_PLUGIN:
 {
            CHECK_INTERFACE(IDrm, data, reply);
            reply->writeInt32(destroyPlugin());
 return OK;
 }

 case OPEN_SESSION:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId;
 status_t result = openSession(sessionId);
            writeVector(reply, sessionId);
            reply->writeInt32(result);
 return OK;
 }

 case CLOSE_SESSION:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId;
            readVector(data, sessionId);
            reply->writeInt32(closeSession(sessionId));
 return OK;
 }

 case GET_KEY_REQUEST:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId, initData;

            readVector(data, sessionId);
            readVector(data, initData);
 String8 mimeType = data.readString8();
 DrmPlugin::KeyType keyType = (DrmPlugin::KeyType)data.readInt32();

 KeyedVector<String8, String8> optionalParameters;
 uint32_t count = data.readInt32();
 for (size_t i = 0; i < count; ++i) {
 String8 key, value;
                key = data.readString8();
                value = data.readString8();
                optionalParameters.add(key, value);
 }

             Vector<uint8_t> request;
             String8 defaultUrl;
            DrmPlugin::KeyRequestType keyRequestType = DrmPlugin::kKeyRequestType_Unknown;

             status_t result = getKeyRequest(sessionId, initData, mimeType,
                     keyType, optionalParameters, request, defaultUrl,
 &keyRequestType);

            writeVector(reply, request);
            reply->writeString8(defaultUrl);
            reply->writeInt32(static_cast<int32_t>(keyRequestType));
            reply->writeInt32(result);
 return OK;
 }

 case PROVIDE_KEY_RESPONSE:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId, response, keySetId;
            readVector(data, sessionId);
            readVector(data, response);
 uint32_t result = provideKeyResponse(sessionId, response, keySetId);
            writeVector(reply, keySetId);
            reply->writeInt32(result);
 return OK;
 }

 case REMOVE_KEYS:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> keySetId;
            readVector(data, keySetId);
            reply->writeInt32(removeKeys(keySetId));
 return OK;
 }

 case RESTORE_KEYS:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId, keySetId;
            readVector(data, sessionId);
            readVector(data, keySetId);
            reply->writeInt32(restoreKeys(sessionId, keySetId));
 return OK;
 }

 case QUERY_KEY_STATUS:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId;
            readVector(data, sessionId);
 KeyedVector<String8, String8> infoMap;
 status_t result = queryKeyStatus(sessionId, infoMap);
 size_t count = infoMap.size();
            reply->writeInt32(count);
 for (size_t i = 0; i < count; ++i) {
                reply->writeString8(infoMap.keyAt(i));
                reply->writeString8(infoMap.valueAt(i));
 }
            reply->writeInt32(result);
 return OK;
 }

 case GET_PROVISION_REQUEST:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 String8 certType = data.readString8();
 String8 certAuthority = data.readString8();

 Vector<uint8_t> request;
 String8 defaultUrl;
 status_t result = getProvisionRequest(certType, certAuthority,
                                                  request, defaultUrl);
            writeVector(reply, request);
            reply->writeString8(defaultUrl);
            reply->writeInt32(result);
 return OK;
 }

 case PROVIDE_PROVISION_RESPONSE:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> response;
 Vector<uint8_t> certificate;
 Vector<uint8_t> wrappedKey;
            readVector(data, response);
 status_t result = provideProvisionResponse(response, certificate, wrappedKey);
            writeVector(reply, certificate);
            writeVector(reply, wrappedKey);
            reply->writeInt32(result);
 return OK;
 }

 case UNPROVISION_DEVICE:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 status_t result = unprovisionDevice();
            reply->writeInt32(result);
 return OK;
 }

 case GET_SECURE_STOPS:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 List<Vector<uint8_t> > secureStops;
 status_t result = getSecureStops(secureStops);
 size_t count = secureStops.size();
            reply->writeInt32(count);
 List<Vector<uint8_t> >::iterator iter = secureStops.begin();
 while(iter != secureStops.end()) {
 size_t size = iter->size();
                reply->writeInt32(size);
                reply->write(iter->array(), iter->size());
                iter++;
 }
            reply->writeInt32(result);
 return OK;
 }

 case GET_SECURE_STOP:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> ssid, secureStop;
            readVector(data, ssid);
 status_t result = getSecureStop(ssid, secureStop);
            writeVector(reply, secureStop);
            reply->writeInt32(result);
 return OK;
 }

 case RELEASE_SECURE_STOPS:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> ssRelease;
            readVector(data, ssRelease);
            reply->writeInt32(releaseSecureStops(ssRelease));
 return OK;
 }

 case RELEASE_ALL_SECURE_STOPS:
 {
            CHECK_INTERFACE(IDrm, data, reply);
            reply->writeInt32(releaseAllSecureStops());
 return OK;
 }

 case GET_PROPERTY_STRING:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 String8 name = data.readString8();
 String8 value;
 status_t result = getPropertyString(name, value);
            reply->writeString8(value);
            reply->writeInt32(result);
 return OK;
 }

 case GET_PROPERTY_BYTE_ARRAY:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 String8 name = data.readString8();
 Vector<uint8_t> value;
 status_t result = getPropertyByteArray(name, value);
            writeVector(reply, value);
            reply->writeInt32(result);
 return OK;
 }

 case SET_PROPERTY_STRING:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 String8 name = data.readString8();
 String8 value = data.readString8();
            reply->writeInt32(setPropertyString(name, value));
 return OK;
 }

 case SET_PROPERTY_BYTE_ARRAY:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 String8 name = data.readString8();
 Vector<uint8_t> value;
            readVector(data, value);
            reply->writeInt32(setPropertyByteArray(name, value));
 return OK;
 }

 case SET_CIPHER_ALGORITHM:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId;
            readVector(data, sessionId);
 String8 algorithm = data.readString8();
            reply->writeInt32(setCipherAlgorithm(sessionId, algorithm));
 return OK;
 }

 case SET_MAC_ALGORITHM:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId;
            readVector(data, sessionId);
 String8 algorithm = data.readString8();
            reply->writeInt32(setMacAlgorithm(sessionId, algorithm));
 return OK;
 }

 case ENCRYPT:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId, keyId, input, iv, output;
            readVector(data, sessionId);
            readVector(data, keyId);
            readVector(data, input);
            readVector(data, iv);
 uint32_t result = encrypt(sessionId, keyId, input, iv, output);
            writeVector(reply, output);
            reply->writeInt32(result);
 return OK;
 }

 case DECRYPT:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId, keyId, input, iv, output;
            readVector(data, sessionId);
            readVector(data, keyId);
            readVector(data, input);
            readVector(data, iv);
 uint32_t result = decrypt(sessionId, keyId, input, iv, output);
            writeVector(reply, output);
            reply->writeInt32(result);
 return OK;
 }

 case SIGN:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId, keyId, message, signature;
            readVector(data, sessionId);
            readVector(data, keyId);
            readVector(data, message);
 uint32_t result = sign(sessionId, keyId, message, signature);
            writeVector(reply, signature);
            reply->writeInt32(result);
 return OK;
 }

 case VERIFY:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId, keyId, message, signature;
            readVector(data, sessionId);
            readVector(data, keyId);
            readVector(data, message);
            readVector(data, signature);
 bool match;
 uint32_t result = verify(sessionId, keyId, message, signature, match);
            reply->writeInt32(match);
            reply->writeInt32(result);
 return OK;
 }

 case SIGN_RSA:
 {
            CHECK_INTERFACE(IDrm, data, reply);
 Vector<uint8_t> sessionId, message, wrappedKey, signature;
            readVector(data, sessionId);
 String8 algorithm = data.readString8();
            readVector(data, message);
            readVector(data, wrappedKey);
 uint32_t result = signRSA(sessionId, algorithm, message, wrappedKey, signature);
            writeVector(reply, signature);
            reply->writeInt32(result);
 return OK;
 }

 case SET_LISTENER: {
        CHECK_INTERFACE(IDrm, data, reply);
        sp<IDrmClient> listener =
            interface_cast<IDrmClient>(data.readStrongBinder());
        reply->writeInt32(setListener(listener));
 return NO_ERROR;
 } break;

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


status_t BnOMX::onTransact(
 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
 switch (code) {
 case LIVES_LOCALLY:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);
            node_id node = (node_id)data.readInt32();
 pid_t pid = (pid_t)data.readInt32();
            reply->writeInt32(livesLocally(node, pid));

 return OK;
 }

 case LIST_NODES:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

 List<ComponentInfo> list;
            listNodes(&list);

            reply->writeInt32(list.size());
 for (List<ComponentInfo>::iterator it = list.begin();
                 it != list.end(); ++it) {
 ComponentInfo &cur = *it;

                reply->writeString8(cur.mName);
                reply->writeInt32(cur.mRoles.size());
 for (List<String8>::iterator role_it = cur.mRoles.begin();
                     role_it != cur.mRoles.end(); ++role_it) {
                    reply->writeString8(*role_it);
 }
 }

 return NO_ERROR;
 }

 case ALLOCATE_NODE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

 const char *name = data.readCString();

            sp<IOMXObserver> observer =
                interface_cast<IOMXObserver>(data.readStrongBinder());

            node_id node;

 status_t err = allocateNode(name, observer, &node);
            reply->writeInt32(err);
 if (err == OK) {
                reply->writeInt32((int32_t)node);
 }

 return NO_ERROR;
 }

 case FREE_NODE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();

            reply->writeInt32(freeNode(node));

 return NO_ERROR;
 }

 case SEND_COMMAND:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();

            OMX_COMMANDTYPE cmd =
 static_cast<OMX_COMMANDTYPE>(data.readInt32());

            OMX_S32 param = data.readInt32();
            reply->writeInt32(sendCommand(node, cmd, param));

 return NO_ERROR;
 }

 case GET_PARAMETER:
 case SET_PARAMETER:
 case GET_CONFIG:
 case SET_CONFIG:
 case SET_INTERNAL_OPTION:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());

 size_t size = data.readInt64();

 void *params = malloc(size);
            data.read(params, size);

 status_t err;
 switch (code) {
 case GET_PARAMETER:
                    err = getParameter(node, index, params, size);
 break;
 case SET_PARAMETER:
                    err = setParameter(node, index, params, size);
 break;
 case GET_CONFIG:
                    err = getConfig(node, index, params, size);
 break;
 case SET_CONFIG:
                    err = setConfig(node, index, params, size);
 break;
 case SET_INTERNAL_OPTION:
 {
 InternalOptionType type =
 (InternalOptionType)data.readInt32();

                    err = setInternalOption(node, index, type, params, size);
 break;
 }

 default:
                    TRESPASS();
 }

            reply->writeInt32(err);

 if ((code == GET_PARAMETER || code == GET_CONFIG) && err == OK) {
                reply->write(params, size);
 }

            free(params);
            params = NULL;

 return NO_ERROR;
 }

 case GET_STATE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_STATETYPE state = OMX_StateInvalid;

 status_t err = getState(node, &state);
            reply->writeInt32(state);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case ENABLE_GRAPHIC_BUFFERS:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            OMX_BOOL enable = (OMX_BOOL)data.readInt32();

 status_t err = enableGraphicBuffers(node, port_index, enable);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case GET_GRAPHIC_BUFFER_USAGE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();

            OMX_U32 usage = 0;
 status_t err = getGraphicBufferUsage(node, port_index, &usage);
            reply->writeInt32(err);
            reply->writeInt32(usage);

 return NO_ERROR;
 }

 case USE_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            sp<IMemory> params =
                interface_cast<IMemory>(data.readStrongBinder());
            OMX_U32 allottedSize = data.readInt32();

            buffer_id buffer;
 status_t err = useBuffer(node, port_index, params, &buffer, allottedSize);
            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32((int32_t)buffer);
 }

 return NO_ERROR;
 }

 case USE_GRAPHIC_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
            data.read(*graphicBuffer);

            buffer_id buffer;
 status_t err = useGraphicBuffer(
                    node, port_index, graphicBuffer, &buffer);
            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32((int32_t)buffer);
 }

 return NO_ERROR;
 }

 case UPDATE_GRAPHIC_BUFFER_IN_META:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
            data.read(*graphicBuffer);
            buffer_id buffer = (buffer_id)data.readInt32();

 status_t err = updateGraphicBufferInMeta(
                    node, port_index, graphicBuffer, buffer);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case CREATE_INPUT_SURFACE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();

             OMX_U32 port_index = data.readInt32();

             sp<IGraphicBufferProducer> bufferProducer;
            MetadataBufferType type;
             status_t err = createInputSurface(node, port_index, &bufferProducer, &type);

             reply->writeInt32(type);
             reply->writeInt32(err);

 if (err == OK) {
                reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
 }

 return NO_ERROR;
 }

 case CREATE_PERSISTENT_INPUT_SURFACE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            sp<IGraphicBufferProducer> bufferProducer;
            sp<IGraphicBufferConsumer> bufferConsumer;
 status_t err = createPersistentInputSurface(
 &bufferProducer, &bufferConsumer);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
                reply->writeStrongBinder(IInterface::asBinder(bufferConsumer));
 }

 return NO_ERROR;
 }

 case SET_INPUT_SURFACE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();

             sp<IGraphicBufferConsumer> bufferConsumer =
                     interface_cast<IGraphicBufferConsumer>(data.readStrongBinder());

            MetadataBufferType type;
             status_t err = setInputSurface(node, port_index, bufferConsumer, &type);

             reply->writeInt32(type);
             reply->writeInt32(err);
             return NO_ERROR;
 }

 case SIGNAL_END_OF_INPUT_STREAM:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();

 status_t err = signalEndOfInputStream(node);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case STORE_META_DATA_IN_BUFFERS:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();

             OMX_U32 port_index = data.readInt32();
             OMX_BOOL enable = (OMX_BOOL)data.readInt32();

            MetadataBufferType type;
             status_t err = storeMetaDataInBuffers(node, port_index, enable, &type);
             reply->writeInt32(type);
             reply->writeInt32(err);

 return NO_ERROR;
 }

 case PREPARE_FOR_ADAPTIVE_PLAYBACK:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            OMX_BOOL enable = (OMX_BOOL)data.readInt32();
            OMX_U32 max_width = data.readInt32();
            OMX_U32 max_height = data.readInt32();

 status_t err = prepareForAdaptivePlayback(
                    node, port_index, enable, max_width, max_height);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case CONFIGURE_VIDEO_TUNNEL_MODE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            OMX_BOOL tunneled = (OMX_BOOL)data.readInt32();
            OMX_U32 audio_hw_sync = data.readInt32();

 native_handle_t *sideband_handle = NULL;
 status_t err = configureVideoTunnelMode(
                    node, port_index, tunneled, audio_hw_sync, &sideband_handle);
            reply->writeInt32(err);
 if(err == OK){
                reply->writeNativeHandle(sideband_handle);
 }

 return NO_ERROR;
 }

 case ALLOC_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
 if (!isSecure(node) || port_index != 0 /* kPortIndexInput */) {
                ALOGE("b/24310423");
                reply->writeInt32(INVALID_OPERATION);
 return NO_ERROR;
 }

 size_t size = data.readInt64();

            buffer_id buffer;
 void *buffer_data;
 status_t err = allocateBuffer(
                    node, port_index, size, &buffer, &buffer_data);
            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32((int32_t)buffer);
                reply->writeInt64((uintptr_t)buffer_data);
 }

 return NO_ERROR;
 }

 case ALLOC_BUFFER_WITH_BACKUP:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            sp<IMemory> params =
                interface_cast<IMemory>(data.readStrongBinder());
            OMX_U32 allottedSize = data.readInt32();

            buffer_id buffer;
 status_t err = allocateBufferWithBackup(
                    node, port_index, params, &buffer, allottedSize);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32((int32_t)buffer);
 }

 return NO_ERROR;
 }

 case FREE_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            buffer_id buffer = (buffer_id)data.readInt32();
            reply->writeInt32(freeBuffer(node, port_index, buffer));

 return NO_ERROR;
 }

 case FILL_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            buffer_id buffer = (buffer_id)data.readInt32();
 bool haveFence = data.readInt32();
 int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
            reply->writeInt32(fillBuffer(node, buffer, fenceFd));

 return NO_ERROR;
 }

 case EMPTY_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            buffer_id buffer = (buffer_id)data.readInt32();
            OMX_U32 range_offset = data.readInt32();
            OMX_U32 range_length = data.readInt32();
            OMX_U32 flags = data.readInt32();
            OMX_TICKS timestamp = data.readInt64();
 bool haveFence = data.readInt32();
 int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
            reply->writeInt32(emptyBuffer(
                    node, buffer, range_offset, range_length, flags, timestamp, fenceFd));

 return NO_ERROR;
 }

 case GET_EXTENSION_INDEX:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
 const char *parameter_name = data.readCString();

            OMX_INDEXTYPE index;
 status_t err = getExtensionIndex(node, parameter_name, &index);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32(index);
 }

 return OK;
 }

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

media/libmedia/IOMX.cpp in mediaserver in Android 6.x before 2016-04-01 does not initialize certain metadata buffer pointers, which allows attackers to obtain sensitive information from process memory, and consequently bypass an unspecified protection mechanism, via unspecified vectors, as demonstrated by obtaining Signature or SignatureOrSystem access, aka internal bug 26324358.


status_t BnOMX::onTransact(
 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
 switch (code) {
 case LIVES_LOCALLY:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);
            node_id node = (node_id)data.readInt32();
 pid_t pid = (pid_t)data.readInt32();
            reply->writeInt32(livesLocally(node, pid));

 return OK;
 }

 case LIST_NODES:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

 List<ComponentInfo> list;
            listNodes(&list);

            reply->writeInt32(list.size());
 for (List<ComponentInfo>::iterator it = list.begin();
                 it != list.end(); ++it) {
 ComponentInfo &cur = *it;

                reply->writeString8(cur.mName);
                reply->writeInt32(cur.mRoles.size());
 for (List<String8>::iterator role_it = cur.mRoles.begin();
                     role_it != cur.mRoles.end(); ++role_it) {
                    reply->writeString8(*role_it);
 }
 }

 return NO_ERROR;
 }

 case ALLOCATE_NODE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

 const char *name = data.readCString();

            sp<IOMXObserver> observer =
                interface_cast<IOMXObserver>(data.readStrongBinder());

            node_id node;

 status_t err = allocateNode(name, observer, &node);
            reply->writeInt32(err);
 if (err == OK) {
                reply->writeInt32((int32_t)node);
 }

 return NO_ERROR;
 }

 case FREE_NODE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();

            reply->writeInt32(freeNode(node));

 return NO_ERROR;
 }

 case SEND_COMMAND:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();

            OMX_COMMANDTYPE cmd =
 static_cast<OMX_COMMANDTYPE>(data.readInt32());

            OMX_S32 param = data.readInt32();
            reply->writeInt32(sendCommand(node, cmd, param));

 return NO_ERROR;
 }

 case GET_PARAMETER:
 case SET_PARAMETER:
 case GET_CONFIG:
 case SET_CONFIG:
 case SET_INTERNAL_OPTION:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());

 size_t size = data.readInt64();

 void *params = malloc(size);
            data.read(params, size);

 status_t err;
 switch (code) {
 case GET_PARAMETER:
                    err = getParameter(node, index, params, size);
 break;
 case SET_PARAMETER:
                    err = setParameter(node, index, params, size);
 break;
 case GET_CONFIG:
                    err = getConfig(node, index, params, size);
 break;
 case SET_CONFIG:
                    err = setConfig(node, index, params, size);
 break;
 case SET_INTERNAL_OPTION:
 {
 InternalOptionType type =
 (InternalOptionType)data.readInt32();

                    err = setInternalOption(node, index, type, params, size);
 break;
 }

 default:
                    TRESPASS();
 }

            reply->writeInt32(err);

 if ((code == GET_PARAMETER || code == GET_CONFIG) && err == OK) {
                reply->write(params, size);
 }

            free(params);
            params = NULL;

 return NO_ERROR;
 }

 case GET_STATE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_STATETYPE state = OMX_StateInvalid;

 status_t err = getState(node, &state);
            reply->writeInt32(state);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case ENABLE_GRAPHIC_BUFFERS:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            OMX_BOOL enable = (OMX_BOOL)data.readInt32();

 status_t err = enableGraphicBuffers(node, port_index, enable);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case GET_GRAPHIC_BUFFER_USAGE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();

            OMX_U32 usage = 0;
 status_t err = getGraphicBufferUsage(node, port_index, &usage);
            reply->writeInt32(err);
            reply->writeInt32(usage);

 return NO_ERROR;
 }

 case USE_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            sp<IMemory> params =
                interface_cast<IMemory>(data.readStrongBinder());
            OMX_U32 allottedSize = data.readInt32();

            buffer_id buffer;
 status_t err = useBuffer(node, port_index, params, &buffer, allottedSize);
            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32((int32_t)buffer);
 }

 return NO_ERROR;
 }

 case USE_GRAPHIC_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
            data.read(*graphicBuffer);

            buffer_id buffer;
 status_t err = useGraphicBuffer(
                    node, port_index, graphicBuffer, &buffer);
            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32((int32_t)buffer);
 }

 return NO_ERROR;
 }

 case UPDATE_GRAPHIC_BUFFER_IN_META:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
            data.read(*graphicBuffer);
            buffer_id buffer = (buffer_id)data.readInt32();

 status_t err = updateGraphicBufferInMeta(
                    node, port_index, graphicBuffer, buffer);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case CREATE_INPUT_SURFACE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();

             OMX_U32 port_index = data.readInt32();

             sp<IGraphicBufferProducer> bufferProducer;
            MetadataBufferType type = kMetadataBufferTypeInvalid;
             status_t err = createInputSurface(node, port_index, &bufferProducer, &type);

            if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
                android_errorWriteLog(0x534e4554, "26324358");
            }

             reply->writeInt32(type);
             reply->writeInt32(err);

 if (err == OK) {
                reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
 }

 return NO_ERROR;
 }

 case CREATE_PERSISTENT_INPUT_SURFACE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            sp<IGraphicBufferProducer> bufferProducer;
            sp<IGraphicBufferConsumer> bufferConsumer;
 status_t err = createPersistentInputSurface(
 &bufferProducer, &bufferConsumer);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
                reply->writeStrongBinder(IInterface::asBinder(bufferConsumer));
 }

 return NO_ERROR;
 }

 case SET_INPUT_SURFACE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();

             sp<IGraphicBufferConsumer> bufferConsumer =
                     interface_cast<IGraphicBufferConsumer>(data.readStrongBinder());

            MetadataBufferType type = kMetadataBufferTypeInvalid;
             status_t err = setInputSurface(node, port_index, bufferConsumer, &type);

            if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
                android_errorWriteLog(0x534e4554, "26324358");
            }

             reply->writeInt32(type);
             reply->writeInt32(err);
             return NO_ERROR;
 }

 case SIGNAL_END_OF_INPUT_STREAM:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();

 status_t err = signalEndOfInputStream(node);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case STORE_META_DATA_IN_BUFFERS:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();

             OMX_U32 port_index = data.readInt32();
             OMX_BOOL enable = (OMX_BOOL)data.readInt32();

            MetadataBufferType type = kMetadataBufferTypeInvalid;
             status_t err = storeMetaDataInBuffers(node, port_index, enable, &type);

            if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
                android_errorWriteLog(0x534e4554, "26324358");
            }

             reply->writeInt32(type);
             reply->writeInt32(err);

 return NO_ERROR;
 }

 case PREPARE_FOR_ADAPTIVE_PLAYBACK:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            OMX_BOOL enable = (OMX_BOOL)data.readInt32();
            OMX_U32 max_width = data.readInt32();
            OMX_U32 max_height = data.readInt32();

 status_t err = prepareForAdaptivePlayback(
                    node, port_index, enable, max_width, max_height);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case CONFIGURE_VIDEO_TUNNEL_MODE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            OMX_BOOL tunneled = (OMX_BOOL)data.readInt32();
            OMX_U32 audio_hw_sync = data.readInt32();

 native_handle_t *sideband_handle = NULL;
 status_t err = configureVideoTunnelMode(
                    node, port_index, tunneled, audio_hw_sync, &sideband_handle);
            reply->writeInt32(err);
 if(err == OK){
                reply->writeNativeHandle(sideband_handle);
 }

 return NO_ERROR;
 }

 case ALLOC_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
 if (!isSecure(node) || port_index != 0 /* kPortIndexInput */) {
                ALOGE("b/24310423");
                reply->writeInt32(INVALID_OPERATION);
 return NO_ERROR;
 }

 size_t size = data.readInt64();

            buffer_id buffer;
 void *buffer_data;
 status_t err = allocateBuffer(
                    node, port_index, size, &buffer, &buffer_data);
            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32((int32_t)buffer);
                reply->writeInt64((uintptr_t)buffer_data);
 }

 return NO_ERROR;
 }

 case ALLOC_BUFFER_WITH_BACKUP:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            sp<IMemory> params =
                interface_cast<IMemory>(data.readStrongBinder());
            OMX_U32 allottedSize = data.readInt32();

            buffer_id buffer;
 status_t err = allocateBufferWithBackup(
                    node, port_index, params, &buffer, allottedSize);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32((int32_t)buffer);
 }

 return NO_ERROR;
 }

 case FREE_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            buffer_id buffer = (buffer_id)data.readInt32();
            reply->writeInt32(freeBuffer(node, port_index, buffer));

 return NO_ERROR;
 }

 case FILL_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            buffer_id buffer = (buffer_id)data.readInt32();
 bool haveFence = data.readInt32();
 int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
            reply->writeInt32(fillBuffer(node, buffer, fenceFd));

 return NO_ERROR;
 }

 case EMPTY_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            buffer_id buffer = (buffer_id)data.readInt32();
            OMX_U32 range_offset = data.readInt32();
            OMX_U32 range_length = data.readInt32();
            OMX_U32 flags = data.readInt32();
            OMX_TICKS timestamp = data.readInt64();
 bool haveFence = data.readInt32();
 int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
            reply->writeInt32(emptyBuffer(
                    node, buffer, range_offset, range_length, flags, timestamp, fenceFd));

 return NO_ERROR;
 }

 case GET_EXTENSION_INDEX:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
 const char *parameter_name = data.readCString();

            OMX_INDEXTYPE index;
 status_t err = getExtensionIndex(node, parameter_name, &index);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32(index);
 }

 return OK;
 }

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


status_t BnOMX::onTransact(
 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
 switch (code) {
 case LIVES_LOCALLY:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);
            node_id node = (node_id)data.readInt32();
 pid_t pid = (pid_t)data.readInt32();
            reply->writeInt32(livesLocally(node, pid));

 return OK;
 }

 case LIST_NODES:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

 List<ComponentInfo> list;
            listNodes(&list);

            reply->writeInt32(list.size());
 for (List<ComponentInfo>::iterator it = list.begin();
                 it != list.end(); ++it) {
 ComponentInfo &cur = *it;

                reply->writeString8(cur.mName);
                reply->writeInt32(cur.mRoles.size());
 for (List<String8>::iterator role_it = cur.mRoles.begin();
                     role_it != cur.mRoles.end(); ++role_it) {
                    reply->writeString8(*role_it);
 }
 }

 return NO_ERROR;
 }

 case ALLOCATE_NODE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

 const char *name = data.readCString();

            sp<IOMXObserver> observer =
                interface_cast<IOMXObserver>(data.readStrongBinder());

            node_id node;

 status_t err = allocateNode(name, observer, &node);
            reply->writeInt32(err);
 if (err == OK) {
                reply->writeInt32((int32_t)node);
 }

 return NO_ERROR;
 }

 case FREE_NODE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();

            reply->writeInt32(freeNode(node));

 return NO_ERROR;
 }

 case SEND_COMMAND:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();

            OMX_COMMANDTYPE cmd =
 static_cast<OMX_COMMANDTYPE>(data.readInt32());

            OMX_S32 param = data.readInt32();
            reply->writeInt32(sendCommand(node, cmd, param));

 return NO_ERROR;
 }

 case GET_PARAMETER:
 case SET_PARAMETER:
 case GET_CONFIG:
 case SET_CONFIG:
 case SET_INTERNAL_OPTION:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());

             size_t size = data.readInt64();

            void *params = malloc(size);
            data.read(params, size);

            status_t err;
            switch (code) {
                case GET_PARAMETER:
                    err = getParameter(node, index, params, size);
                    break;
                case SET_PARAMETER:
                    err = setParameter(node, index, params, size);
                    break;
                case GET_CONFIG:
                    err = getConfig(node, index, params, size);
                    break;
                case SET_CONFIG:
                    err = setConfig(node, index, params, size);
                    break;
                case SET_INTERNAL_OPTION:
                {
                    InternalOptionType type =
                        (InternalOptionType)data.readInt32();

                    err = setInternalOption(node, index, type, params, size);
                    break;
                 }
                default:
                    TRESPASS();
             }

             reply->writeInt32(err);

 if ((code == GET_PARAMETER || code == GET_CONFIG) && err == OK) {
                reply->write(params, size);
 }

            free(params);
            params = NULL;

 return NO_ERROR;
 }

 case GET_STATE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_STATETYPE state = OMX_StateInvalid;

 status_t err = getState(node, &state);
            reply->writeInt32(state);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case ENABLE_GRAPHIC_BUFFERS:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            OMX_BOOL enable = (OMX_BOOL)data.readInt32();

 status_t err = enableGraphicBuffers(node, port_index, enable);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case GET_GRAPHIC_BUFFER_USAGE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();

            OMX_U32 usage = 0;
 status_t err = getGraphicBufferUsage(node, port_index, &usage);
            reply->writeInt32(err);
            reply->writeInt32(usage);

 return NO_ERROR;
 }

 case USE_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            sp<IMemory> params =
                interface_cast<IMemory>(data.readStrongBinder());

            buffer_id buffer;
 status_t err = useBuffer(node, port_index, params, &buffer);
            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32((int32_t)buffer);
 }

 return NO_ERROR;
 }

 case USE_GRAPHIC_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
            data.read(*graphicBuffer);

            buffer_id buffer;
 status_t err = useGraphicBuffer(
                    node, port_index, graphicBuffer, &buffer);
            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32((int32_t)buffer);
 }

 return NO_ERROR;
 }

 case UPDATE_GRAPHIC_BUFFER_IN_META:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
            data.read(*graphicBuffer);
            buffer_id buffer = (buffer_id)data.readInt32();

 status_t err = updateGraphicBufferInMeta(
                    node, port_index, graphicBuffer, buffer);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case CREATE_INPUT_SURFACE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();

            sp<IGraphicBufferProducer> bufferProducer;
 status_t err = createInputSurface(node, port_index,
 &bufferProducer);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeStrongBinder(bufferProducer->asBinder());
 }

 return NO_ERROR;
 }

 case SIGNAL_END_OF_INPUT_STREAM:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();

 status_t err = signalEndOfInputStream(node);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case STORE_META_DATA_IN_BUFFERS:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            OMX_BOOL enable = (OMX_BOOL)data.readInt32();

 status_t err = storeMetaDataInBuffers(node, port_index, enable);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case PREPARE_FOR_ADAPTIVE_PLAYBACK:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            OMX_BOOL enable = (OMX_BOOL)data.readInt32();
            OMX_U32 max_width = data.readInt32();
            OMX_U32 max_height = data.readInt32();

 status_t err = prepareForAdaptivePlayback(
                    node, port_index, enable, max_width, max_height);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case CONFIGURE_VIDEO_TUNNEL_MODE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            OMX_BOOL tunneled = (OMX_BOOL)data.readInt32();
            OMX_U32 audio_hw_sync = data.readInt32();

 native_handle_t *sideband_handle = NULL;
 status_t err = configureVideoTunnelMode(
                    node, port_index, tunneled, audio_hw_sync, &sideband_handle);
            reply->writeInt32(err);
 if(err == OK){
                reply->writeNativeHandle(sideband_handle);
 }

 return NO_ERROR;
 }

 case ALLOC_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
 if (!isSecure(node) || port_index != 0 /* kPortIndexInput */) {
                ALOGE("b/24310423");
                reply->writeInt32(INVALID_OPERATION);
 return NO_ERROR;
 }

 size_t size = data.readInt64();

            buffer_id buffer;
 void *buffer_data;
 status_t err = allocateBuffer(
                    node, port_index, size, &buffer, &buffer_data);
            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32((int32_t)buffer);
                reply->writeInt64((uintptr_t)buffer_data);
 }

 return NO_ERROR;
 }

 case ALLOC_BUFFER_WITH_BACKUP:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            sp<IMemory> params =
                interface_cast<IMemory>(data.readStrongBinder());

            buffer_id buffer;
 status_t err = allocateBufferWithBackup(
                    node, port_index, params, &buffer);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32((int32_t)buffer);
 }

 return NO_ERROR;
 }

 case FREE_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            buffer_id buffer = (buffer_id)data.readInt32();
            reply->writeInt32(freeBuffer(node, port_index, buffer));

 return NO_ERROR;
 }

 case FILL_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            buffer_id buffer = (buffer_id)data.readInt32();
            reply->writeInt32(fillBuffer(node, buffer));

 return NO_ERROR;
 }

 case EMPTY_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            buffer_id buffer = (buffer_id)data.readInt32();
            OMX_U32 range_offset = data.readInt32();
            OMX_U32 range_length = data.readInt32();
            OMX_U32 flags = data.readInt32();
            OMX_TICKS timestamp = data.readInt64();

            reply->writeInt32(
                    emptyBuffer(
                        node, buffer, range_offset, range_length,
                        flags, timestamp));

 return NO_ERROR;
 }

 case GET_EXTENSION_INDEX:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
 const char *parameter_name = data.readCString();

            OMX_INDEXTYPE index;
 status_t err = getExtensionIndex(node, parameter_name, &index);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32(index);
 }

 return OK;
 }

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

media/libmedia/IOMX.cpp 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-04-01 does not initialize a parameter data structure, which allows attackers to obtain sensitive information from process memory, and consequently bypass an unspecified protection mechanism, via unspecified vectors, as demonstrated by obtaining Signature or SignatureOrSystem access, aka internal bug 26914474.


status_t BnOMX::onTransact(
 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
 switch (code) {
 case LIVES_LOCALLY:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);
            node_id node = (node_id)data.readInt32();
 pid_t pid = (pid_t)data.readInt32();
            reply->writeInt32(livesLocally(node, pid));

 return OK;
 }

 case LIST_NODES:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

 List<ComponentInfo> list;
            listNodes(&list);

            reply->writeInt32(list.size());
 for (List<ComponentInfo>::iterator it = list.begin();
                 it != list.end(); ++it) {
 ComponentInfo &cur = *it;

                reply->writeString8(cur.mName);
                reply->writeInt32(cur.mRoles.size());
 for (List<String8>::iterator role_it = cur.mRoles.begin();
                     role_it != cur.mRoles.end(); ++role_it) {
                    reply->writeString8(*role_it);
 }
 }

 return NO_ERROR;
 }

 case ALLOCATE_NODE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

 const char *name = data.readCString();

            sp<IOMXObserver> observer =
                interface_cast<IOMXObserver>(data.readStrongBinder());

            node_id node;

 status_t err = allocateNode(name, observer, &node);
            reply->writeInt32(err);
 if (err == OK) {
                reply->writeInt32((int32_t)node);
 }

 return NO_ERROR;
 }

 case FREE_NODE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();

            reply->writeInt32(freeNode(node));

 return NO_ERROR;
 }

 case SEND_COMMAND:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();

            OMX_COMMANDTYPE cmd =
 static_cast<OMX_COMMANDTYPE>(data.readInt32());

            OMX_S32 param = data.readInt32();
            reply->writeInt32(sendCommand(node, cmd, param));

 return NO_ERROR;
 }

 case GET_PARAMETER:
 case SET_PARAMETER:
 case GET_CONFIG:
 case SET_CONFIG:
 case SET_INTERNAL_OPTION:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());

             size_t size = data.readInt64();

            status_t err = NO_MEMORY;
            void *params = calloc(size, 1);
            if (params) {
                err = data.read(params, size);
                if (err != OK) {
                    android_errorWriteLog(0x534e4554, "26914474");
                } else {
                    switch (code) {
                        case GET_PARAMETER:
                            err = getParameter(node, index, params, size);
                            break;
                        case SET_PARAMETER:
                            err = setParameter(node, index, params, size);
                            break;
                        case GET_CONFIG:
                            err = getConfig(node, index, params, size);
                            break;
                        case SET_CONFIG:
                            err = setConfig(node, index, params, size);
                            break;
                        case SET_INTERNAL_OPTION:
                        {
                            InternalOptionType type =
                                (InternalOptionType)data.readInt32();

                            err = setInternalOption(node, index, type, params, size);
                            break;
                        }

                        default:
                            TRESPASS();
                    }
                 }
             }

             reply->writeInt32(err);

 if ((code == GET_PARAMETER || code == GET_CONFIG) && err == OK) {
                reply->write(params, size);
 }

            free(params);
            params = NULL;

 return NO_ERROR;
 }

 case GET_STATE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_STATETYPE state = OMX_StateInvalid;

 status_t err = getState(node, &state);
            reply->writeInt32(state);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case ENABLE_GRAPHIC_BUFFERS:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            OMX_BOOL enable = (OMX_BOOL)data.readInt32();

 status_t err = enableGraphicBuffers(node, port_index, enable);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case GET_GRAPHIC_BUFFER_USAGE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();

            OMX_U32 usage = 0;
 status_t err = getGraphicBufferUsage(node, port_index, &usage);
            reply->writeInt32(err);
            reply->writeInt32(usage);

 return NO_ERROR;
 }

 case USE_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            sp<IMemory> params =
                interface_cast<IMemory>(data.readStrongBinder());

            buffer_id buffer;
 status_t err = useBuffer(node, port_index, params, &buffer);
            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32((int32_t)buffer);
 }

 return NO_ERROR;
 }

 case USE_GRAPHIC_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
            data.read(*graphicBuffer);

            buffer_id buffer;
 status_t err = useGraphicBuffer(
                    node, port_index, graphicBuffer, &buffer);
            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32((int32_t)buffer);
 }

 return NO_ERROR;
 }

 case UPDATE_GRAPHIC_BUFFER_IN_META:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
            data.read(*graphicBuffer);
            buffer_id buffer = (buffer_id)data.readInt32();

 status_t err = updateGraphicBufferInMeta(
                    node, port_index, graphicBuffer, buffer);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case CREATE_INPUT_SURFACE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();

            sp<IGraphicBufferProducer> bufferProducer;
 status_t err = createInputSurface(node, port_index,
 &bufferProducer);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeStrongBinder(bufferProducer->asBinder());
 }

 return NO_ERROR;
 }

 case SIGNAL_END_OF_INPUT_STREAM:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();

 status_t err = signalEndOfInputStream(node);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case STORE_META_DATA_IN_BUFFERS:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            OMX_BOOL enable = (OMX_BOOL)data.readInt32();

 status_t err = storeMetaDataInBuffers(node, port_index, enable);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case PREPARE_FOR_ADAPTIVE_PLAYBACK:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            OMX_BOOL enable = (OMX_BOOL)data.readInt32();
            OMX_U32 max_width = data.readInt32();
            OMX_U32 max_height = data.readInt32();

 status_t err = prepareForAdaptivePlayback(
                    node, port_index, enable, max_width, max_height);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case CONFIGURE_VIDEO_TUNNEL_MODE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            OMX_BOOL tunneled = (OMX_BOOL)data.readInt32();
            OMX_U32 audio_hw_sync = data.readInt32();

 native_handle_t *sideband_handle = NULL;
 status_t err = configureVideoTunnelMode(
                    node, port_index, tunneled, audio_hw_sync, &sideband_handle);
            reply->writeInt32(err);
 if(err == OK){
                reply->writeNativeHandle(sideband_handle);
 }

 return NO_ERROR;
 }

 case ALLOC_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
 if (!isSecure(node) || port_index != 0 /* kPortIndexInput */) {
                ALOGE("b/24310423");
                reply->writeInt32(INVALID_OPERATION);
 return NO_ERROR;
 }

 size_t size = data.readInt64();

            buffer_id buffer;
 void *buffer_data;
 status_t err = allocateBuffer(
                    node, port_index, size, &buffer, &buffer_data);
            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32((int32_t)buffer);
                reply->writeInt64((uintptr_t)buffer_data);
 }

 return NO_ERROR;
 }

 case ALLOC_BUFFER_WITH_BACKUP:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            sp<IMemory> params =
                interface_cast<IMemory>(data.readStrongBinder());

            buffer_id buffer;
 status_t err = allocateBufferWithBackup(
                    node, port_index, params, &buffer);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32((int32_t)buffer);
 }

 return NO_ERROR;
 }

 case FREE_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            buffer_id buffer = (buffer_id)data.readInt32();
            reply->writeInt32(freeBuffer(node, port_index, buffer));

 return NO_ERROR;
 }

 case FILL_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            buffer_id buffer = (buffer_id)data.readInt32();
            reply->writeInt32(fillBuffer(node, buffer));

 return NO_ERROR;
 }

 case EMPTY_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            buffer_id buffer = (buffer_id)data.readInt32();
            OMX_U32 range_offset = data.readInt32();
            OMX_U32 range_length = data.readInt32();
            OMX_U32 flags = data.readInt32();
            OMX_TICKS timestamp = data.readInt64();

            reply->writeInt32(
                    emptyBuffer(
                        node, buffer, range_offset, range_length,
                        flags, timestamp));

 return NO_ERROR;
 }

 case GET_EXTENSION_INDEX:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
 const char *parameter_name = data.readCString();

            OMX_INDEXTYPE index;
 status_t err = getExtensionIndex(node, parameter_name, &index);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32(index);
 }

 return OK;
 }

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


void BufferQueueConsumer::dump(String8& result, const char* prefix) const {
 const IPCThreadState* ipc = IPCThreadState::self();
 const pid_t pid = ipc->getCallingPid();
 const uid_t uid = ipc->getCallingUid();
 if ((uid != AID_SHELL)
 && !PermissionCache::checkPermission(String16(

             "android.permission.DUMP"), pid, uid)) {
         result.appendFormat("Permission Denial: can't dump BufferQueueConsumer "
                 "from pid=%d, uid=%d\n", pid, uid);
     } else {
         mCore->dump(result, prefix);
     }
}

libs/gui/BufferQueueConsumer.cpp 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-04-01 does not check for the android.permission.DUMP permission, which allows attackers to obtain sensitive information, and consequently bypass an unspecified protection mechanism, via a dump request, as demonstrated by obtaining Signature or SignatureOrSystem access, aka internal bug 27046057.


void BufferQueueConsumer::dump(String8& result, const char* prefix) const {
 const IPCThreadState* ipc = IPCThreadState::self();
 const pid_t pid = ipc->getCallingPid();
 const uid_t uid = ipc->getCallingUid();
 if ((uid != AID_SHELL)
 && !PermissionCache::checkPermission(String16(

             "android.permission.DUMP"), pid, uid)) {
         result.appendFormat("Permission Denial: can't dump BufferQueueConsumer "
                 "from pid=%d, uid=%d\n", pid, uid);
        android_errorWriteWithInfoLog(0x534e4554, "27046057", uid, NULL, 0);
     } else {
         mCore->dump(result, prefix);
     }
}


void SoftVPX::onQueueFilled(OMX_U32 /* portIndex */) {
 if (mOutputPortSettingsChange != NONE) {
 return;
 }

 List<BufferInfo *> &inQueue = getPortQueue(0);
 List<BufferInfo *> &outQueue = getPortQueue(1);
 bool EOSseen = false;

 while (!inQueue.empty() && !outQueue.empty()) {
 BufferInfo *inInfo = *inQueue.begin();
        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;

 BufferInfo *outInfo = *outQueue.begin();
        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;

 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
 EOSseen = true;
 if (inHeader->nFilledLen == 0) {
                inQueue.erase(inQueue.begin());
                inInfo->mOwnedByUs = false;
                notifyEmptyBufferDone(inHeader);

                outHeader->nFilledLen = 0;
                outHeader->nFlags = OMX_BUFFERFLAG_EOS;

                outQueue.erase(outQueue.begin());
                outInfo->mOwnedByUs = false;
                notifyFillBufferDone(outHeader);
 return;
 }
 }

 if (mImg == NULL) {
 if (vpx_codec_decode(
 (vpx_codec_ctx_t *)mCtx,
                        inHeader->pBuffer + inHeader->nOffset,
                        inHeader->nFilledLen,
                        NULL,
 0)) {
                ALOGE("on2 decoder failed to decode frame.");

                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
 return;
 }
 vpx_codec_iter_t iter = NULL;
            mImg = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter);

         }

         if (mImg != NULL) {
            CHECK_EQ(mImg->fmt, IMG_FMT_I420);

             uint32_t width = mImg->d_w;
             uint32_t height = mImg->d_h;
 bool portWillReset = false;
            handlePortSettingsChange(&portWillReset, width, height);
 if (portWillReset) {
 return;
 }

            outHeader->nOffset = 0;
            outHeader->nFilledLen = (outputBufferWidth() * outputBufferHeight() * 3) / 2;
            outHeader->nFlags = EOSseen ? OMX_BUFFERFLAG_EOS : 0;

             outHeader->nTimeStamp = inHeader->nTimeStamp;

             uint8_t *dst = outHeader->pBuffer;
            const uint8_t *srcY = (const uint8_t *)mImg->planes[PLANE_Y];
            const uint8_t *srcU = (const uint8_t *)mImg->planes[PLANE_U];
            const uint8_t *srcV = (const uint8_t *)mImg->planes[PLANE_V];
            size_t srcYStride = mImg->stride[PLANE_Y];
            size_t srcUStride = mImg->stride[PLANE_U];
            size_t srcVStride = mImg->stride[PLANE_V];
             copyYV12FrameToOutputBuffer(dst, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride);

             mImg = NULL;
            outInfo->mOwnedByUs = false;
            outQueue.erase(outQueue.begin());
            outInfo = NULL;
            notifyFillBufferDone(outHeader);
            outHeader = NULL;
 }

        inInfo->mOwnedByUs = false;
        inQueue.erase(inQueue.begin());
        inInfo = NULL;
        notifyEmptyBufferDone(inHeader);
        inHeader = NULL;
 }
}

libvpx in mediaserver in Android 4.x before 4.4.4, 5.x before 5.1.1 LMY49H, and 6.0 before 2016-03-01 allows remote attackers to execute arbitrary code or cause a denial of service (memory corruption) via a crafted media file, related to libwebm/mkvparser.cpp and other files, aka internal bug 23452792.


void SoftVPX::onQueueFilled(OMX_U32 /* portIndex */) {
 if (mOutputPortSettingsChange != NONE) {
 return;
 }

 List<BufferInfo *> &inQueue = getPortQueue(0);
 List<BufferInfo *> &outQueue = getPortQueue(1);
 bool EOSseen = false;

 while (!inQueue.empty() && !outQueue.empty()) {
 BufferInfo *inInfo = *inQueue.begin();
        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;

 BufferInfo *outInfo = *outQueue.begin();
        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;

 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
 EOSseen = true;
 if (inHeader->nFilledLen == 0) {
                inQueue.erase(inQueue.begin());
                inInfo->mOwnedByUs = false;
                notifyEmptyBufferDone(inHeader);

                outHeader->nFilledLen = 0;
                outHeader->nFlags = OMX_BUFFERFLAG_EOS;

                outQueue.erase(outQueue.begin());
                outInfo->mOwnedByUs = false;
                notifyFillBufferDone(outHeader);
 return;
 }
 }

 if (mImg == NULL) {
 if (vpx_codec_decode(
 (vpx_codec_ctx_t *)mCtx,
                        inHeader->pBuffer + inHeader->nOffset,
                        inHeader->nFilledLen,
                        NULL,
 0)) {
                ALOGE("on2 decoder failed to decode frame.");

                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
 return;
 }
 vpx_codec_iter_t iter = NULL;
            mImg = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter);

         }

         if (mImg != NULL) {
            CHECK_EQ(mImg->fmt, VPX_IMG_FMT_I420);

             uint32_t width = mImg->d_w;
             uint32_t height = mImg->d_h;
 bool portWillReset = false;
            handlePortSettingsChange(&portWillReset, width, height);
 if (portWillReset) {
 return;
 }

            outHeader->nOffset = 0;
            outHeader->nFilledLen = (outputBufferWidth() * outputBufferHeight() * 3) / 2;
            outHeader->nFlags = EOSseen ? OMX_BUFFERFLAG_EOS : 0;

             outHeader->nTimeStamp = inHeader->nTimeStamp;

             uint8_t *dst = outHeader->pBuffer;
            const uint8_t *srcY = (const uint8_t *)mImg->planes[VPX_PLANE_Y];
            const uint8_t *srcU = (const uint8_t *)mImg->planes[VPX_PLANE_U];
            const uint8_t *srcV = (const uint8_t *)mImg->planes[VPX_PLANE_V];
            size_t srcYStride = mImg->stride[VPX_PLANE_Y];
            size_t srcUStride = mImg->stride[VPX_PLANE_U];
            size_t srcVStride = mImg->stride[VPX_PLANE_V];
             copyYV12FrameToOutputBuffer(dst, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride);

             mImg = NULL;
            outInfo->mOwnedByUs = false;
            outQueue.erase(outQueue.begin());
            outInfo = NULL;
            notifyFillBufferDone(outHeader);
            outHeader = NULL;
 }

        inInfo->mOwnedByUs = false;
        inQueue.erase(inQueue.begin());
        inInfo = NULL;
        notifyEmptyBufferDone(inHeader);
        inHeader = NULL;
 }
}


valid_length(uint8_t option, int dl, int *type)
{
 const struct dhcp_opt *opt;
 ssize_t sz;

 if (dl == 0)
 return -1;

 for (opt = dhcp_opts; opt->option; opt++) {
 if (opt->option != option)
 continue;

 		if (type)
 			*type = opt->type;
 		if (opt->type == 0 ||
 		    opt->type & (STRING | RFC3442 | RFC5969))
 			return 0;
 		sz = 0;
		if (opt->type & (UINT32 | IPV4))
 			sz = sizeof(uint32_t);
		if (opt->type & UINT16)
 			sz = sizeof(uint16_t);
		if (opt->type & UINT8)
 			sz = sizeof(uint8_t);
		if (opt->type & (IPV4 | ARRAY))
			return dl % sz;
		return (dl == sz ? 0 : -1);
 	}

 	/* unknown option, so let it pass */
 return 0;
}

dhcpcd before 6.10.0, as used 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-04-01 and other products, mismanages option lengths, which allows remote attackers to execute arbitrary code or cause a denial of service (heap-based buffer overflow) via a malformed DHCP response, aka internal bug 26461634.


valid_length(uint8_t option, int dl, int *type)
{
 const struct dhcp_opt *opt;
 ssize_t sz;

 if (dl == 0)
 return -1;

 for (opt = dhcp_opts; opt->option; opt++) {
 if (opt->option != option)
 continue;

 		if (type)
 			*type = opt->type;
		/* The size of RFC3442 and RFC5969 options is checked at a later
		 * stage in the code */
 		if (opt->type == 0 ||
 		    opt->type & (STRING | RFC3442 | RFC5969))
 			return 0;
		/* The code does not use SINT16 / SINT32 together with ARRAY.
		 * It is however far easier to reason about the code if all
		 * possible array elements are included, and also does not code
		 * any additional CPU resources. sizeof(uintXX_t) ==
		 * sizeof(intXX_t) can be assumed. */
 		sz = 0;
		if (opt->type & (UINT32 | SINT32 | IPV4))
 			sz = sizeof(uint32_t);
		else if (opt->type & (UINT16 | SINT16))
 			sz = sizeof(uint16_t);
		else if (opt->type & UINT8)
 			sz = sizeof(uint8_t);
		if (opt->type & ARRAY) {
			/* The result of modulo zero is undefined. There are no
			 * options defined in this file that do not match one of
			 * the if-clauses above, so the following is not really
			 * necessary. However, to avoid confusion and unexpected
			 * behavior if the defined options are ever extended,
			 * returning false here seems sensible. */
			if (!sz) return -1;
			return (dl % sz == 0) ? 0 : -1;
		}
		return (sz == dl) ? 0 : -1;
 	}

 	/* unknown option, so let it pass */
 return 0;
}


sp<IMemoryHeap> BpMemory::getMemory(ssize_t* offset, size_t* size) const
{
 if (mHeap == 0) {
 Parcel data, reply;
        data.writeInterfaceToken(IMemory::getInterfaceDescriptor());
 if (remote()->transact(GET_MEMORY, data, &reply) == NO_ERROR) {
            sp<IBinder> heap = reply.readStrongBinder();
 ssize_t o = reply.readInt32();
 size_t s = reply.readInt32();

             if (heap != 0) {
                 mHeap = interface_cast<IMemoryHeap>(heap);
                 if (mHeap != 0) {
                    mOffset = o;
                    mSize = s;
                 }
             }
         }
     }
     if (offset) *offset = mOffset;
     if (size) *size = mSize;
    return mHeap;
 }

libs/binder/IMemory.cpp in the IMemory Native Interface 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-04-01 does not properly consider the heap size, which allows attackers to gain privileges via a crafted application, as demonstrated by obtaining Signature or SignatureOrSystem access, aka internal bug 26877992.