Merge tag 'LA.UM.9.12.r1-15600-SMxx50.0' of https://git.codelinaro.org/clo/la/platform/vendor/opensource/audio-kernel into android13-4.19-kona
"LA.UM.9.12.r1-15600-SMxx50.0" * tag 'LA.UM.9.12.r1-15600-SMxx50.0' of https://git.codelinaro.org/clo/la/platform/vendor/opensource/audio-kernel: ASoC: msm-pcm-host-voice: Check validity of session idx dsp: q6lsm: Address use after free for mmap handle dsp: q6lsm: Add check for payload buffer ASoC: Resolve use after free in listen sound client ASoC: dsp: q6core: Avoid use after free ASoC: msm-pcm-q6-v2: Add dsp buf check ASoC: dsp: q6core: Avoid use after free ASoC: msm-pcm-host-voice: Address buffer overflow in hpcm copy ASoC: msm-pcm-q6-v2: Add dsp buf check dsp: q6core: Avoid OOB access in q6core ASoC: msm-pcm-host-voice: Handle OOB access in hpcm_start dsp: afe: Add check for num_channels dsp: asm: validate payload size before access dsp: afe: Add check for sidetone iir config copy size dsp: q6voice: Add buf size check for cvs cal data ASoC: msm-pcm-voip: Avoid interger underflow dsp: afe: check for param size before copying dsp: q6core: validate payload size before access for AVCS Change-Id: I586bec33dde9200927e0d6226237aa932a5f7531
This commit is contained in:
@@ -2112,6 +2112,7 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
|||||||
case SNDRV_LSM_GET_MODULE_PARAMS_32: {
|
case SNDRV_LSM_GET_MODULE_PARAMS_32: {
|
||||||
struct lsm_params_get_info_32 p_info_32, *param_info_rsp = NULL;
|
struct lsm_params_get_info_32 p_info_32, *param_info_rsp = NULL;
|
||||||
struct lsm_params_get_info *p_info = NULL;
|
struct lsm_params_get_info *p_info = NULL;
|
||||||
|
prtd->lsm_client->get_param_payload = NULL;
|
||||||
|
|
||||||
memset(&p_info_32, 0 , sizeof(p_info_32));
|
memset(&p_info_32, 0 , sizeof(p_info_32));
|
||||||
if (!prtd->lsm_client->use_topology) {
|
if (!prtd->lsm_client->use_topology) {
|
||||||
@@ -2162,6 +2163,7 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
|||||||
__func__, err);
|
__func__, err);
|
||||||
kfree(p_info);
|
kfree(p_info);
|
||||||
kfree(prtd->lsm_client->get_param_payload);
|
kfree(prtd->lsm_client->get_param_payload);
|
||||||
|
prtd->lsm_client->get_param_payload = NULL;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2172,6 +2174,7 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
|||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
kfree(p_info);
|
kfree(p_info);
|
||||||
kfree(prtd->lsm_client->get_param_payload);
|
kfree(prtd->lsm_client->get_param_payload);
|
||||||
|
prtd->lsm_client->get_param_payload = NULL;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2196,6 +2199,7 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
|
|||||||
kfree(p_info);
|
kfree(p_info);
|
||||||
kfree(param_info_rsp);
|
kfree(param_info_rsp);
|
||||||
kfree(prtd->lsm_client->get_param_payload);
|
kfree(prtd->lsm_client->get_param_payload);
|
||||||
|
prtd->lsm_client->get_param_payload = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SNDRV_LSM_REG_SND_MODEL_V2:
|
case SNDRV_LSM_REG_SND_MODEL_V2:
|
||||||
@@ -2407,6 +2411,7 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
|
|||||||
|
|
||||||
case SNDRV_LSM_GET_MODULE_PARAMS: {
|
case SNDRV_LSM_GET_MODULE_PARAMS: {
|
||||||
struct lsm_params_get_info temp_p_info, *p_info = NULL;
|
struct lsm_params_get_info temp_p_info, *p_info = NULL;
|
||||||
|
prtd->lsm_client->get_param_payload = NULL;
|
||||||
|
|
||||||
memset(&temp_p_info, 0, sizeof(temp_p_info));
|
memset(&temp_p_info, 0, sizeof(temp_p_info));
|
||||||
if (!prtd->lsm_client->use_topology) {
|
if (!prtd->lsm_client->use_topology) {
|
||||||
@@ -2478,6 +2483,7 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
|
|||||||
free:
|
free:
|
||||||
kfree(p_info);
|
kfree(p_info);
|
||||||
kfree(prtd->lsm_client->get_param_payload);
|
kfree(prtd->lsm_client->get_param_payload);
|
||||||
|
prtd->lsm_client->get_param_payload = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SNDRV_LSM_EVENT_STATUS:
|
case SNDRV_LSM_EVENT_STATUS:
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
|
||||||
|
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
@@ -626,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) &&
|
if ((prtd->mixer_conf.tx.enable || prtd->mixer_conf.rx.enable) &&
|
||||||
*no_of_tp == no_of_tp_req) {
|
*no_of_tp == no_of_tp_req) {
|
||||||
voc_send_cvp_start_vocpcm(voc_get_session_id(sess_name),
|
voc_send_cvp_start_vocpcm(voc_get_session_id(sess_name),
|
||||||
@@ -656,6 +663,11 @@ static void hpcm_copy_playback_data_from_queue(struct dai_data *dai_data,
|
|||||||
struct hpcm_buf_node, list);
|
struct hpcm_buf_node, list);
|
||||||
list_del(&buf_node->list);
|
list_del(&buf_node->list);
|
||||||
*len = buf_node->frame.len;
|
*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,
|
memcpy((u8 *)dai_data->vocpcm_ion_buffer.kvaddr,
|
||||||
&buf_node->frame.voc_pkt[0],
|
&buf_node->frame.voc_pkt[0],
|
||||||
buf_node->frame.len);
|
buf_node->frame.len);
|
||||||
@@ -683,6 +695,12 @@ static void hpcm_copy_capture_data_to_queue(struct dai_data *dai_data,
|
|||||||
if (dai_data->substream == NULL)
|
if (dai_data->substream == NULL)
|
||||||
return;
|
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 */
|
/* Copy out buffer packet into free_queue */
|
||||||
spin_lock_irqsave(&dai_data->dsp_lock, dsp_flags);
|
spin_lock_irqsave(&dai_data->dsp_lock, dsp_flags);
|
||||||
|
|
||||||
@@ -725,6 +743,13 @@ void hpcm_notify_evt_processing(uint8_t *data, char *session,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prtd->mixer_conf.sess_indx < VOICE_INDEX ||
|
||||||
|
prtd->mixer_conf.sess_indx >= MAX_SESSION) {
|
||||||
|
pr_err("%s:: Invalid session idx %d\n",
|
||||||
|
__func__, prtd->mixer_conf.sess_indx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (notify_evt->tap_point == VSS_IVPCM_TAP_POINT_TX_DEFAULT) {
|
if (notify_evt->tap_point == VSS_IVPCM_TAP_POINT_TX_DEFAULT) {
|
||||||
tp = &prtd->session[prtd->mixer_conf.sess_indx].tx_tap_point;
|
tp = &prtd->session[prtd->mixer_conf.sess_indx].tx_tap_point;
|
||||||
tmd = &prtd->mixer_conf.tx;
|
tmd = &prtd->mixer_conf.tx;
|
||||||
|
|||||||
@@ -1016,7 +1016,7 @@ static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == 0 || size < prtd->pcm_count) {
|
if ((size == 0 || size < prtd->pcm_count) && ((offset + size) < prtd->pcm_count)) {
|
||||||
memset(bufptr + offset + size, 0, prtd->pcm_count - size);
|
memset(bufptr + offset + size, 0, prtd->pcm_count - size);
|
||||||
if (fbytes > prtd->pcm_count)
|
if (fbytes > prtd->pcm_count)
|
||||||
size = xfer = prtd->pcm_count;
|
size = xfer = prtd->pcm_count;
|
||||||
|
|||||||
@@ -1288,6 +1288,9 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv)
|
|||||||
sizeof(struct afe_port_mod_evt_rsp_hdr));
|
sizeof(struct afe_port_mod_evt_rsp_hdr));
|
||||||
uint32_t *dc_presence_flag = num_channels + 1;
|
uint32_t *dc_presence_flag = num_channels + 1;
|
||||||
|
|
||||||
|
if (*num_channels < 1 || *num_channels > 4)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
for (i = 0; i < *num_channels; i++) {
|
for (i = 0; i < *num_channels; i++) {
|
||||||
if (dc_presence_flag[i] == 1)
|
if (dc_presence_flag[i] == 1)
|
||||||
dc_detected = true;
|
dc_detected = true;
|
||||||
@@ -8050,6 +8053,14 @@ static int afe_sidetone_iir(u16 tx_port_id)
|
|||||||
pr_debug("%s: adding 2 to size:%d\n", __func__, size);
|
pr_debug("%s: adding 2 to size:%d\n", __func__, size);
|
||||||
size = size + 2;
|
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);
|
memcpy(&filter_data.iir_config, &st_iir_cal_info->iir_config, size);
|
||||||
mutex_unlock(&this_afe.cal_data[cal_index]->lock);
|
mutex_unlock(&this_afe.cal_data[cal_index]->lock);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
|
||||||
|
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
* Author: Brian Swetland <swetland@google.com>
|
* Author: Brian Swetland <swetland@google.com>
|
||||||
*
|
*
|
||||||
* This software is licensed under the terms of the GNU General Public
|
* 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();
|
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",
|
dev_vdbg(ac->dev, "%s: ReadDone: status=%d buff_add=0x%x act_size=%d offset=%d\n",
|
||||||
__func__, payload[READDONE_IDX_STATUS],
|
__func__, payload[READDONE_IDX_STATUS],
|
||||||
payload[READDONE_IDX_BUFADD_LSW],
|
payload[READDONE_IDX_BUFADD_LSW],
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ EXPORT_SYMBOL(q6core_send_uevent);
|
|||||||
static int parse_fwk_version_info(uint32_t *payload, uint16_t payload_size)
|
static int parse_fwk_version_info(uint32_t *payload, uint16_t payload_size)
|
||||||
{
|
{
|
||||||
size_t ver_size;
|
size_t ver_size;
|
||||||
int num_services;
|
uint16_t num_services;
|
||||||
|
|
||||||
pr_debug("%s: Payload info num services %d\n",
|
pr_debug("%s: Payload info num services %d\n",
|
||||||
__func__, payload[4]);
|
__func__, payload[4]);
|
||||||
@@ -475,6 +475,8 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv)
|
|||||||
case AVCS_CMD_RSP_LOAD_MODULES:
|
case AVCS_CMD_RSP_LOAD_MODULES:
|
||||||
pr_debug("%s: Received AVCS_CMD_RSP_LOAD_MODULES\n",
|
pr_debug("%s: Received AVCS_CMD_RSP_LOAD_MODULES\n",
|
||||||
__func__);
|
__func__);
|
||||||
|
if (!rsp_payload)
|
||||||
|
return -EINVAL;
|
||||||
if (data->payload_size != ((sizeof(struct avcs_load_unload_modules_sec_payload)
|
if (data->payload_size != ((sizeof(struct avcs_load_unload_modules_sec_payload)
|
||||||
* rsp_payload->num_modules) + sizeof(uint32_t))) {
|
* rsp_payload->num_modules) + sizeof(uint32_t))) {
|
||||||
pr_err("%s: payload size greater than expected size %d\n",
|
pr_err("%s: payload size greater than expected size %d\n",
|
||||||
@@ -1099,6 +1101,7 @@ int32_t q6core_avcs_load_unload_modules(struct avcs_load_unload_modules_payload
|
|||||||
done:
|
done:
|
||||||
kfree(mod);
|
kfree(mod);
|
||||||
kfree(rsp_payload);
|
kfree(rsp_payload);
|
||||||
|
rsp_payload = NULL;
|
||||||
mutex_unlock(&(q6core_lcl.cmd_lock));
|
mutex_unlock(&(q6core_lcl.cmd_lock));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, Linux Foundation. All rights reserved.
|
* Copyright (c) 2013-2020, Linux Foundation. All rights reserved.
|
||||||
|
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
@@ -235,6 +236,11 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!client->get_param_payload) {
|
||||||
|
pr_err("%s: invalid get_param_payload buffer ptr\n", __func__);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
memcpy((u8 *)client->get_param_payload,
|
memcpy((u8 *)client->get_param_payload,
|
||||||
(u8 *)payload + payload_min_size_expected, param_size);
|
(u8 *)payload + payload_min_size_expected, param_size);
|
||||||
done:
|
done:
|
||||||
@@ -472,6 +478,10 @@ static int q6lsm_apr_send_pkt(struct lsm_client *client, void *handle,
|
|||||||
}
|
}
|
||||||
|
|
||||||
pr_debug("%s: enter wait %d\n", __func__, wait);
|
pr_debug("%s: enter wait %d\n", __func__, wait);
|
||||||
|
if (mmap_handle_p) {
|
||||||
|
pr_debug("%s: Invalid mmap_handle\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
if (wait)
|
if (wait)
|
||||||
mutex_lock(&lsm_common.apr_lock);
|
mutex_lock(&lsm_common.apr_lock);
|
||||||
if (mmap_p) {
|
if (mmap_p) {
|
||||||
@@ -517,6 +527,7 @@ static int q6lsm_apr_send_pkt(struct lsm_client *client, void *handle,
|
|||||||
|
|
||||||
if (mmap_p && *mmap_p == 0)
|
if (mmap_p && *mmap_p == 0)
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
mmap_handle_p = NULL;
|
||||||
pr_debug("%s: leave ret %d\n", __func__, ret);
|
pr_debug("%s: leave ret %d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -2040,7 +2051,8 @@ static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv)
|
|||||||
case LSM_SESSION_CMDRSP_SHARED_MEM_MAP_REGIONS:
|
case LSM_SESSION_CMDRSP_SHARED_MEM_MAP_REGIONS:
|
||||||
if (atomic_read(&client->cmd_state) == CMD_STATE_WAIT_RESP) {
|
if (atomic_read(&client->cmd_state) == CMD_STATE_WAIT_RESP) {
|
||||||
spin_lock_irqsave(&mmap_lock, flags);
|
spin_lock_irqsave(&mmap_lock, flags);
|
||||||
*mmap_handle_p = command;
|
if (mmap_handle_p)
|
||||||
|
*mmap_handle_p = command;
|
||||||
/* spin_unlock_irqrestore implies barrier */
|
/* spin_unlock_irqrestore implies barrier */
|
||||||
spin_unlock_irqrestore(&mmap_lock, flags);
|
spin_unlock_irqrestore(&mmap_lock, flags);
|
||||||
atomic_set(&client->cmd_state, CMD_STATE_CLEARED);
|
atomic_set(&client->cmd_state, CMD_STATE_CLEARED);
|
||||||
|
|||||||
@@ -2759,6 +2759,13 @@ static int voice_send_cvs_register_cal_cmd(struct voice_data *v)
|
|||||||
goto unlock;
|
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],
|
memcpy(&cvs_reg_cal_cmd.cvs_cal_data.column_info[0],
|
||||||
(void *) &((struct audio_cal_info_voc_col *)
|
(void *) &((struct audio_cal_info_voc_col *)
|
||||||
col_data->cal_info)->data,
|
col_data->cal_info)->data,
|
||||||
|
|||||||
Reference in New Issue
Block a user