qcacmn: Fix use-after-freed when sending WMI command to FW

Using a buffer after passing it to wmi_unified_cmd_send() induces a
race condition that may result in a use-after-freed situation. Fix
several potential use-after-freed situations when calling
wmi_unified_cmd_send() by ensuring all access to a buffer is done
before the call to wmi_unified_cmd_send().

Change-Id: I985aad6e49daf1d823e3751a9cb0a293a298323c
CRs-Fixed: 1089713
This commit is contained in:
Dustin Brown
2016-11-14 16:11:26 -08:00
committed by qcabuildsw
parent 06520827d4
commit 4103e4a36e
3 changed files with 60 additions and 48 deletions

View File

@@ -1738,6 +1738,8 @@ static bool wmi_is_pm_resume_cmd(uint32_t cmd_id)
* @len: wmi buffer length * @len: wmi buffer length
* @cmd_id: wmi command id * @cmd_id: wmi command id
* *
* Note, it is NOT safe to access buf after calling this function!
*
* Return: 0 on success * Return: 0 on success
*/ */
QDF_STATUS wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf, QDF_STATUS wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf,

View File

@@ -777,7 +777,7 @@ QDF_STATUS send_green_ap_ps_cmd_non_tlv(wmi_unified_t wmi_handle,
qdf_print("%s: Sent WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID.\n" qdf_print("%s: Sent WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID.\n"
"enable=%u status=%d\n", "enable=%u status=%d\n",
__func__, __func__,
cmd->enable, value,
ret); ret);
#endif /* OL_GREEN_AP_DEBUG_CONFIG_INTERACTIONS */ #endif /* OL_GREEN_AP_DEBUG_CONFIG_INTERACTIONS */
return ret; return ret;
@@ -2324,19 +2324,23 @@ QDF_STATUS send_smart_ant_enable_cmd_non_tlv(wmi_unified_t wmi_handle,
if (ret != 0) { if (ret != 0) {
qdf_print(" %s :WMI Failed\n", __func__); qdf_print(" %s :WMI Failed\n", __func__);
qdf_print("%s: Sent WMI_PDEV_SMART_ANT_ENABLE_CMDID.\n" qdf_print("%s: Failed to send WMI_PDEV_SMART_ANT_ENABLE_CMDID.\n"
"enable:%d mode:%d rx_antenna: 0x%08x PINS: " "enable:%d mode:%d rx_antenna: 0x%08x PINS: "
"[%d %d %d %d] Func[%d %d %d %d] cmdstatus=%d\n", "[%d %d %d %d] Func[%d %d %d %d] cmdstatus=%d\n",
__func__, __func__,
cmd->enable, cmd->enable,
cmd->mode, cmd->mode,
cmd->rx_antenna, cmd->rx_antenna,
cmd->gpio_pin[0], cmd->gpio_pin[1], cmd->gpio_pin[0],
cmd->gpio_pin[2], cmd->gpio_pin[3], cmd->gpio_pin[1],
cmd->gpio_func[0], cmd->gpio_func[1], cmd->gpio_pin[2],
cmd->gpio_func[2], cmd->gpio_func[3], cmd->gpio_pin[3],
ret); cmd->gpio_func[0],
cmd->gpio_func[1],
cmd->gpio_func[2],
cmd->gpio_func[3],
ret);
wmi_buf_free(buf);
} }
return ret; return ret;
} }
@@ -2371,11 +2375,12 @@ QDF_STATUS send_smart_ant_set_rx_ant_cmd_non_tlv(wmi_unified_t wmi_handle,
if (ret != 0) { if (ret != 0) {
qdf_print(" %s :WMI Failed\n", __func__); qdf_print(" %s :WMI Failed\n", __func__);
qdf_print("%s: Sent WMI_PDEV_SMART_ANT_SET_RX_ANTENNA_CMDID.\n" qdf_print("%s: Failed to send WMI_PDEV_SMART_ANT_SET_RX_ANTENNA_CMDID.\n"
" rx_antenna: 0x%08x cmdstatus=%d\n", " rx_antenna: 0x%08x cmdstatus=%d\n",
__func__, __func__,
cmd->rx_antenna, cmd->rx_antenna,
ret); ret);
wmi_buf_free(buf);
} }
return ret; return ret;
} }
@@ -2416,13 +2421,14 @@ QDF_STATUS send_smart_ant_set_tx_ant_cmd_non_tlv(wmi_unified_t wmi_handle,
if (ret != 0) { if (ret != 0) {
qdf_print(" %s :WMI Failed\n", __func__); qdf_print(" %s :WMI Failed\n", __func__);
qdf_print("%s: Sent WMI_PEER_SMART_ANT_SET_TX_ANTENNA_CMDID.\n" qdf_print("%s: Failed to send WMI_PEER_SMART_ANT_SET_TX_ANTENNA_CMDID.\n"
" Node: %s tx_antennas: [0x%08x 0x%08x] cmdstatus=%d\n", " Node: %s tx_antennas: [0x%08x 0x%08x] cmdstatus=%d\n",
__func__, __func__,
ether_sprintf(macaddr), ether_sprintf(macaddr),
cmd->antenna_series[0], cmd->antenna_series[0],
cmd->antenna_series[1], cmd->antenna_series[1],
ret); ret);
wmi_buf_free(buf);
} }
return ret; return ret;
} }
@@ -2467,15 +2473,17 @@ QDF_STATUS send_smart_ant_set_training_info_cmd_non_tlv(
if (ret != 0) { if (ret != 0) {
qdf_print(" %s :WMI Failed\n", __func__); qdf_print(" %s :WMI Failed\n", __func__);
qdf_print("%s: Sent WMI_PEER_SMART_ANT_SET_TRAIN_INFO_CMDID.\n" qdf_print("%s: Failed to Send WMI_PEER_SMART_ANT_SET_TRAIN_INFO_CMDID.\n"
" Train Node: %s rate_array[0x%02x 0x%02x] " " Train Node: %s rate_array[0x%02x 0x%02x] "
"tx_antennas: [0x%08x 0x%08x] cmdstatus=%d\n", "tx_antennas: [0x%08x 0x%08x] cmdstatus=%d\n",
__func__, __func__,
ether_sprintf(macaddr), ether_sprintf(macaddr),
cmd->train_rate_series[0], cmd->train_rate_series[1], cmd->train_rate_series[0],
cmd->train_rate_series[1],
cmd->train_antenna_series[0], cmd->train_antenna_series[0],
cmd->train_antenna_series[1], cmd->train_antenna_series[1],
ret); ret);
wmi_buf_free(buf);
} }
return ret; return ret;
} }
@@ -2656,25 +2664,25 @@ QDF_STATUS send_vdev_spectral_configure_cmd_non_tlv(wmi_unified_t wmi_handle,
"spectral_scan_bin_scale = %u\n" "spectral_scan_bin_scale = %u\n"
"spectral_scan_dBm_adj = %u\n" "spectral_scan_dBm_adj = %u\n"
"spectral_scan_chn_mask = %u\n", "spectral_scan_chn_mask = %u\n",
cmd->vdev_id, param->vdev_id,
cmd->spectral_scan_count, param->count,
cmd->spectral_scan_period, param->period,
cmd->spectral_scan_priority, param->spectral_pri,
cmd->spectral_scan_fft_size, param->fft_size,
cmd->spectral_scan_gc_ena, param->gc_enable,
cmd->spectral_scan_restart_ena, param->restart_enable,
cmd->spectral_scan_noise_floor_ref, param->noise_floor_ref,
cmd->spectral_scan_init_delay, param->init_delay,
cmd->spectral_scan_nb_tone_thr, param->nb_tone_thr,
cmd->spectral_scan_str_bin_thr, param->str_bin_thr,
cmd->spectral_scan_wb_rpt_mode, param->wb_rpt_mode,
cmd->spectral_scan_rssi_rpt_mode, param->rssi_rpt_mode,
cmd->spectral_scan_rssi_thr, param->rssi_thr,
cmd->spectral_scan_pwr_format, param->pwr_format,
cmd->spectral_scan_rpt_mode, param->rpt_mode,
cmd->spectral_scan_bin_scale, param->bin_scale,
cmd->spectral_scan_dBm_adj, param->dBm_adj,
cmd->spectral_scan_chn_mask); param->chn_mask);
qdf_print("%s: Status: %d\n\n", __func__, ret); qdf_print("%s: Status: %d\n\n", __func__, ret);
#endif /* OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS */ #endif /* OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS */

