summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRajeev Kumar <rajekuma@qca.qualcomm.com>2014-02-10 20:51:29 -0800
committerAkash Patel <c_akashp@qca.qualcomm.com>2014-02-11 19:54:41 -0800
commit6ebee0b05e275644201a4aef46c7fb9fc808fa21 (patch)
tree51fb9b6b5368ba1ea20007215a82a5f40fd209a2
parentea42719efacbbc595c8f8fa6761ae7c800b346cc (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.h2
-rw-r--r--CORE/SERVICES/WMA/wma.c47
-rw-r--r--CORE/VOSS/src/vos_api.c9
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 );