mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-13 00:00:00 -04:00
qcacld-3.0: Fix mem leak in wma_roam_synch_frame_event_handler
The function wma_roam_synch_frame_event_handler, memory is allocated for iface->roam_synch_frame_ind.bcn_probe_rsp, iface->roam_synch_frame_ind.bcn_reassoc_req, iface->roam_synch_frame_ind.bcn_reassoc_rsp when the wmi event WMI_ROAM_SYNCH_FRAME_EVENT is received. This event is followed by a WMI_ROAM_SYNCH_EVENT from the firmware where the host copies the bcn_probe_rsp, bcn_reassoc_req, bcn_reassoc_rsp to the structure roam_synch_ind_ptr and frees the allocated memory. In this flow memory leak can happen in following cases: 1. Firmware sends multiple cascade of WMI_ROAM_SYNCH_FRAME_EVENT the host allocates bcn_reassoc_req, bcn_reassoc_rsp and bcn_probe_rsp with out freeing the previous instance. 2. Firmware sends WMI_ROAM_SYNCH_FRAME_EVENT with either bcn_reassoc_req or bcn_reassoc_req or bcn_probe_rsp NULL or all the three are NULL. 3. Firmware sends WMI_ROAM_SYNCH_FRAME_EVENT having bcn_reassoc_req bcn_reassoc_req and bcn_probe_rsp. Then it sends the WMI_ROAM_SYNCH_EVENT with non zero bcn_reassoc_req_len or bcn_reassoc_rsp_len or bcn_probe_rsp length. 4. Host doesn't free the allocated memory in wma_roam_synch_frame_event_handler during failure cases. Check if received iface->roam_synch_frame_ind has non NULL bcn_probe_rsp, bcn_reassoc_req, bcn_reassoc_rsp and free the same before allocating new memory. Also free the allocated bcn_probe_rsp, bcn_reassoc_req, bcn_reassoc_rsp in failure return cases. Change-Id: I2b76769d09fd61929f7837cb8661d778cd2f881a CRs-Fixed: 2282413
This commit is contained in:
parent
cf33f9653b
commit
ea97fe9ff1
1 changed files with 68 additions and 31 deletions
|
|
@ -1894,6 +1894,35 @@ void wma_process_roam_synch_fail(WMA_HANDLE handle,
|
|||
false;
|
||||
}
|
||||
|
||||
/**
|
||||
* wma_free_roam_synch_frame_ind() - Free the bcn_probe_rsp, reassoc_req,
|
||||
* reassoc_rsp received as part of the ROAM_SYNC_FRAME event
|
||||
*
|
||||
* @iface - interaface corresponding to a vdev
|
||||
*
|
||||
* This API is used to free the buffer allocated during the ROAM_SYNC_FRAME
|
||||
* event
|
||||
*
|
||||
*/
|
||||
static void wma_free_roam_synch_frame_ind(struct wma_txrx_node *iface)
|
||||
{
|
||||
if (iface->roam_synch_frame_ind.bcn_probe_rsp) {
|
||||
qdf_mem_free(iface->roam_synch_frame_ind.bcn_probe_rsp);
|
||||
iface->roam_synch_frame_ind.bcn_probe_rsp_len = 0;
|
||||
iface->roam_synch_frame_ind.bcn_probe_rsp = NULL;
|
||||
}
|
||||
if (iface->roam_synch_frame_ind.reassoc_req) {
|
||||
qdf_mem_free(iface->roam_synch_frame_ind.reassoc_req);
|
||||
iface->roam_synch_frame_ind.reassoc_req_len = 0;
|
||||
iface->roam_synch_frame_ind.reassoc_req = NULL;
|
||||
}
|
||||
if (iface->roam_synch_frame_ind.reassoc_rsp) {
|
||||
qdf_mem_free(iface->roam_synch_frame_ind.reassoc_rsp);
|
||||
iface->roam_synch_frame_ind.reassoc_rsp_len = 0;
|
||||
iface->roam_synch_frame_ind.reassoc_rsp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* wma_fill_data_synch_frame_event() - Fill the the roam sync data buffer using
|
||||
* synch frame event data
|
||||
|
|
@ -2038,12 +2067,14 @@ static int wma_fill_roam_synch_buffer(tp_wma_handle wma,
|
|||
wmi_key_material *key;
|
||||
struct wma_txrx_node *iface = NULL;
|
||||
wmi_roam_fils_synch_tlv_param *fils_info;
|
||||
int status = -EINVAL;
|
||||
|
||||
synch_event = param_buf->fixed_param;
|
||||
roam_synch_ind_ptr->roamedVdevId = synch_event->vdev_id;
|
||||
roam_synch_ind_ptr->authStatus = synch_event->auth_status;
|
||||
roam_synch_ind_ptr->roamReason = synch_event->roam_reason;
|
||||
roam_synch_ind_ptr->rssi = synch_event->rssi;
|
||||
iface = &wma->interfaces[synch_event->vdev_id];
|
||||
WMI_MAC_ADDR_TO_CHAR_ARRAY(&synch_event->bssid,
|
||||
roam_synch_ind_ptr->bssid.bytes);
|
||||
WMA_LOGD("%s: roamedVdevId %d authStatus %d roamReason %d rssi %d isBeacon %d",
|
||||
|
|
@ -2055,11 +2086,10 @@ static int wma_fill_roam_synch_buffer(tp_wma_handle wma,
|
|||
wma->csr_roam_synch_cb((tpAniSirGlobal)wma->mac_context,
|
||||
roam_synch_ind_ptr, NULL, SIR_ROAMING_DEREGISTER_STA))) {
|
||||
WMA_LOGE("LFR3: CSR Roam synch cb failed");
|
||||
return -EINVAL;
|
||||
wma_free_roam_synch_frame_ind(iface);
|
||||
return status;
|
||||
}
|
||||
|
||||
iface = &wma->interfaces[synch_event->vdev_id];
|
||||
|
||||
/*
|
||||
* If lengths of bcn_probe_rsp, reassoc_req and reassoc_rsp are zero in
|
||||
* synch_event driver would have received bcn_probe_rsp, reassoc_req
|
||||
|
|
@ -2072,19 +2102,22 @@ static int wma_fill_roam_synch_buffer(tp_wma_handle wma,
|
|||
WMA_LOGE("LFR3: bcn_probe_rsp is NULL");
|
||||
QDF_ASSERT(iface->roam_synch_frame_ind.
|
||||
bcn_probe_rsp != NULL);
|
||||
return -EINVAL;
|
||||
wma_free_roam_synch_frame_ind(iface);
|
||||
return status;
|
||||
}
|
||||
if (!iface->roam_synch_frame_ind.reassoc_rsp) {
|
||||
WMA_LOGE("LFR3: reassoc_rsp is NULL");
|
||||
QDF_ASSERT(iface->roam_synch_frame_ind.
|
||||
reassoc_rsp != NULL);
|
||||
return -EINVAL;
|
||||
wma_free_roam_synch_frame_ind(iface);
|
||||
return status;
|
||||
}
|
||||
if (!iface->roam_synch_frame_ind.reassoc_req) {
|
||||
WMA_LOGE("LFR3: reassoc_req is NULL");
|
||||
QDF_ASSERT(iface->roam_synch_frame_ind.
|
||||
reassoc_req != NULL);
|
||||
return -EINVAL;
|
||||
wma_free_roam_synch_frame_ind(iface);
|
||||
return status;
|
||||
}
|
||||
wma_fill_data_synch_frame_event(wma, roam_synch_ind_ptr, iface);
|
||||
} else {
|
||||
|
|
@ -2120,7 +2153,8 @@ static int wma_fill_roam_synch_buffer(tp_wma_handle wma,
|
|||
__func__,
|
||||
fils_info->kek_len,
|
||||
fils_info->pmk_len);
|
||||
return -EINVAL;
|
||||
wma_free_roam_synch_frame_ind(iface);
|
||||
return status;
|
||||
}
|
||||
|
||||
roam_synch_ind_ptr->kek_len = fils_info->kek_len;
|
||||
|
|
@ -2143,6 +2177,7 @@ static int wma_fill_roam_synch_buffer(tp_wma_handle wma,
|
|||
roam_synch_ind_ptr->update_erp_next_seq_num,
|
||||
roam_synch_ind_ptr->next_erp_seq_num);
|
||||
}
|
||||
wma_free_roam_synch_frame_ind(iface);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2477,25 +2512,25 @@ int wma_roam_synch_frame_event_handler(void *handle, uint8_t *event,
|
|||
WMA_LOGD("LFR3:Synch Frame event");
|
||||
if (!event) {
|
||||
WMA_LOGE("event param null");
|
||||
goto cleanup_label;
|
||||
return status;
|
||||
}
|
||||
|
||||
param_buf = (WMI_ROAM_SYNCH_FRAME_EVENTID_param_tlvs *) event;
|
||||
if (!param_buf) {
|
||||
WMA_LOGE("received null buf from target");
|
||||
goto cleanup_label;
|
||||
return status;
|
||||
}
|
||||
|
||||
synch_frame_event = param_buf->fixed_param;
|
||||
if (!synch_frame_event) {
|
||||
WMA_LOGE("received null event data from target");
|
||||
goto cleanup_label;
|
||||
return status;
|
||||
}
|
||||
|
||||
if (synch_frame_event->vdev_id >= wma->max_bssid) {
|
||||
WMA_LOGE("received invalid vdev_id %d",
|
||||
synch_frame_event->vdev_id);
|
||||
goto cleanup_label;
|
||||
return status;
|
||||
}
|
||||
|
||||
vdev_id = synch_frame_event->vdev_id;
|
||||
|
|
@ -2503,7 +2538,8 @@ int wma_roam_synch_frame_event_handler(void *handle, uint8_t *event,
|
|||
|
||||
if (wma_is_roam_synch_in_progress(wma, vdev_id)) {
|
||||
WMA_LOGE("Ignoring this event as it is unexpected");
|
||||
goto cleanup_label;
|
||||
wma_free_roam_synch_frame_ind(iface);
|
||||
return status;
|
||||
}
|
||||
WMA_LOGD("LFR3: Received ROAM_SYNCH_FRAME_EVENT");
|
||||
|
||||
|
|
@ -2519,6 +2555,9 @@ int wma_roam_synch_frame_event_handler(void *handle, uint8_t *event,
|
|||
iface->roam_synch_frame_ind.is_beacon =
|
||||
synch_frame_event->is_beacon;
|
||||
|
||||
if (iface->roam_synch_frame_ind.bcn_probe_rsp)
|
||||
qdf_mem_free(iface->roam_synch_frame_ind.
|
||||
bcn_probe_rsp);
|
||||
iface->roam_synch_frame_ind.bcn_probe_rsp =
|
||||
qdf_mem_malloc(iface->roam_synch_frame_ind.
|
||||
bcn_probe_rsp_len);
|
||||
|
|
@ -2527,7 +2566,8 @@ int wma_roam_synch_frame_event_handler(void *handle, uint8_t *event,
|
|||
QDF_ASSERT(iface->roam_synch_frame_ind.
|
||||
bcn_probe_rsp != NULL);
|
||||
status = -ENOMEM;
|
||||
goto cleanup_label;
|
||||
wma_free_roam_synch_frame_ind(iface);
|
||||
return status;
|
||||
}
|
||||
qdf_mem_copy(iface->roam_synch_frame_ind.
|
||||
bcn_probe_rsp,
|
||||
|
|
@ -2539,6 +2579,8 @@ int wma_roam_synch_frame_event_handler(void *handle, uint8_t *event,
|
|||
iface->roam_synch_frame_ind.reassoc_req_len =
|
||||
synch_frame_event->reassoc_req_len;
|
||||
|
||||
if (iface->roam_synch_frame_ind.reassoc_req)
|
||||
qdf_mem_free(iface->roam_synch_frame_ind.reassoc_req);
|
||||
iface->roam_synch_frame_ind.reassoc_req =
|
||||
qdf_mem_malloc(iface->roam_synch_frame_ind.
|
||||
reassoc_req_len);
|
||||
|
|
@ -2547,7 +2589,8 @@ int wma_roam_synch_frame_event_handler(void *handle, uint8_t *event,
|
|||
QDF_ASSERT(iface->roam_synch_frame_ind.
|
||||
reassoc_req != NULL);
|
||||
status = -ENOMEM;
|
||||
goto cleanup_label;
|
||||
wma_free_roam_synch_frame_ind(iface);
|
||||
return status;
|
||||
}
|
||||
qdf_mem_copy(iface->roam_synch_frame_ind.reassoc_req,
|
||||
param_buf->reassoc_req_frame,
|
||||
|
|
@ -2555,9 +2598,18 @@ int wma_roam_synch_frame_event_handler(void *handle, uint8_t *event,
|
|||
}
|
||||
|
||||
if (synch_frame_event->reassoc_rsp_len) {
|
||||
if (!iface->roam_synch_frame_ind.bcn_probe_rsp ||
|
||||
!iface->roam_synch_frame_ind.reassoc_req) {
|
||||
WMA_LOGE("failed: No probe or reassoc rsp");
|
||||
wma_free_roam_synch_frame_ind(iface);
|
||||
return status;
|
||||
}
|
||||
iface->roam_synch_frame_ind.reassoc_rsp_len =
|
||||
synch_frame_event->reassoc_rsp_len;
|
||||
|
||||
if (iface->roam_synch_frame_ind.reassoc_rsp)
|
||||
qdf_mem_free(iface->roam_synch_frame_ind.reassoc_rsp);
|
||||
|
||||
iface->roam_synch_frame_ind.reassoc_rsp =
|
||||
qdf_mem_malloc(iface->roam_synch_frame_ind.
|
||||
reassoc_rsp_len);
|
||||
|
|
@ -2566,29 +2618,14 @@ int wma_roam_synch_frame_event_handler(void *handle, uint8_t *event,
|
|||
QDF_ASSERT(iface->roam_synch_frame_ind.
|
||||
reassoc_rsp != NULL);
|
||||
status = -ENOMEM;
|
||||
goto cleanup_label;
|
||||
wma_free_roam_synch_frame_ind(iface);
|
||||
return status;
|
||||
}
|
||||
qdf_mem_copy(iface->roam_synch_frame_ind.reassoc_rsp,
|
||||
param_buf->reassoc_rsp_frame,
|
||||
iface->roam_synch_frame_ind.reassoc_rsp_len);
|
||||
}
|
||||
return 0;
|
||||
|
||||
cleanup_label:
|
||||
if (iface && (iface->roam_synch_frame_ind.bcn_probe_rsp)) {
|
||||
qdf_mem_free(iface->roam_synch_frame_ind.
|
||||
bcn_probe_rsp);
|
||||
iface->roam_synch_frame_ind.bcn_probe_rsp = NULL;
|
||||
}
|
||||
if (iface && (iface->roam_synch_frame_ind.reassoc_req)) {
|
||||
qdf_mem_free(iface->roam_synch_frame_ind.reassoc_req);
|
||||
iface->roam_synch_frame_ind.reassoc_req = NULL;
|
||||
}
|
||||
if (iface && (iface->roam_synch_frame_ind.reassoc_rsp)) {
|
||||
qdf_mem_free(iface->roam_synch_frame_ind.reassoc_rsp);
|
||||
iface->roam_synch_frame_ind.reassoc_rsp = NULL;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
#define RSN_CAPS_SHIFT 16
|
||||
|
|
|
|||
Loading…
Reference in a new issue