diff options
| author | Mahesh Lanka <mlanka@codeaurora.org> | 2016-04-10 19:04:12 +0530 |
|---|---|---|
| committer | Michael Bestas <mikeioannina@cyanogenmod.org> | 2016-06-07 17:14:55 +0300 |
| commit | e36799536e24626c72148457c56a3ca877e5ebd4 (patch) | |
| tree | f3a41eda0f3092f81421b2ebf9fa216ccdf8975d | |
| parent | 6945ec2ffc9808b24ba9b207938af58b61de94a8 (diff) | |
| download | android_hardware_qcom_media-e36799536e24626c72148457c56a3ca877e5ebd4.tar.gz android_hardware_qcom_media-e36799536e24626c72148457c56a3ca877e5ebd4.tar.bz2 android_hardware_qcom_media-e36799536e24626c72148457c56a3ca877e5ebd4.zip | |
DO NOT MERGE mm-video-v4l2: vdec: add safety checks for freeing buffers
Allow only up to 64 buffers on input/output port (since the
allocation bitmap is only 64-wide).
Do not allow changing theactual buffer count while still
holding allocation (Client can technically negotiate
buffer count on a free/disabled port)
Add safety checks to free only as many buffers were allocated.
Fixes: Security Vulnerability - Heap Overflow and Possible Local
Privilege Escalation in MediaServer (libOmxVdec problem #3)
Bug: 27532282 27661749
Change-Id: I06dd680d43feaef3efdc87311e8a6703e234b523
(cherry picked from commit 159739439a7df7da6892d2bdef1943d4b6ff6f65)
| -rw-r--r--[-rwxr-xr-x] | mm-video-v4l2/vidc/vdec/inc/omx_vdec.h | 2 | ||||
| -rw-r--r-- | mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp | 60 |
2 files changed, 48 insertions, 14 deletions
diff --git a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h index 00d5e6e2..194239c1 100755..100644 --- a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h +++ b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h @@ -182,7 +182,7 @@ class VideoHeap : public MemoryHeapBase #define DESC_BUFFER_SIZE (8192 * 16) #ifdef _ANDROID_ -#define MAX_NUM_INPUT_OUTPUT_BUFFERS 32 +#define MAX_NUM_INPUT_OUTPUT_BUFFERS 64 #endif #define OMX_FRAMEINFO_EXTRADATA 0x00010000 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 e8342891..b9aa1bfe 100644 --- a/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp +++ b/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp @@ -2869,8 +2869,12 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port\n"); m_display_id = portDefn->format.video.pNativeWindow; unsigned int buffer_size; - if (!client_buffers.get_buffer_req(buffer_size)) { - DEBUG_PRINT_ERROR("\n Error in getting buffer requirements"); + if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) { + DEBUG_PRINT_ERROR("Requested o/p buf count (%u) exceeds limit (%u)", + portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS); + eRet = OMX_ErrorBadParameter; + } else if (!client_buffers.get_buffer_req(buffer_size)) { + DEBUG_PRINT_ERROR("Error in getting buffer requirements"); eRet = OMX_ErrorBadParameter; } else { if ( portDefn->nBufferCountActual >= drv_ctx.op_buf.mincount && @@ -2946,6 +2950,19 @@ OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, eRet = get_buffer_req(&drv_ctx.op_buf); } } + if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) { + DEBUG_PRINT_ERROR("Requested i/p buf count (%u) exceeds limit (%u)", + portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS); + eRet = OMX_ErrorBadParameter; + break; + } + // Buffer count can change only when port is disabled + if (!release_input_done()) { + DEBUG_PRINT_ERROR("Cannot change i/p buffer count since all buffers are not freed yet !"); + eRet = OMX_ErrorInvalidState; + break; + } + if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount || portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size) { port_format_changed = true; @@ -4972,8 +4989,9 @@ OMX_ERRORTYPE omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE hComp, else nPortIndex = buffer - m_inp_heap_ptr; - DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d \n", nPortIndex); - if (nPortIndex < drv_ctx.ip_buf.actualcount) { + DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex); + if (nPortIndex < drv_ctx.ip_buf.actualcount && + BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) { // Clear the bit associated with it. BITMASK_CLEAR(&m_inp_bm_count,nPortIndex); BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex); @@ -5015,8 +5033,9 @@ OMX_ERRORTYPE omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE hComp, } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) { // check if the buffer is valid nPortIndex = buffer - client_buffers.get_il_buf_hdr(); - if (nPortIndex < drv_ctx.op_buf.actualcount) { - DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d \n", nPortIndex); + if (nPortIndex < drv_ctx.op_buf.actualcount && + BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) { + DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex); // Clear the bit associated with it. BITMASK_CLEAR(&m_out_bm_count,nPortIndex); m_out_bPopulated = OMX_FALSE; @@ -5675,7 +5694,14 @@ OMX_ERRORTYPE omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp) if (m_out_mem_ptr) { DEBUG_PRINT_LOW("Freeing the Output Memory\n"); for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) { - free_output_buffer (&m_out_mem_ptr[i]); + if (BITMASK_PRESENT(&m_out_bm_count, i)) { + BITMASK_CLEAR(&m_out_bm_count, i); + client_buffers.free_output_buffer (&m_out_mem_ptr[i]); + } + + if (release_output_done()) { + break; + } } #ifdef _ANDROID_ICS_ memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS)); @@ -5686,11 +5712,19 @@ OMX_ERRORTYPE omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp) if (m_inp_mem_ptr || m_inp_heap_ptr) { DEBUG_PRINT_LOW("Freeing the Input Memory\n"); for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) { - if (m_inp_mem_ptr) - free_input_buffer (i,&m_inp_mem_ptr[i]); - else - free_input_buffer (i,NULL); - } + + if (BITMASK_PRESENT(&m_inp_bm_count, i)) { + BITMASK_CLEAR(&m_inp_bm_count, i); + if (m_inp_mem_ptr) + free_input_buffer (i,&m_inp_mem_ptr[i]); + else + free_input_buffer (i,NULL); + } + + if (release_input_done()) { + break; + } + } } free_input_buffer_header(); free_output_buffer_header(); @@ -6077,7 +6111,7 @@ bool omx_vdec::release_output_done(void) bool bRet = false; unsigned i=0,j=0; - DEBUG_PRINT_LOW("\n Value of m_out_mem_ptr %p",m_inp_mem_ptr); + DEBUG_PRINT_LOW("Value of m_out_mem_ptr %p",m_out_mem_ptr); if (m_out_mem_ptr) { for (; j < drv_ctx.op_buf.actualcount ; j++) { if (BITMASK_PRESENT(&m_out_bm_count,j)) { |
