mirror of
https://github.com/followmsi/android_hardware_qcom_media.git
synced 2024-10-31 22:47:35 +00:00
mm-video-v4l2: venc: Avoid buffer access after free
client expects buffer to be free if free_buffer is called, but if omx is in executing state free buffer call will error out. When async thread tries to copy data to client buffer which is already freed,it leads to crash. Added a bitmask to avoid copy to buffer after free. Bug: 36130225 CRs-Fixed: 2106434 Author: Uma Mehta <umamehta@codeaurora.org> Change-Id: Id439aac54ee64a65ea68b6431a9f5150255a6980
This commit is contained in:
parent
6ec830ac0c
commit
2cd0260b52
3 changed files with 19 additions and 7 deletions
|
@ -665,6 +665,7 @@ class omx_video: public qc_omx_component
|
|||
int pending_output_buffers;
|
||||
|
||||
uint64_t m_out_bm_count;
|
||||
uint64_t m_client_out_bm_count;
|
||||
uint64_t m_inp_bm_count;
|
||||
uint64_t m_flags;
|
||||
uint64_t m_etb_count;
|
||||
|
|
|
@ -295,6 +295,7 @@ omx_video::omx_video():
|
|||
pending_input_buffers(0),
|
||||
pending_output_buffers(0),
|
||||
m_out_bm_count(0),
|
||||
m_client_out_bm_count(0),
|
||||
m_inp_bm_count(0),
|
||||
m_flags(0),
|
||||
m_etb_count(0),
|
||||
|
@ -2658,7 +2659,6 @@ OMX_ERRORTYPE omx_video::use_output_buffer(
|
|||
return OMX_ErrorBadParameter;
|
||||
}
|
||||
|
||||
auto_lock l(m_buf_lock);
|
||||
if (!m_out_mem_ptr) {
|
||||
output_use_buffer = true;
|
||||
int nBufHdrSize = 0;
|
||||
|
@ -2809,6 +2809,7 @@ OMX_ERRORTYPE omx_video::use_output_buffer(
|
|||
}
|
||||
|
||||
BITMASK_SET(&m_out_bm_count,i);
|
||||
BITMASK_SET(&m_client_out_bm_count,i);
|
||||
} else {
|
||||
DEBUG_PRINT_ERROR("ERROR: All o/p Buffers have been Used, invalid use_buf call for "
|
||||
"index = %u", i);
|
||||
|
@ -2846,6 +2847,8 @@ OMX_ERRORTYPE omx_video::use_buffer(
|
|||
DEBUG_PRINT_ERROR("ERROR: Use Buffer in Invalid State");
|
||||
return OMX_ErrorInvalidState;
|
||||
}
|
||||
|
||||
auto_lock l(m_buf_lock);
|
||||
if (port == PORT_INDEX_IN) {
|
||||
eRet = use_input_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
|
||||
} else if (port == PORT_INDEX_OUT) {
|
||||
|
@ -2917,7 +2920,6 @@ OMX_ERRORTYPE omx_video::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
|
|||
}
|
||||
|
||||
if (index < m_sInPortDef.nBufferCountActual && m_pInput_pmem) {
|
||||
auto_lock l(m_lock);
|
||||
|
||||
if (m_pInput_pmem[index].fd > 0 && input_use_buffer == false) {
|
||||
DEBUG_PRINT_LOW("FreeBuffer:: i/p AllocateBuffer case");
|
||||
|
@ -3429,7 +3431,7 @@ OMX_ERRORTYPE omx_video::allocate_buffer(OMX_IN OMX_HANDLETYPE h
|
|||
DEBUG_PRINT_ERROR("ERROR: Allocate Buf in Invalid State");
|
||||
return OMX_ErrorInvalidState;
|
||||
}
|
||||
|
||||
auto_lock l(m_buf_lock);
|
||||
// What if the client calls again.
|
||||
if (port == PORT_INDEX_IN) {
|
||||
#ifdef _ANDROID_ICS_
|
||||
|
@ -3500,7 +3502,12 @@ OMX_ERRORTYPE omx_video::free_buffer(OMX_IN OMX_HANDLETYPE hComp,
|
|||
unsigned int nPortIndex;
|
||||
|
||||
DEBUG_PRINT_LOW("In for encoder free_buffer");
|
||||
|
||||
auto_lock l(m_buf_lock);
|
||||
if (port == PORT_INDEX_OUT) { //client called freebuffer, clearing client buffer bitmask right away to avoid use after free
|
||||
nPortIndex = buffer - (OMX_BUFFERHEADERTYPE*)m_out_mem_ptr;
|
||||
if(BITMASK_PRESENT(&m_client_out_bm_count, nPortIndex))
|
||||
BITMASK_CLEAR(&m_client_out_bm_count,nPortIndex);
|
||||
}
|
||||
if (m_state == OMX_StateIdle &&
|
||||
(BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
|
||||
DEBUG_PRINT_LOW(" free buffer while Component in Loading pending");
|
||||
|
@ -3577,7 +3584,6 @@ OMX_ERRORTYPE omx_video::free_buffer(OMX_IN OMX_HANDLETYPE hComp,
|
|||
nPortIndex, (unsigned int)m_sOutPortDef.nBufferCountActual);
|
||||
if (nPortIndex < m_sOutPortDef.nBufferCountActual &&
|
||||
BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) {
|
||||
auto_lock l(m_buf_lock);
|
||||
// Clear the bit associated with it.
|
||||
BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
|
||||
m_sOutPortDef.bPopulated = OMX_FALSE;
|
||||
|
@ -3838,7 +3844,7 @@ OMX_ERRORTYPE omx_video::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,
|
|||
{
|
||||
DEBUG_PRINT_LOW("Heap UseBuffer case, so memcpy the data");
|
||||
|
||||
auto_lock l(m_lock);
|
||||
auto_lock l(m_buf_lock);
|
||||
pmem_data_buf = (OMX_U8 *)m_pInput_pmem[nBufIndex].buffer;
|
||||
if (pmem_data_buf) {
|
||||
memcpy (pmem_data_buf, (buffer->pBuffer + buffer->nOffset),
|
||||
|
|
|
@ -2148,11 +2148,15 @@ OMX_ERRORTYPE omx_venc::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
|
|||
DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d",\
|
||||
m_state);
|
||||
}
|
||||
|
||||
auto_lock l(m_buf_lock);
|
||||
if (m_out_mem_ptr) {
|
||||
DEBUG_PRINT_LOW("Freeing the Output Memory");
|
||||
for (i=0; i< m_sOutPortDef.nBufferCountActual; i++ ) {
|
||||
if (BITMASK_PRESENT(&m_out_bm_count, i)) {
|
||||
BITMASK_CLEAR(&m_out_bm_count, i);
|
||||
if (BITMASK_PRESENT(&m_client_out_bm_count, i))
|
||||
BITMASK_CLEAR(&m_client_out_bm_count, i);
|
||||
free_output_buffer (&m_out_mem_ptr[i]);
|
||||
}
|
||||
|
||||
|
@ -2504,7 +2508,8 @@ int omx_venc::async_message_process (void *context, void* message)
|
|||
omxhdr->nFlags = m_sVenc_msg->buf.flags;
|
||||
|
||||
/*Use buffer case*/
|
||||
if (omx->output_use_buffer && !omx->m_use_output_pmem && !omx->is_secure_session()) {
|
||||
if (BITMASK_PRESENT(&(omx->m_client_out_bm_count), bufIndex) &&
|
||||
omx->output_use_buffer && !omx->m_use_output_pmem && !omx->is_secure_session()) {
|
||||
DEBUG_PRINT_LOW("memcpy() for o/p Heap UseBuffer");
|
||||
memcpy(omxhdr->pBuffer,
|
||||
(m_sVenc_msg->buf.ptrbuffer),
|
||||
|
|
Loading…
Reference in a new issue