From 1b13d6dd1a6f9d98c212e03ac94c443b450a0974 Mon Sep 17 00:00:00 2001 From: Sandhya Mutha Naga Venkata Date: Wed, 1 Feb 2023 18:17:27 +0530 Subject: [PATCH 01/15] dsp: add lock in ion free to avoid use after free add lock in ion free to protect dma buff and avoid use after free. Change-Id: I6376408ce1a5b98b7aeacc32e44ec4db08ff9df5 Signed-off-by: Prasad Kumpatla --- dsp/msm_audio_ion.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/dsp/msm_audio_ion.c b/dsp/msm_audio_ion.c index 2bf02fcad7bb..a204bc39fa15 100644 --- a/dsp/msm_audio_ion.c +++ b/dsp/msm_audio_ion.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved. + * + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -63,6 +65,7 @@ static void msm_audio_ion_add_allocation( mutex_unlock(&(msm_audio_ion_data->list_mutex)); } +/* This function is called with ion_data list mutex lock */ static int msm_audio_dma_buf_map(struct dma_buf *dma_buf, dma_addr_t *addr, size_t *len) { @@ -151,7 +154,6 @@ static int msm_audio_dma_buf_unmap(struct dma_buf *dma_buf) * should be explicitly acquired to avoid race condition * on adding elements to the list. */ - mutex_lock(&(msm_audio_ion_data.list_mutex)); list_for_each_safe(ptr, next, &(msm_audio_ion_data.alloc_list)) { @@ -175,7 +177,6 @@ static int msm_audio_dma_buf_unmap(struct dma_buf *dma_buf) break; } } - mutex_unlock(&(msm_audio_ion_data.list_mutex)); if (!found) { dev_err(cb_dev, @@ -230,6 +231,7 @@ int msm_audio_ion_get_smmu_info(struct device **cb_dev, return 0; } +/* This function is called with ion_data list mutex lock */ static void *msm_audio_ion_map_kernel(struct dma_buf *dma_buf) { int rc = 0; @@ -278,7 +280,6 @@ static int msm_audio_ion_unmap_kernel(struct dma_buf *dma_buf) * TBD: remove the below section once new API * for unmapping kernel virtual address is available. */ - mutex_lock(&(msm_audio_ion_data.list_mutex)); list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list), list) { if (alloc_data->dma_buf == dma_buf) { @@ -286,7 +287,6 @@ static int msm_audio_ion_unmap_kernel(struct dma_buf *dma_buf) break; } } - mutex_unlock(&(msm_audio_ion_data.list_mutex)); if (!vaddr) { dev_err(cb_dev, @@ -309,7 +309,8 @@ static int msm_audio_ion_unmap_kernel(struct dma_buf *dma_buf) return rc; } -static int msm_audio_ion_map_buf(struct dma_buf *dma_buf, dma_addr_t *paddr, +/* This function is called with ion_data list mutex lock */ +static int msm_audio_ion_buf_map(struct dma_buf *dma_buf, dma_addr_t *paddr, size_t *plen, void **vaddr) { int rc = 0; @@ -331,7 +332,9 @@ static int msm_audio_ion_map_buf(struct dma_buf *dma_buf, dma_addr_t *paddr, if (IS_ERR_OR_NULL(*vaddr)) { pr_err("%s: ION memory mapping for AUDIO failed\n", __func__); rc = -ENOMEM; + mutex_lock(&(msm_audio_ion_data.list_mutex)); msm_audio_dma_buf_unmap(dma_buf); + mutex_unlock(&(msm_audio_ion_data.list_mutex)); goto err; } @@ -390,7 +393,7 @@ int msm_audio_ion_alloc(struct dma_buf **dma_buf, size_t bufsz, goto err; } - rc = msm_audio_ion_map_buf(*dma_buf, paddr, plen, vaddr); + rc = msm_audio_ion_buf_map(*dma_buf, paddr, plen, vaddr); if (rc) { pr_err("%s: failed to map ION buf, rc = %d\n", __func__, rc); goto err; @@ -490,7 +493,7 @@ int msm_audio_ion_import(struct dma_buf **dma_buf, int fd, } } - rc = msm_audio_ion_map_buf(*dma_buf, paddr, plen, vaddr); + rc = msm_audio_ion_buf_map(*dma_buf, paddr, plen, vaddr); if (rc) { pr_err("%s: failed to map ION buf, rc = %d\n", __func__, rc); goto err; @@ -516,6 +519,7 @@ EXPORT_SYMBOL(msm_audio_ion_import); * * Returns 0 on success or error on failure */ +/* This funtion is called with ion_data list mutex lock */ int msm_audio_ion_free(struct dma_buf *dma_buf) { int ret = 0; @@ -525,11 +529,15 @@ int msm_audio_ion_free(struct dma_buf *dma_buf) return -EINVAL; } + mutex_lock(&(msm_audio_ion_data.list_mutex)); ret = msm_audio_ion_unmap_kernel(dma_buf); - if (ret) + if (ret) { + mutex_unlock(&(msm_audio_ion_data.list_mutex)); return ret; + } msm_audio_dma_buf_unmap(dma_buf); + mutex_unlock(&(msm_audio_ion_data.list_mutex)); return 0; } From 4853cb76b0d2a5db0814b7a9a11c34c5ec3ff00b Mon Sep 17 00:00:00 2001 From: Soumya Managoli Date: Thu, 15 Oct 2020 11:08:02 +0800 Subject: [PATCH 02/15] asoc: routing: add PRI_TDM path as echo reference data Add PRI_TDM_TX_0 and PRI_TDM_RX_0 as echo reference data. Change-Id: Iea5e870e081866f882a3ae5c962d92d7c908ef67 Signed-off-by: Soumya Managoli --- asoc/msm-pcm-routing-v2.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c index 1e0fa9b9b91d..a79139db6daa 100644 --- a/asoc/msm-pcm-routing-v2.c +++ b/asoc/msm-pcm-routing-v2.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -5566,6 +5566,14 @@ static int get_ec_ref_port_id(int value, int *index) *index = 40; port_id = AFE_PORT_ID_QUINARY_TDM_TX; break; + case 41: + *index = 41; + port_id = AFE_PORT_ID_PRIMARY_TDM_RX; + break; + case 42: + *index = 42; + port_id = AFE_PORT_ID_PRIMARY_TDM_TX; + break; default: *index = 0; /* NONE */ pr_err("%s: Invalid value %d\n", __func__, value); @@ -5624,6 +5632,7 @@ static const char *const ec_ref_rx[] = { "None", "SLIM_RX", "I2S_RX", "SLIM_7_RX", "RX_CDC_DMA_RX_0", "RX_CDC_DMA_RX_1", "RX_CDC_DMA_RX_2", "RX_CDC_DMA_RX_3", "TX_CDC_DMA_TX_0", "TERT_TDM_RX_2", "SEC_TDM_TX_0", "DISPLAY_PORT1", "SEN_MI2S_RX", "SENARY_MI2S_TX", "QUIN_TDM_TX_0", + "PRI_TDM_RX_0", "PRI_TDM_TX_0", }; static const struct soc_enum msm_route_ec_ref_rx_enum[] = { @@ -29688,6 +29697,8 @@ static const struct snd_soc_dapm_route intercon_tdm[] = { {"AUDIO_REF_EC_UL1 MUX", "TERT_TDM_RX_2", "TERT_TDM_RX_2"}, {"AUDIO_REF_EC_UL1 MUX", "SEC_TDM_TX_0", "SEC_TDM_TX_0"}, {"AUDIO_REF_EC_UL1 MUX", "QUIN_TDM_TX_0", "QUIN_TDM_TX_0"}, + {"AUDIO_REF_EC_UL1 MUX", "PRI_TDM_RX_0", "PRI_TDM_RX_0"}, + {"AUDIO_REF_EC_UL1 MUX", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, {"AUDIO_REF_EC_UL10 MUX", "QUAT_TDM_TX_1", "QUAT_TDM_TX_1"}, {"AUDIO_REF_EC_UL10 MUX", "QUAT_TDM_RX_0", "QUAT_TDM_RX_0"}, @@ -29696,6 +29707,8 @@ static const struct snd_soc_dapm_route intercon_tdm[] = { {"AUDIO_REF_EC_UL10 MUX", "TERT_TDM_TX_0", "TERT_TDM_TX_0"}, {"AUDIO_REF_EC_UL10 MUX", "TERT_TDM_RX_2", "TERT_TDM_RX_2"}, {"AUDIO_REF_EC_UL10 MUX", "SEC_TDM_TX_0", "SEC_TDM_TX_0"}, + {"AUDIO_REF_EC_UL10 MUX", "PRI_TDM_RX_0", "PRI_TDM_RX_0"}, + {"AUDIO_REF_EC_UL10 MUX", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, {"LSM1 Mixer", "QUIN_TDM_TX_0", "QUIN_TDM_TX_0"}, {"LSM1 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"}, From 8a9807e7d73ba22d90eef7e2901c3987b8cf6e65 Mon Sep 17 00:00:00 2001 From: Himanshu Agrawal Date: Fri, 10 Mar 2023 14:58:05 +0530 Subject: [PATCH 03/15] asoc: Compilation fix for SDLLVM toolchain 16.0 Change-Id: Iefd0daebd1931da569d7f6269ff2ab19f63712f1 --- asoc/codecs/Kbuild | 1 + 1 file changed, 1 insertion(+) diff --git a/asoc/codecs/Kbuild b/asoc/codecs/Kbuild index c0213bf00f9c..8669a1e1aba1 100644 --- a/asoc/codecs/Kbuild +++ b/asoc/codecs/Kbuild @@ -220,6 +220,7 @@ CDEFINES += -DANI_LITTLE_BYTE_ENDIAN \ -DPTT_SOCK_SVC_ENABLE \ -Wall\ -Werror\ + -Wno-enum-conversion \ -D__linux__ KBUILD_CPPFLAGS += $(CDEFINES) From e37ef1ceb647ef30635b735983ab9a3c16637681 Mon Sep 17 00:00:00 2001 From: Shalini Manjunatha Date: Tue, 23 May 2023 11:29:05 +0530 Subject: [PATCH 04/15] dsp: afe: check for param size before copying Check for the proper param size before copying, to avoid buffer overflow. Change-Id: I70c52e6ab76f528ea3714784ab9013b070839c40 Signed-off-by: Shalini Manjunatha --- dsp/q6afe.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/dsp/q6afe.c b/dsp/q6afe.c index 5a2a7d464ed2..9a2037164ea9 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #include #include @@ -751,32 +752,74 @@ static int32_t sp_make_afe_callback(uint32_t opcode, uint32_t *payload, switch (param_hdr.param_id) { case AFE_PARAM_ID_CALIB_RES_CFG_V2: expected_size += sizeof(struct asm_calib_res_cfg); + if (param_hdr.param_size != sizeof(struct asm_calib_res_cfg)) { + pr_err("%s: Error: param_size %d is greater than expected\n", + __func__,param_hdr.param_size); + return -EINVAL; + } data_dest = (u32 *) &this_afe.calib_data; break; case AFE_PARAM_ID_SP_V2_TH_VI_FTM_PARAMS: expected_size += sizeof(struct afe_sp_th_vi_ftm_params); + if (param_hdr.param_size != sizeof(struct afe_sp_th_vi_ftm_params)) { + pr_err("%s: Error: param_size %d is greater than expected\n", + __func__,param_hdr.param_size); + return -EINVAL; + } data_dest = (u32 *) &this_afe.th_vi_resp; break; case AFE_PARAM_ID_SP_V2_TH_VI_V_VALI_PARAMS: expected_size += sizeof(struct afe_sp_th_vi_v_vali_params); + if (param_hdr.param_size != sizeof(struct afe_sp_th_vi_v_vali_params)) { + pr_err("%s: Error: param_size %d is greater than expected\n", + __func__,param_hdr.param_size); + return -EINVAL; + } data_dest = (u32 *) &this_afe.th_vi_v_vali_resp; break; case AFE_PARAM_ID_SP_V2_EX_VI_FTM_PARAMS: expected_size += sizeof(struct afe_sp_ex_vi_ftm_params); + if (param_hdr.param_size != sizeof(struct afe_sp_ex_vi_ftm_params)) { + pr_err("%s: Error: param_size %d is greater than expected\n", + __func__,param_hdr.param_size); + return -EINVAL; + } data_dest = (u32 *) &this_afe.ex_vi_resp; break; case AFE_PARAM_ID_SP_RX_TMAX_XMAX_LOGGING: expected_size += sizeof( struct afe_sp_rx_tmax_xmax_logging_param); + if (param_hdr.param_size != sizeof(struct afe_sp_rx_tmax_xmax_logging_param)) { + pr_err("%s: Error: param_size %d is greater than expected\n", + __func__,param_hdr.param_size); + return -EINVAL; + } data_dest = (u32 *) &this_afe.xt_logging_resp; break; case AFE_PARAM_ID_SP_V4_CALIB_RES_CFG: expected_size += sizeof( struct afe_sp_v4_param_th_vi_calib_res_cfg); + if (param_hdr.param_size != sizeof( + struct afe_sp_v4_param_th_vi_calib_res_cfg)) { + pr_err("%s: Error: param_size %d is greater than expected\n", + __func__,param_hdr.param_size); + return -EINVAL; + } data_dest = (u32 *) &this_afe.spv4_calib_data; break; case AFE_PARAM_ID_SP_V4_TH_VI_FTM_PARAMS: num_ch = data_start[0]; + if (num_ch > SP_V2_NUM_MAX_SPKRS) { + pr_err("%s: Error: num_ch %d is greater than expected\n", + __func__,num_ch); + return -EINVAL; + } + if (param_hdr.param_size != (sizeof(struct afe_sp_v4_param_th_vi_ftm_params) + + (num_ch * sizeof(struct afe_sp_v4_channel_ftm_params)))) { + pr_err("%s: Error: param_size %d is greater than expected\n", + __func__,param_hdr.param_size); + return -EINVAL; + } 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 += @@ -785,6 +828,18 @@ static int32_t sp_make_afe_callback(uint32_t opcode, uint32_t *payload, break; case AFE_PARAM_ID_SP_V4_TH_VI_V_VALI_PARAMS: num_ch = data_start[0]; + if (num_ch > SP_V2_NUM_MAX_SPKRS) { + pr_err("%s: Error: num_ch %d is greater than expected\n", + __func__,num_ch); + return -EINVAL; + } + if (param_hdr.param_size != (sizeof(struct afe_sp_v4_param_th_vi_v_vali_params) + + (num_ch * + sizeof(struct afe_sp_v4_channel_v_vali_params)))) { + pr_err("%s: Error: param_size %d is greater than expected\n", + __func__,param_hdr.param_size); + return -EINVAL; + } this_afe.spv4_v_vali_rcvd_param_size = param_hdr.param_size; data_dest = (u32 *)&this_afe.spv4_v_vali_resp; expected_size += @@ -794,6 +849,18 @@ 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]; + if (num_ch > SP_V2_NUM_MAX_SPKRS) { + pr_err("%s: Error: num_ch %d is greater than expected\n", + __func__,num_ch); + return -EINVAL; + } + if (param_hdr.param_size != (sizeof(struct afe_sp_v4_param_ex_vi_ftm_params) + + (num_ch * + sizeof(struct afe_sp_v4_channel_ex_vi_ftm_params)))) { + pr_err("%s: Error: param_size %d is greater than expected\n", + __func__,param_hdr.param_size); + return -EINVAL; + } 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 += @@ -802,6 +869,18 @@ static int32_t sp_make_afe_callback(uint32_t opcode, uint32_t *payload, break; case AFE_PARAM_ID_SP_V4_RX_TMAX_XMAX_LOGGING: num_ch = data_start[0]; + if (num_ch > SP_V2_NUM_MAX_SPKRS) { + pr_err("%s: Error: num_ch %d is greater than expected\n", + __func__,num_ch); + return -EINVAL; + } + if (param_hdr.param_size != (sizeof(struct afe_sp_v4_param_tmax_xmax_logging) + + (num_ch * + sizeof(struct afe_sp_v4_channel_tmax_xmax_params)))) { + pr_err("%s: Error: param_size %d is greater than expected\n", + __func__,param_hdr.param_size); + return -EINVAL; + } this_afe.spv4_max_log_rcvd_param_size = param_hdr.param_size; data_dest = (u32 *)&this_afe.spv4_max_log_resp; expected_size += From 2475586bdb7763cccd0ee13fcc8006c5ef29f262 Mon Sep 17 00:00:00 2001 From: Shalini Manjunatha Date: Mon, 17 Apr 2023 16:49:39 +0530 Subject: [PATCH 05/15] dsp: q6core: validate payload size before access for AVCS Payload size is not checked before payload access for AVCS. Check size to avoid out-of-boundary memory access. Change-Id: I6de3342617bd4f3fb8849ad2230dd57c07469372 Signed-off-by: Shalini Manjunatha --- dsp/q6core.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dsp/q6core.c b/dsp/q6core.c index 7de1b4f93305..6b8065f34e06 100644 --- a/dsp/q6core.c +++ b/dsp/q6core.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -474,6 +475,12 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv) case AVCS_CMD_RSP_LOAD_MODULES: pr_debug("%s: Received AVCS_CMD_RSP_LOAD_MODULES\n", __func__); + if (data->payload_size != ((sizeof(struct avcs_load_unload_modules_sec_payload) + * rsp_payload->num_modules) + sizeof(uint32_t))) { + pr_err("%s: payload size greater than expected size %d\n", + __func__,data->payload_size); + return -EINVAL; + } memcpy(rsp_payload, data->payload, data->payload_size); q6core_lcl.avcs_module_resp_received = 1; wake_up(&q6core_lcl.avcs_module_load_unload_wait); @@ -1036,6 +1043,8 @@ int32_t q6core_avcs_load_unload_modules(struct avcs_load_unload_modules_payload return -ENOMEM; } + rsp_payload->num_modules = num_modules; + memcpy((uint8_t *)mod + sizeof(struct apr_hdr) + sizeof(struct avcs_load_unload_modules_meminfo), payload, payload_size); From ca6932adde839bfcf4320749217948c614e04e2a Mon Sep 17 00:00:00 2001 From: Shalini Manjunatha Date: Wed, 5 Apr 2023 16:35:10 +0530 Subject: [PATCH 06/15] dsp: asm: validate payload size before access Payload size is not checked before payload access. Check size to avoid out-of-boundary memory access. Change-Id: I1bd8281ad263b8c0102335504a740312755b8d15 Signed-off-by: Shalini Manjunatha --- dsp/q6asm.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dsp/q6asm.c b/dsp/q6asm.c index 2939599d907e..4effafb90629 100644 --- a/dsp/q6asm.c +++ b/dsp/q6asm.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. * Author: Brian Swetland * * This software is licensed under the terms of the GNU General Public @@ -2289,6 +2290,15 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) config_debug_fs_read_cb(); + if (data->payload_size != (READDONE_IDX_SEQ_ID + 1) * sizeof(uint32_t)) { + pr_err("%s: payload size of %d is less than expected %d.\n", + __func__, data->payload_size, + ((READDONE_IDX_SEQ_ID + 1) * sizeof(uint32_t))); + spin_unlock_irqrestore( + &(session[session_id].session_lock), + flags); + return -EINVAL; + } dev_vdbg(ac->dev, "%s: ReadDone: status=%d buff_add=0x%x act_size=%d offset=%d\n", __func__, payload[READDONE_IDX_STATUS], payload[READDONE_IDX_BUFADD_LSW], From 731bdaec10b79a68ae4da4599334a5175df4f3d4 Mon Sep 17 00:00:00 2001 From: Soumya Managoli Date: Mon, 17 Apr 2023 17:02:59 +0530 Subject: [PATCH 07/15] ASoC: msm-pcm-voip: Avoid interger underflow There is no check for voip pkt pkt_len,if it contains the minimum required data. This can lead to integer underflow. Add check for the same. Change-Id: I4f57eb125967d52ad8da60d21a440af1f81d2579 Signed-off-by: Soumya Managoli --- asoc/msm-pcm-voip-v2.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/asoc/msm-pcm-voip-v2.c b/asoc/msm-pcm-voip-v2.c index e2ad13b4cc6c..d2f4e0b654d7 100644 --- a/asoc/msm-pcm-voip-v2.c +++ b/asoc/msm-pcm-voip-v2.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -365,6 +366,13 @@ static void voip_process_ul_pkt(uint8_t *voc_pkt, switch (prtd->mode) { case MODE_AMR_WB: case MODE_AMR: { + if (pkt_len <= DSP_FRAME_HDR_LEN) { + pr_err("%s: pkt_len %d is < required len\n", + __func__, pkt_len); + spin_unlock_irqrestore(&prtd->dsp_ul_lock, + dsp_flags); + return; + } /* Remove the DSP frame info header. Header format: * Bits 0-3: Frame rate * Bits 4-7: Frame type @@ -385,6 +393,13 @@ static void voip_process_ul_pkt(uint8_t *voc_pkt, case MODE_4GV_NB: case MODE_4GV_WB: case MODE_4GV_NW: { + if (pkt_len <= DSP_FRAME_HDR_LEN) { + pr_err("%s: pkt_len %d is < required len\n", + __func__, pkt_len); + spin_unlock_irqrestore(&prtd->dsp_ul_lock, + dsp_flags); + return; + } /* Remove the DSP frame info header. * Header format: * Bits 0-3: frame rate @@ -422,6 +437,13 @@ static void voip_process_ul_pkt(uint8_t *voc_pkt, buf_node->frame.frm_hdr.timestamp = timestamp; voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN; + if (pkt_len <= 2 * DSP_FRAME_HDR_LEN) { + pr_err("%s: pkt_len %d is < required len\n", + __func__, pkt_len); + spin_unlock_irqrestore(&prtd->dsp_ul_lock, + dsp_flags); + return; + } /* There are two frames in the buffer. Length of the * first frame: */ @@ -457,6 +479,13 @@ static void voip_process_ul_pkt(uint8_t *voc_pkt, buf_node->frame.frm_hdr.timestamp = timestamp; voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN; + if (pkt_len <= 2 * DSP_FRAME_HDR_LEN) { + pr_err("%s: pkt_len %d is < required len\n", + __func__, pkt_len); + spin_unlock_irqrestore(&prtd->dsp_ul_lock, + dsp_flags); + return; + } /* There are two frames in the buffer. Length * of the second frame: */ From d30e903737ce8703014db4fad72a290b7a2cf3b5 Mon Sep 17 00:00:00 2001 From: Soumya Managoli Date: Wed, 12 Apr 2023 14:27:28 +0530 Subject: [PATCH 08/15] ASoC: msm-pcm-host-voice: Address buffer overflow in hpcm copy Add check for the max hpcm_buf_node size before copy to avoid buffer out of bounds issue. Change-Id: Id647888430ce302359a857ef54d321bee99889bf Signed-off-by: Soumya Managoli --- asoc/msm-pcm-host-voice-v2.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/asoc/msm-pcm-host-voice-v2.c b/asoc/msm-pcm-host-voice-v2.c index 41c3982dd343..caa90b6e24dd 100644 --- a/asoc/msm-pcm-host-voice-v2.c +++ b/asoc/msm-pcm-host-voice-v2.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -656,6 +657,11 @@ static void hpcm_copy_playback_data_from_queue(struct dai_data *dai_data, struct hpcm_buf_node, list); list_del(&buf_node->list); *len = buf_node->frame.len; + if (*len > HPCM_MAX_VOC_PKT_SIZE) { + pr_err("%s: Playback data len %d overflow\n", + __func__, *len); + return; + } memcpy((u8 *)dai_data->vocpcm_ion_buffer.kvaddr, &buf_node->frame.voc_pkt[0], buf_node->frame.len); @@ -683,6 +689,12 @@ static void hpcm_copy_capture_data_to_queue(struct dai_data *dai_data, if (dai_data->substream == NULL) return; + if (len > HPCM_MAX_VOC_PKT_SIZE) { + pr_err("%s: Copy capture data len %d overflow\n", + __func__, len); + return; + } + /* Copy out buffer packet into free_queue */ spin_lock_irqsave(&dai_data->dsp_lock, dsp_flags); From 3aaf15ea4a3ddf15efba5025ae537dd0ce59fec7 Mon Sep 17 00:00:00 2001 From: Sandhya Mutha Naga Venkata Date: Mon, 10 Apr 2023 15:28:02 +0530 Subject: [PATCH 09/15] dsp: afe: Add check for sidetone iir config copy size Avoid OOB access of sidetone iir config array when iir_num_biquad_stages returned from cal block is > 10 Change-Id: I45b95e8bdd1a993a526590c94cf2f9a85c12af37 Signed-off-by: Soumya Managoli --- dsp/q6afe.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/dsp/q6afe.c b/dsp/q6afe.c index 9a2037164ea9..fcfd5a187997 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include #include @@ -8050,6 +8050,14 @@ static int afe_sidetone_iir(u16 tx_port_id) pr_debug("%s: adding 2 to size:%d\n", __func__, size); size = size + 2; } + + if (size > MAX_SIDETONE_IIR_DATA_SIZE) { + pr_err("%s: iir_config size is out of bounds:%d\n", __func__, size); + mutex_unlock(&this_afe.cal_data[cal_index]->lock); + ret = -EINVAL; + goto done; + } + memcpy(&filter_data.iir_config, &st_iir_cal_info->iir_config, size); mutex_unlock(&this_afe.cal_data[cal_index]->lock); From c3e92ec36b046b9c1deaf5674eb33b3c49e8ad89 Mon Sep 17 00:00:00 2001 From: Sandhya Mutha Naga Venkata Date: Tue, 16 May 2023 12:01:48 +0530 Subject: [PATCH 10/15] dsp: afe: Add check for num_channels Check for valid num_channels before accessing. Change-Id: I8f39d12e2f5f52fa145fbd3aed2b023afaa2b53b Signed-off-by: Soumya Managoli --- dsp/q6afe.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dsp/q6afe.c b/dsp/q6afe.c index 9a2037164ea9..791db3978b7c 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -1288,6 +1288,9 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv) sizeof(struct afe_port_mod_evt_rsp_hdr)); uint32_t *dc_presence_flag = num_channels + 1; + if (*num_channels < 1 || *num_channels > 4) + return -EINVAL; + for (i = 0; i < *num_channels; i++) { if (dc_presence_flag[i] == 1) dc_detected = true; From b6877fa2ddd4b6a2dfd807fe750a0bee3ea9aff0 Mon Sep 17 00:00:00 2001 From: Sandhya Mutha Naga Venkata Date: Tue, 11 Apr 2023 10:17:55 +0530 Subject: [PATCH 11/15] dsp: q6voice: Add buf size check for cvs cal data Check for the max size of cvs command register calibration data that can be copied else will result in buffer overflow. Change-Id: Id7a4c5a9795143798b68dfde779f17fb450e3848 Signed-off-by: Soumya Managoli --- dsp/q6voice.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dsp/q6voice.c b/dsp/q6voice.c index 84a2eb94b0e4..ee16121c15a1 100644 --- a/dsp/q6voice.c +++ b/dsp/q6voice.c @@ -2759,6 +2759,13 @@ static int voice_send_cvs_register_cal_cmd(struct voice_data *v) goto unlock; } + if (col_data->cal_data.size >= MAX_COL_INFO_SIZE) { + pr_err("%s: Invalid cal data size %d!\n", + __func__, col_data->cal_data.size); + ret = -EINVAL; + goto unlock; + } + memcpy(&cvs_reg_cal_cmd.cvs_cal_data.column_info[0], (void *) &((struct audio_cal_info_voc_col *) col_data->cal_info)->data, From c334cc823a9e7dd78b81655a981760512ab36dc2 Mon Sep 17 00:00:00 2001 From: Sandhya Mutha Naga Venkata Date: Wed, 12 Apr 2023 12:34:26 +0530 Subject: [PATCH 12/15] dsp: q6core: Avoid OOB access in q6core "num_services", a signed integer when compared with constant results in conversion of signed integer to max possible unsigned int value when "num_services" is a negative value. This can lead to OOB read. Fix is to handle this case. Change-Id: Id6a8f150d9019c972a87f789e4c626337a97bfff Signed-off-by: Soumya Managoli --- dsp/q6core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dsp/q6core.c b/dsp/q6core.c index 6b8065f34e06..4ba76e2b419c 100644 --- a/dsp/q6core.c +++ b/dsp/q6core.c @@ -205,7 +205,7 @@ EXPORT_SYMBOL(q6core_send_uevent); static int parse_fwk_version_info(uint32_t *payload, uint16_t payload_size) { size_t ver_size; - int num_services; + uint16_t num_services; pr_debug("%s: Payload info num services %d\n", __func__, payload[4]); From 75a7e363e642203d1a49bdf1badef9bdebad080c Mon Sep 17 00:00:00 2001 From: Soumya Managoli Date: Thu, 6 Apr 2023 13:55:23 +0530 Subject: [PATCH 13/15] ASoC: msm-pcm-host-voice: Handle OOB access in hpcm_start There is no error check for case when hpcm_start is called for the same RX or TX tap points multiple times. This can result in OOB access of struct vss_ivpcm_tap_point. Handle this scenario with appropriate no_of_tp check. Change-Id: Ib384d21c9bf372f3e5d78f64b5c056e836728399 Signed-off-by: Soumya Managoli --- asoc/msm-pcm-host-voice-v2.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/asoc/msm-pcm-host-voice-v2.c b/asoc/msm-pcm-host-voice-v2.c index caa90b6e24dd..f38915490abe 100644 --- a/asoc/msm-pcm-host-voice-v2.c +++ b/asoc/msm-pcm-host-voice-v2.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. - * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -627,6 +627,12 @@ static int hpcm_start_vocpcm(char *pcm_id, struct hpcm_drv *prtd, } } + if (*no_of_tp != no_of_tp_req && *no_of_tp > 2) { + pr_err("%s:: Invalid hpcm start request\n", __func__); + memset(&prtd->start_cmd, 0, sizeof(struct start_cmd)); + return -EINVAL; + } + if ((prtd->mixer_conf.tx.enable || prtd->mixer_conf.rx.enable) && *no_of_tp == no_of_tp_req) { voc_send_cvp_start_vocpcm(voc_get_session_id(sess_name), From 8945987126e223fac960d051b01796350f72a5cb Mon Sep 17 00:00:00 2001 From: Sandhya Mutha Naga Venkata Date: Tue, 13 Jun 2023 16:04:25 +0530 Subject: [PATCH 14/15] dsp: q6voice: added fix to resolve Lookahead error Change-Id: Ic48a77ad307dc7cb5e72090683616833bbf73ab1 --- dsp/q6voice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dsp/q6voice.c b/dsp/q6voice.c index ee16121c15a1..cbe123de7761 100644 --- a/dsp/q6voice.c +++ b/dsp/q6voice.c @@ -2760,7 +2760,7 @@ static int voice_send_cvs_register_cal_cmd(struct voice_data *v) } if (col_data->cal_data.size >= MAX_COL_INFO_SIZE) { - pr_err("%s: Invalid cal data size %d!\n", + pr_err("%s: Invalid cal data size %ld!\n", __func__, col_data->cal_data.size); ret = -EINVAL; goto unlock; From 342f8ec22b291999b7b7afbe5d1cc832ccfda90a Mon Sep 17 00:00:00 2001 From: Sandhya Mutha Naga Venkata Date: Wed, 14 Jun 2023 12:28:28 +0530 Subject: [PATCH 15/15] dsp: Added fix to resolve compilation error - Format specifier mismatch causing compilation error - Modified the format specifier to fix the issue Change-Id: I2a9c278bfa05594e949a91c8358d2e4f87026b04 Signed-off-by: Sandhya Mutha Naga Venkata --- dsp/q6asm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dsp/q6asm.c b/dsp/q6asm.c index 4effafb90629..88f3acf62618 100644 --- a/dsp/q6asm.c +++ b/dsp/q6asm.c @@ -2291,7 +2291,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) config_debug_fs_read_cb(); if (data->payload_size != (READDONE_IDX_SEQ_ID + 1) * sizeof(uint32_t)) { - pr_err("%s: payload size of %d is less than expected %d.\n", + pr_err("%s: payload size of %d is less than expected %ld.\n", __func__, data->payload_size, ((READDONE_IDX_SEQ_ID + 1) * sizeof(uint32_t))); spin_unlock_irqrestore(