diff options
author | Vangala, Amarnath <avangala@codeaurora.org> | 2020-07-14 03:39:52 +0530 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2020-08-25 12:29:01 -0700 |
commit | e1815843066bf82ac90eec43082478eef557dad1 (patch) | |
tree | db162e683588093616b1290932db9f1924433e2b | |
parent | c093d81c8837e7e78b9c9d1f0cfccaab0ba7c777 (diff) | |
download | msm-extra-e1815843066bf82ac90eec43082478eef557dad1.tar.gz |
asoc: dsp: Fix possible invalid memory access due to race condition
Fix for possible double free issue in speaker protection implementation.
Replace vulnerable code with safe call flow.
Change-Id: Id96cf97dd60d85897d64f1d8f2440a5b6de3ba61
Signed-off-by: Vangala, Amarnath <avangala@codeaurora.org>
-rw-r--r-- | dsp/q6afe.c | 171 |
1 files changed, 94 insertions, 77 deletions
diff --git a/dsp/q6afe.c b/dsp/q6afe.c index 0811d6c1..c9a5c95e 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -26,6 +26,8 @@ #define WAKELOCK_TIMEOUT 5000 #define AFE_CLK_TOKEN 1024 +#define SP_V4_NUM_MAX_SPKRS SP_V2_NUM_MAX_SPKRS + struct afe_avcs_payload_port_mapping { u16 port_id; struct avcs_load_unload_modules_payload *payload; @@ -125,6 +127,46 @@ struct wlock { static struct wlock wl; +struct afe_sp_v4_th_vi_ftm_get_param_resp { + struct afe_sp_v4_gen_get_param_resp gen_resp; + int32_t num_ch; + /* Number of channels for Rx signal. + */ + + struct afe_sp_v4_channel_ftm_params + ch_ftm_params[SP_V4_NUM_MAX_SPKRS]; +} __packed; + +struct afe_sp_v4_v_vali_get_param_resp { + struct afe_sp_v4_gen_get_param_resp gen_resp; + int32_t num_ch; + /* Number of channels for Rx signal. + */ + + struct afe_sp_v4_channel_v_vali_params + ch_v_vali_params[SP_V4_NUM_MAX_SPKRS]; +} __packed; + +struct afe_sp_v4_ex_vi_ftm_get_param_resp { + struct afe_sp_v4_gen_get_param_resp gen_resp; + int32_t num_ch; + /* Number of channels for Rx signal. + */ + + struct afe_sp_v4_channel_ex_vi_ftm_params + ch_ex_vi_ftm_params[SP_V4_NUM_MAX_SPKRS]; +} __packed; + +struct afe_sp_v4_max_log_get_param_resp { + struct afe_sp_v4_gen_get_param_resp gen_resp; + int32_t num_ch; + /* Number of channels for Rx signal. + */ + + struct afe_sp_v4_channel_tmax_xmax_params + ch_max_params[SP_V4_NUM_MAX_SPKRS]; +} __packed; + struct afe_ctl { void *apr; atomic_t state; @@ -174,8 +216,14 @@ struct afe_ctl { struct afe_sp_rx_tmax_xmax_logging_resp xt_logging_resp; struct afe_sp_v4_th_vi_calib_resp spv4_calib_data; struct afe_sp_v4_param_vi_channel_map_cfg v4_ch_map_cfg; - struct afe_sp_v4_gen_get_param_resp *spv4_get_param_resp_ptr; - uint32_t spv4_rcvd_param_size; + struct afe_sp_v4_th_vi_ftm_get_param_resp spv4_th_vi_ftm_resp; + uint32_t spv4_th_vi_ftm_rcvd_param_size; + struct afe_sp_v4_v_vali_get_param_resp spv4_v_vali_resp; + uint32_t spv4_v_vali_rcvd_param_size; + struct afe_sp_v4_ex_vi_ftm_get_param_resp spv4_ex_vi_ftm_resp; + uint32_t spv4_ex_vi_ftm_rcvd_param_size; + struct afe_sp_v4_max_log_get_param_resp spv4_max_log_resp; + uint32_t spv4_max_log_rcvd_param_size; struct afe_av_dev_drift_get_param_resp av_dev_drift_resp; struct afe_doa_tracking_mon_get_param_resp doa_tracking_mon_resp; int vi_tx_port; @@ -656,27 +704,16 @@ static int32_t sp_make_afe_callback(uint32_t opcode, uint32_t *payload, break; case AFE_PARAM_ID_SP_V4_TH_VI_FTM_PARAMS: num_ch = data_start[0]; - this_afe.spv4_rcvd_param_size = - sizeof(struct afe_sp_v4_gen_get_param_resp) + - sizeof(struct afe_sp_v4_param_th_vi_ftm_params) + - (num_ch * sizeof(struct afe_sp_v4_channel_ftm_params)); - this_afe.spv4_get_param_resp_ptr = - kzalloc(this_afe.spv4_rcvd_param_size, GFP_ATOMIC); - data_dest = (u32 *)this_afe.spv4_get_param_resp_ptr; + this_afe.spv4_th_vi_ftm_rcvd_param_size = param_hdr.param_size; + data_dest = (u32 *)&this_afe.spv4_th_vi_ftm_resp; expected_size += sizeof(struct afe_sp_v4_param_th_vi_ftm_params) + (num_ch * sizeof(struct afe_sp_v4_channel_ftm_params)); break; case AFE_PARAM_ID_SP_V4_TH_VI_V_VALI_PARAMS: num_ch = data_start[0]; - this_afe.spv4_rcvd_param_size = - sizeof(struct afe_sp_v4_gen_get_param_resp) + - sizeof(struct afe_sp_v4_param_th_vi_v_vali_params) + - (num_ch * - sizeof(struct afe_sp_v4_channel_v_vali_params)); - this_afe.spv4_get_param_resp_ptr = - kzalloc(this_afe.spv4_rcvd_param_size, GFP_ATOMIC); - data_dest = (u32 *)this_afe.spv4_get_param_resp_ptr; + this_afe.spv4_v_vali_rcvd_param_size = param_hdr.param_size; + data_dest = (u32 *)&this_afe.spv4_v_vali_resp; expected_size += sizeof(struct afe_sp_v4_param_th_vi_v_vali_params) + (num_ch * @@ -684,29 +721,19 @@ static int32_t sp_make_afe_callback(uint32_t opcode, uint32_t *payload, break; case AFE_PARAM_ID_SP_V4_EX_VI_FTM_PARAMS: num_ch = data_start[0]; - this_afe.spv4_rcvd_param_size = - sizeof(struct afe_sp_v4_gen_get_param_resp) + - sizeof(struct afe_sp_v4_param_ex_vi_ftm_params) + - (num_ch * sizeof(struct afe_sp_v4_channel_ex_vi_ftm_params)); - this_afe.spv4_get_param_resp_ptr = - kzalloc(this_afe.spv4_rcvd_param_size, GFP_ATOMIC); - data_dest = (u32 *)this_afe.spv4_get_param_resp_ptr; + this_afe.spv4_ex_vi_ftm_rcvd_param_size = param_hdr.param_size; + data_dest = (u32 *)&this_afe.spv4_ex_vi_ftm_resp; expected_size += - sizeof(struct afe_sp_v4_param_ex_vi_ftm_params) + - (num_ch * sizeof(struct afe_sp_v4_channel_ex_vi_ftm_params)); + sizeof(struct afe_sp_v4_param_ex_vi_ftm_params) + + (num_ch * sizeof(struct afe_sp_v4_channel_ex_vi_ftm_params)); break; case AFE_PARAM_ID_SP_V4_RX_TMAX_XMAX_LOGGING: num_ch = data_start[0]; - this_afe.spv4_rcvd_param_size = - sizeof(struct afe_sp_v4_gen_get_param_resp) + - sizeof(struct afe_sp_v4_param_tmax_xmax_logging) + - (num_ch * sizeof(struct afe_sp_v4_channel_tmax_xmax_params)); - this_afe.spv4_get_param_resp_ptr = - kzalloc(this_afe.spv4_rcvd_param_size, GFP_ATOMIC); - data_dest = (u32 *)this_afe.spv4_get_param_resp_ptr; + this_afe.spv4_max_log_rcvd_param_size = param_hdr.param_size; + data_dest = (u32 *)&this_afe.spv4_max_log_resp; expected_size += - sizeof(struct afe_sp_v4_param_tmax_xmax_logging) + - (num_ch * sizeof(struct afe_sp_v4_channel_tmax_xmax_params)); + sizeof(struct afe_sp_v4_param_tmax_xmax_logging) + + (num_ch * sizeof(struct afe_sp_v4_channel_tmax_xmax_params)); break; default: pr_err("%s: Unrecognized param ID %d\n", __func__, @@ -8920,8 +8947,8 @@ static int afe_get_spv4_th_vi_v_vali_data(void *params, uint32_t size) struct param_hdr_v3 param_hdr; int port = SLIMBUS_4_TX; int ret = -EINVAL; - u8 *rcvd_params = NULL; - struct afe_sp_v4_channel_v_vali_params *v_vali_params; + uint32_t min_size = 0; + struct afe_sp_v4_channel_v_vali_params *v_vali_params = NULL; if (!params) { pr_err("%s: Invalid params\n", __func__); @@ -8944,14 +8971,14 @@ static int afe_get_spv4_th_vi_v_vali_data(void *params, uint32_t size) goto get_params_fail; } - rcvd_params = (u8 *)this_afe.spv4_get_param_resp_ptr + - sizeof(struct afe_sp_v4_gen_get_param_resp); + min_size = (size < this_afe.spv4_v_vali_rcvd_param_size) ? + size : this_afe.spv4_v_vali_rcvd_param_size; + memcpy(params, (void*)&this_afe.spv4_v_vali_resp.num_ch, min_size); - memcpy(params, rcvd_params, this_afe.spv4_rcvd_param_size); + v_vali_params = &this_afe.spv4_v_vali_resp.ch_v_vali_params[0]; - v_vali_params = (struct afe_sp_v4_channel_v_vali_params *) - (params + sizeof(struct afe_sp_v4_param_th_vi_v_vali_params)); - pr_debug("%s: Vrms %d %d status %d %d\n", __func__, + pr_debug("%s: num_ch %d Vrms %d %d status %d %d\n", __func__, + this_afe.spv4_v_vali_resp.num_ch, v_vali_params[SP_V2_SPKR_1].vrms_q24, v_vali_params[SP_V2_SPKR_2].vrms_q24, v_vali_params[SP_V2_SPKR_1].status, @@ -8965,7 +8992,6 @@ static int afe_get_spv4_th_vi_v_vali_data(void *params, uint32_t size) ret = 0; get_params_fail: - kfree(this_afe.spv4_get_param_resp_ptr); mutex_unlock(&this_afe.afe_cmd_lock); done: return ret; @@ -9019,7 +9045,7 @@ static int afe_get_spv4_th_vi_ftm_data(void *params, uint32_t size) struct param_hdr_v3 param_hdr; int port = SLIMBUS_4_TX; int ret = -EINVAL; - u8 *rcvd_params = NULL; + uint32_t min_size = 0; struct afe_sp_v4_channel_ftm_params *th_vi_params; if (!params) { @@ -9043,22 +9069,21 @@ static int afe_get_spv4_th_vi_ftm_data(void *params, uint32_t size) goto get_params_fail; } - rcvd_params = (u8 *)this_afe.spv4_get_param_resp_ptr + - sizeof(struct afe_sp_v4_gen_get_param_resp); - memcpy(params, rcvd_params, this_afe.spv4_rcvd_param_size); + min_size = (size < this_afe.spv4_th_vi_ftm_rcvd_param_size) ? + size : this_afe.spv4_th_vi_ftm_rcvd_param_size; + memcpy(params, (void*)&this_afe.spv4_th_vi_ftm_resp.num_ch, min_size); - th_vi_params = (struct afe_sp_v4_channel_ftm_params *) - (params + sizeof(struct afe_sp_v4_param_th_vi_ftm_params)); - pr_debug("%s: DC resistance %d %d temp %d %d status %d %d\n", - __func__, th_vi_params[SP_V2_SPKR_1].dc_res_q24, - th_vi_params[SP_V2_SPKR_2].dc_res_q24, - th_vi_params[SP_V2_SPKR_1].temp_q22, - th_vi_params[SP_V2_SPKR_2].temp_q22, - th_vi_params[SP_V2_SPKR_1].status, - th_vi_params[SP_V2_SPKR_2].status); + th_vi_params = &this_afe.spv4_th_vi_ftm_resp.ch_ftm_params[0]; + pr_debug("%s:num_ch %d, DC resistance %d %d temp %d %d status %d %d\n", + __func__, this_afe.spv4_th_vi_ftm_resp.num_ch, + th_vi_params[SP_V2_SPKR_1].dc_res_q24, + th_vi_params[SP_V2_SPKR_2].dc_res_q24, + th_vi_params[SP_V2_SPKR_1].temp_q22, + th_vi_params[SP_V2_SPKR_2].temp_q22, + th_vi_params[SP_V2_SPKR_1].status, + th_vi_params[SP_V2_SPKR_2].status); ret = 0; get_params_fail: - kfree(this_afe.spv4_get_param_resp_ptr); mutex_unlock(&this_afe.afe_cmd_lock); done: return ret; @@ -9113,7 +9138,7 @@ static int afe_get_spv4_ex_vi_ftm_data(void *params, uint32_t size) struct param_hdr_v3 param_hdr; int port = SLIMBUS_4_TX; int ret = -EINVAL; - u8 *rcvd_params = NULL; + uint32_t min_size = 0; struct afe_sp_v4_channel_ex_vi_ftm_params *ex_vi_ftm_param; if (!params) { @@ -9138,17 +9163,16 @@ static int afe_get_spv4_ex_vi_ftm_data(void *params, uint32_t size) goto get_params_fail; } - rcvd_params = (u8 *)this_afe.spv4_get_param_resp_ptr + - sizeof(struct afe_sp_v4_gen_get_param_resp); + min_size = (size < this_afe.spv4_ex_vi_ftm_rcvd_param_size) ? + size : this_afe.spv4_ex_vi_ftm_rcvd_param_size; + memcpy(params, (void*)&this_afe.spv4_ex_vi_ftm_resp.num_ch, min_size); - memcpy(params, rcvd_params, this_afe.spv4_rcvd_param_size); + ex_vi_ftm_param = &this_afe.spv4_ex_vi_ftm_resp.ch_ex_vi_ftm_params[0]; - ex_vi_ftm_param = (struct afe_sp_v4_channel_ex_vi_ftm_params *) - (params + sizeof(struct afe_sp_v4_param_ex_vi_ftm_params)); - - pr_debug("%s: resistance %d %d force factor %d %d Damping kg/s %d %d\n" + pr_debug("%s:num_ch %d, res %d %d forcefactor %d %d Dmping kg/s %d %d\n" "stiffness N/mm %d %d freq %d %d Qfactor %d %d status %d %d", - __func__, ex_vi_ftm_param[SP_V2_SPKR_1].ftm_re_q24, + __func__, this_afe.spv4_ex_vi_ftm_resp.num_ch, + ex_vi_ftm_param[SP_V2_SPKR_1].ftm_re_q24, ex_vi_ftm_param[SP_V2_SPKR_2].ftm_re_q24, ex_vi_ftm_param[SP_V2_SPKR_1].ftm_Bl_q24, ex_vi_ftm_param[SP_V2_SPKR_2].ftm_Bl_q24, @@ -9164,7 +9188,6 @@ static int afe_get_spv4_ex_vi_ftm_data(void *params, uint32_t size) ex_vi_ftm_param[SP_V2_SPKR_2].status); ret = 0; get_params_fail: - kfree(this_afe.spv4_get_param_resp_ptr); mutex_unlock(&this_afe.afe_cmd_lock); done: return ret; @@ -9223,7 +9246,6 @@ int afe_get_sp_v4_rx_tmax_xmax_logging_data( { struct param_hdr_v3 param_hdr; int ret = -EINVAL; - struct afe_sp_v4_param_tmax_xmax_logging *tmax_xmax_logging; struct afe_sp_v4_channel_tmax_xmax_params *tx_channel_params; uint32_t i, size = 0; @@ -9248,13 +9270,9 @@ int afe_get_sp_v4_rx_tmax_xmax_logging_data( goto get_params_fail; } - tmax_xmax_logging = (struct afe_sp_v4_param_tmax_xmax_logging *) - ((u8 *)this_afe.spv4_get_param_resp_ptr + - sizeof(struct afe_sp_v4_gen_get_param_resp)); - tx_channel_params = (struct afe_sp_v4_channel_tmax_xmax_params *) - ((u8 *)tmax_xmax_logging + - sizeof(struct afe_sp_v4_param_tmax_xmax_logging)); - for (i = 0; i < tmax_xmax_logging->num_ch; i++) { + tx_channel_params = &this_afe.spv4_max_log_resp.ch_max_params[0]; + for (i = 0; i < this_afe.spv4_max_log_resp.num_ch; i++) { + xt_logging->max_excursion[i] = tx_channel_params[i].max_excursion; xt_logging->count_exceeded_excursion[i] = @@ -9267,7 +9285,6 @@ int afe_get_sp_v4_rx_tmax_xmax_logging_data( ret = 0; get_params_fail: - kfree(this_afe.spv4_get_param_resp_ptr); done: return ret; } |