summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMahesh Lanka <mlanka@codeaurora.org>2016-04-10 19:04:12 +0530
committerMichael Bestas <mikeioannina@cyanogenmod.org>2016-06-07 17:14:55 +0300
commite36799536e24626c72148457c56a3ca877e5ebd4 (patch)
treef3a41eda0f3092f81421b2ebf9fa216ccdf8975d
parent6945ec2ffc9808b24ba9b207938af58b61de94a8 (diff)
downloadandroid_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.h2
-rw-r--r--mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp60
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)) {