diff options
author | Praveen Chavan <pchavan@codeaurora.org> | 2016-08-17 12:19:29 -0700 |
---|---|---|
committer | Bruno Martins <bgcngm@gmail.com> | 2018-04-14 21:05:17 +0100 |
commit | 58207a2eaaa5cdd7868358b79d7ffabc26c42bf4 (patch) | |
tree | 81d4e270054f3dd152c2605f1d4a13d2adbc24ee | |
parent | 2a2ce7e5512b7d9d4acbac8e49f4891c76d2cfc9 (diff) | |
download | android_hardware_qcom_media-58207a2eaaa5cdd7868358b79d7ffabc26c42bf4.tar.gz android_hardware_qcom_media-58207a2eaaa5cdd7868358b79d7ffabc26c42bf4.tar.bz2 android_hardware_qcom_media-58207a2eaaa5cdd7868358b79d7ffabc26c42bf4.zip |
mm-video-v4l2: vdec: Disallow changing buffer modes/counts on allocated ports
Changing Count, size, usage-mode (metadata/bytebuffer/native-handle) or
allocation-mode (allocateBuffer/UseBuffer) of buffers should only be
allowed when the port hasn't been allocated yet.
Since buffer-modes determine the payload-size in case of meta-buffer-mode,
and also determine the memory-base to derive buffer indices from buffer-
headers, letting the client change count/size/mode on a pre-allocated port
will cause inconsistencies in the size of memory allocated for headers and
lead to index overflows.
Fix the range checks for the derived buffer-indices to avoid out-of-bounds
writes.
Also, ensure buffer-mode settings (metadata-mode, native-handle-mode)
are intended for the right ports.
Bug: 29617572 : Heap Overflow/LPE in MediaServer (libOmxVdec problem #8)
Bug: 29982686 : Memory Write/LPE in MediaServer (libOmxVdec problem #10)
Change-Id: I619636a48779580c247bffb3752c3e4025b46542
-rw-r--r-- | mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp | 68 |
1 files changed, 58 insertions, 10 deletions
diff --git a/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp b/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp index 34402dc2..fb182bf3 100644 --- a/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp +++ b/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp @@ -3175,8 +3175,11 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, eRet = OMX_ErrorBadParameter; } else if (!port_format_changed) { - // Buffer count can change only when port is disabled - if (!release_output_done()) { + // Buffer count can change only when port is unallocated + if (m_out_mem_ptr && + (portDefn->nBufferCountActual != drv_ctx.op_buf.actualcount || + portDefn->nBufferSize != drv_ctx.op_buf.buffer_size)) { + DEBUG_PRINT_ERROR("Cannot change o/p buffer count since all buffers are not freed yet !"); eRet = OMX_ErrorInvalidState; break; @@ -3294,8 +3297,10 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, eRet = OMX_ErrorBadParameter; break; } - // Buffer count can change only when port is disabled - if (!release_input_done()) { + // Buffer count can change only when port is unallocated + if (m_inp_mem_ptr && + (portDefn->nBufferCountActual != drv_ctx.ip_buf.actualcount || + portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size)) { DEBUG_PRINT_ERROR("Cannot change i/p buffer count since all buffers are not freed yet !"); eRet = OMX_ErrorInvalidState; break; @@ -3376,6 +3381,14 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, /* Input port */ if (portFmt->nPortIndex == 0) { + // arbitrary_bytes mode cannot be changed arbitrarily since this controls how: + // - headers are allocated and + // - headers-indices are derived + // Avoid changing arbitrary_bytes when the port is already allocated + if (m_inp_mem_ptr) { + DEBUG_PRINT_ERROR("Cannot change arbitrary-bytes-mode since input port is not free!"); + return OMX_ErrorUnsupportedSetting; + } if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) { if (secure_mode) { arbitrary_bytes = false; @@ -3685,6 +3698,15 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: { VALIDATE_OMX_PARAM_DATA(paramData, EnableAndroidNativeBuffersParams); EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData; + if (enableNativeBuffers->nPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) { + DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers allowed only on output port!"); + eRet = OMX_ErrorUnsupportedSetting; + break; + } else if (m_out_mem_ptr) { + DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers is not allowed since Output port is not free !"); + eRet = OMX_ErrorInvalidState; + break; + } if (enableNativeBuffers) { m_enable_android_native_buffers = enableNativeBuffers->enable; } @@ -3753,6 +3775,12 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, break; } if (metabuffer->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) { + + if (m_out_mem_ptr) { + DEBUG_PRINT_ERROR("Enable/Disable dynamic-buffer-mode is not allowed since Output port is not free !"); + eRet = OMX_ErrorInvalidState; + break; + } //set property dynamic buffer mode to driver. struct v4l2_control control; struct v4l2_format fmt; @@ -4674,9 +4702,16 @@ OMX_ERRORTYPE omx_vdec::use_buffer( DEBUG_PRINT_ERROR("Use Buffer in Invalid State"); return OMX_ErrorInvalidState; } - if (port == OMX_CORE_INPUT_PORT_INDEX) + if (port == OMX_CORE_INPUT_PORT_INDEX) { + // If this is not the first allocation (i.e m_inp_mem_ptr is allocated), + // ensure that use-buffer was called for previous allocation. + // Mix-and-match of useBuffer and allocateBuffer is not allowed + if (m_inp_mem_ptr && !input_use_buffer) { + DEBUG_PRINT_ERROR("'Use' Input buffer called after 'Allocate' Input buffer !"); + return OMX_ErrorUndefined; + } error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer); - else if (port == OMX_CORE_OUTPUT_PORT_INDEX) + } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested else { DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port); @@ -5464,6 +5499,13 @@ OMX_ERRORTYPE omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE hC } if (port == OMX_CORE_INPUT_PORT_INDEX) { + // If this is not the first allocation (i.e m_inp_mem_ptr is allocated), + // ensure that use-buffer was never called. + // Mix-and-match of useBuffer and allocateBuffer is not allowed + if (m_inp_mem_ptr && input_use_buffer) { + DEBUG_PRINT_ERROR("'Allocate' Input buffer called after 'Use' Input buffer !"); + return OMX_ErrorUndefined; + } if (arbitrary_bytes) { eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes); } else { @@ -5712,6 +5754,10 @@ OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, } else { if (input_use_buffer == true) { nBufferIndex = buffer - m_inp_heap_ptr; + if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) { + DEBUG_PRINT_ERROR("ERROR: ETB nBufferIndex is invalid in use-buffer mode"); + return OMX_ErrorBadParameter; + } m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen; m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp; m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags; @@ -5723,7 +5769,7 @@ OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, } } - if (nBufferIndex > drv_ctx.ip_buf.actualcount ) { + if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) { DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid"); return OMX_ErrorBadParameter; } @@ -5779,7 +5825,7 @@ OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE h nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr); - if (nPortIndex > drv_ctx.ip_buf.actualcount) { + if (nPortIndex >= drv_ctx.ip_buf.actualcount) { DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]", nPortIndex); return OMX_ErrorBadParameter; @@ -6097,7 +6143,7 @@ OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy( nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr()); - if (bufferAdd == NULL || nPortIndex > drv_ctx.op_buf.actualcount) { + if (bufferAdd == NULL || nPortIndex >= drv_ctx.op_buf.actualcount) { DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer index, nPortIndex %u bufCount %u", nPortIndex, drv_ctx.op_buf.actualcount); return OMX_ErrorBadParameter; @@ -6961,7 +7007,9 @@ OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE hComp, OMX_BUFFERHEADERTYPE* buffer) { - if (buffer == NULL || ((buffer - m_inp_mem_ptr) > (int)drv_ctx.ip_buf.actualcount)) { + int nBufferIndex = buffer - m_inp_mem_ptr; + + if (buffer == NULL || (nBufferIndex >= (int)drv_ctx.ip_buf.actualcount)) { DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer); return OMX_ErrorBadParameter; } |