diff options
| author | Rajeev Kumar <rajekuma@qca.qualcomm.com> | 2014-02-10 20:51:29 -0800 |
|---|---|---|
| committer | Akash Patel <c_akashp@qca.qualcomm.com> | 2014-02-11 19:54:41 -0800 |
| commit | 6ebee0b05e275644201a4aef46c7fb9fc808fa21 (patch) | |
| tree | 51fb9b6b5368ba1ea20007215a82a5f40fd209a2 | |
| parent | ea42719efacbbc595c8f8fa6761ae7c800b346cc (diff) | |
qcacld: Fix of 1 byte memory corruption during driver unload
Following is the crash scenario:
1) vos_close() is calling wma_close() which is freeing wmi_handle
2) After freeing wmi_handle vos_close() is calling HTCStop()
3) HTCStop() which is calling HIFStop and HIStop() is calling
hif_buffer_cleanup() to flush send buffer commands using
hif_send_buffer_cleanup_on_pipe()
4) And now while flushing HIF buffer commands it calls
wmi_htc_tx_complete() which de-references already freed
wmi_handle pointer and decrements it casuing a single byte of
memory corruption.
5) Fixing this issue by moving down wmi_handle free after HTCStop()
during driver unload such that when wmi_htc_tx_complete()
accesses wmi_handle while flushing HIF send buffer it gets
valid wmi_handle.
CRs-Fixed: 613863
Change-Id: I4f053d930f797b7142479897a2238fcad438e023
| -rw-r--r-- | CORE/SERVICES/COMMON/wma_api.h | 2 | ||||
| -rw-r--r-- | CORE/SERVICES/WMA/wma.c | 47 | ||||
| -rw-r--r-- | CORE/VOSS/src/vos_api.c | 9 |
3 files changed, 46 insertions, 12 deletions
diff --git a/CORE/SERVICES/COMMON/wma_api.h b/CORE/SERVICES/COMMON/wma_api.h index 4ded593e5cc8..0055a219dd42 100644 --- a/CORE/SERVICES/COMMON/wma_api.h +++ b/CORE/SERVICES/COMMON/wma_api.h @@ -99,6 +99,8 @@ VOS_STATUS wma_stop(v_VOID_t *vos_context, tANI_U8 reason); VOS_STATUS wma_close(v_VOID_t *vos_context); +VOS_STATUS wma_wmi_service_close(v_VOID_t *vos_context); + v_VOID_t wma_rx_ready_event(WMA_HANDLE handle, v_VOID_t *ev); v_VOID_t wma_rx_service_ready_event(WMA_HANDLE handle, diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c index 8ab7df67acb0..e1a0ad84b875 100644 --- a/CORE/SERVICES/WMA/wma.c +++ b/CORE/SERVICES/WMA/wma.c @@ -15736,6 +15736,41 @@ static void wma_cleanup_vdev_resp(tp_wma_handle wma) adf_os_spin_unlock_bh(&wma->vdev_respq_lock); } +VOS_STATUS wma_wmi_service_close(v_VOID_t *vos_ctx) +{ + tp_wma_handle wma_handle; + + WMA_LOGD("%s: Enter", __func__); + + wma_handle = vos_get_context(VOS_MODULE_ID_WDA, vos_ctx); + + /* validate the wma_handle */ + if (NULL == wma_handle) { + WMA_LOGE("%s: Invalid wma handle", __func__); + return VOS_STATUS_E_INVAL; + } + + /* validate the wmi handle */ + if (NULL == wma_handle->wmi_handle) { + WMA_LOGE("%s: Invalid wmi handle", __func__); + return VOS_STATUS_E_INVAL; + } + + /* dettach the wmi serice */ + WMA_LOGD("calling wmi_unified_detach"); + wmi_unified_detach(wma_handle->wmi_handle); + wma_handle->wmi_handle = NULL; + + vos_mem_free(wma_handle->interfaces); + /* free the wma_handle */ + vos_free_context(wma_handle->vos_context, VOS_MODULE_ID_WDA, wma_handle); + + adf_os_mem_free(((pVosContextType) vos_ctx)->cfg_ctx); + WMA_LOGD("%s: Exit", __func__); + return VOS_STATUS_SUCCESS; +} + + /* function : wma_close * Descriptin : * Args : @@ -15811,18 +15846,6 @@ VOS_STATUS wma_close(v_VOID_t *vos_ctx) wma_utf_detach(wma_handle); #endif - /* dettach the wmi serice */ - if (wma_handle->wmi_handle) { - WMA_LOGD("calling wmi_unified_detach"); - wmi_unified_detach(wma_handle->wmi_handle); - wma_handle->wmi_handle = NULL; - } - vos_mem_free(wma_handle->interfaces); - /* free the wma_handle */ - vos_free_context(wma_handle->vos_context, VOS_MODULE_ID_WDA, wma_handle); - - adf_os_mem_free(((pVosContextType) vos_ctx)->cfg_ctx); - WMA_LOGD("%s: Exit", __func__); return VOS_STATUS_SUCCESS; } diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c index 99173e7ae503..041a9e918a75 100644 --- a/CORE/VOSS/src/vos_api.c +++ b/CORE/VOSS/src/vos_api.c @@ -1116,6 +1116,15 @@ VOS_STATUS vos_close( v_CONTEXT_t vosContext ) } #endif + vosStatus = wma_wmi_service_close( vosContext ); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to close wma_wmi_service", __func__); + VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); + } + + #ifndef QCA_WIFI_2_0 /* Let DXE return packets in WDA_close and then free them here */ vosStatus = vos_packet_close( vosContext ); |