View File

@@ -8319,6 +8319,10 @@ QDF_STATUS send_add_clear_mcbc_filter_cmd_tlv(wmi_unified_t wmi_handle,
(clearList ? WMI_MCAST_FILTER_DELETE : WMI_MCAST_FILTER_SET); (clearList ? WMI_MCAST_FILTER_DELETE : WMI_MCAST_FILTER_SET);
cmd->vdev_id = vdev_id; cmd->vdev_id = vdev_id;
WMI_CHAR_ARRAY_TO_MAC_ADDR(multicast_addr.bytes, &cmd->mcastbdcastaddr); WMI_CHAR_ARRAY_TO_MAC_ADDR(multicast_addr.bytes, &cmd->mcastbdcastaddr);
WMI_LOGD("Action:%d; vdev_id:%d; clearList:%d; MCBC MAC Addr: %pM",
cmd->action, vdev_id, clearList, multicast_addr.bytes);
err = wmi_unified_cmd_send(wmi_handle, buf, err = wmi_unified_cmd_send(wmi_handle, buf,
sizeof(*cmd), sizeof(*cmd),
WMI_SET_MCASTBCAST_FILTER_CMDID); WMI_SET_MCASTBCAST_FILTER_CMDID);
@@ -8327,11 +8331,8 @@ QDF_STATUS send_add_clear_mcbc_filter_cmd_tlv(wmi_unified_t wmi_handle,
wmi_buf_free(buf); wmi_buf_free(buf);
return QDF_STATUS_E_FAILURE; return QDF_STATUS_E_FAILURE;
} }
WMI_LOGD("Action:%d; vdev_id:%d; clearList:%d",
cmd->action, vdev_id, clearList);
WMI_LOGD("MCBC MAC Addr: %pM", multicast_addr.bytes);
return 0; return QDF_STATUS_SUCCESS;
} }
/** /**
@@ -8385,6 +8386,8 @@ QDF_STATUS send_gtk_offload_cmd_tlv(wmi_unified_t wmi_handle, uint8_t vdev_id,
cmd->flags = gtk_offload_opcode; cmd->flags = gtk_offload_opcode;
} }
WMI_LOGD("VDEVID: %d, GTK_FLAGS: x%x", vdev_id, cmd->flags);
/* send the wmi command */ /* send the wmi command */
if (wmi_unified_cmd_send(wmi_handle, buf, len, if (wmi_unified_cmd_send(wmi_handle, buf, len,
WMI_GTK_OFFLOAD_CMDID)) { WMI_GTK_OFFLOAD_CMDID)) {
@@ -8393,7 +8396,6 @@ QDF_STATUS send_gtk_offload_cmd_tlv(wmi_unified_t wmi_handle, uint8_t vdev_id,
status = QDF_STATUS_E_FAILURE; status = QDF_STATUS_E_FAILURE;
} }
WMI_LOGD("VDEVID: %d, GTK_FLAGS: x%x", vdev_id, cmd->flags);
out: out:
WMI_LOGD("%s Exit", __func__); WMI_LOGD("%s Exit", __func__);
return status; return status;