From 775fca8289eff931f91ff6e8c36cf2034ba59e88 Mon Sep 17 00:00:00 2001 From: Weiyin Jiang Date: Wed, 16 Mar 2016 12:51:03 +0800 Subject: ASoC: msm: audio-effects: fix stack overread and heap overwrite Fix overwrite of updt_params allocated in heap, and stack overread where param pointer is passed from user space. CRs-Fixed: 989628 Change-Id: Ida8bdb7da2fcb97023dce3b6eafe4b899a51cb66 Signed-off-by: Weiyin Jiang --- drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c | 3 +- include/sound/msm-audio-effects-q6-v2.h | 4 +- sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c | 835 +++++++++++++++++------- sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c | 2 +- 4 files changed, 588 insertions(+), 256 deletions(-) diff --git a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c index c100c47..3ba20ca 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +++ b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -20,7 +20,6 @@ #include #define MAX_CHANNELS_SUPPORTED 8 -#define MAX_PP_PARAMS_SZ 128 #define WAIT_TIMEDOUT_DURATION_SECS 1 struct q6audio_effects { diff --git a/include/sound/msm-audio-effects-q6-v2.h b/include/sound/msm-audio-effects-q6-v2.h index cbdea32..6bc2338 100644 --- a/include/sound/msm-audio-effects-q6-v2.h +++ b/include/sound/msm-audio-effects-q6-v2.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -16,6 +16,8 @@ #include +#define MAX_PP_PARAMS_SZ 128 + bool msm_audio_effects_is_effmodule_supp_in_top(int effect_module, int topology); diff --git a/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c index e26c453..1c08842 100644 --- a/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -20,6 +20,24 @@ #define MAX_ENABLE_CMD_SIZE 32 +#define GET_NEXT(ptr, upper_limit, rc) \ +({ \ + if (((ptr) + 1) > (upper_limit)) { \ + pr_err("%s: param list out of boundary\n", __func__); \ + (rc) = -EINVAL; \ + } \ + ((rc) == 0) ? *(ptr)++ : -EINVAL; \ +}) + +#define CHECK_PARAM_LEN(len, max_len, tag, rc) \ +do { \ + if ((len) > (max_len)) { \ + pr_err("%s: params length overflows\n", (tag)); \ + (rc) = -EINVAL; \ + } \ +} while (0) + + bool msm_audio_effects_is_effmodule_supp_in_top(int effect_module, int topology) { @@ -109,15 +127,16 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, struct virtualizer_params *virtualizer, long *values) { - int devices = *values++; - int num_commands = *values++; - char *params; + long *param_max_offset = values + MAX_PP_PARAMS_SZ - 1; + char *params = NULL; + int rc = 0; + int devices = GET_NEXT(values, param_max_offset, rc); + int num_commands = GET_NEXT(values, param_max_offset, rc); int *updt_params, i, prev_enable_flag; uint32_t params_length = (MAX_INBAND_PARAM_SZ); - int rc = 0; pr_debug("%s\n", __func__); - if (!ac) { + if (!ac || (devices == -EINVAL) || (num_commands == -EINVAL)) { pr_err("%s: cannot set audio effects\n", __func__); return -EINVAL; } @@ -130,10 +149,14 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, updt_params = (int *)params; params_length = 0; for (i = 0; i < num_commands; i++) { - uint32_t command_id = *values++; - uint32_t command_config_state = *values++; - uint32_t index_offset = *values++; - uint32_t length = *values++; + uint32_t command_id = + GET_NEXT(values, param_max_offset, rc); + uint32_t command_config_state = + GET_NEXT(values, param_max_offset, rc); + uint32_t index_offset = + GET_NEXT(values, param_max_offset, rc); + uint32_t length = + GET_NEXT(values, param_max_offset, rc); switch (command_id) { case VIRTUALIZER_ENABLE: if (length != 1 || index_offset != 0) { @@ -142,17 +165,26 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, goto invalid_config; } prev_enable_flag = virtualizer->enable_flag; - virtualizer->enable_flag = *values++; + virtualizer->enable_flag = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s:VIRT ENABLE prev:%d, new:%d\n", __func__, prev_enable_flag, virtualizer->enable_flag); if (prev_enable_flag != virtualizer->enable_flag) { - *updt_params++ = AUDPROC_MODULE_ID_VIRTUALIZER; - *updt_params++ = - AUDPROC_PARAM_ID_VIRTUALIZER_ENABLE; - *updt_params++ = VIRTUALIZER_ENABLE_PARAM_SZ; - *updt_params++ = virtualizer->enable_flag; params_length += COMMAND_PAYLOAD_SZ + VIRTUALIZER_ENABLE_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "VIRT ENABLE", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_VIRTUALIZER; + *updt_params++ = + AUDPROC_PARAM_ID_VIRTUALIZER_ENABLE; + *updt_params++ = + VIRTUALIZER_ENABLE_PARAM_SZ; + *updt_params++ = + virtualizer->enable_flag; } break; case VIRTUALIZER_STRENGTH: @@ -161,17 +193,26 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, rc = -EINVAL; goto invalid_config; } - virtualizer->strength = *values++; + virtualizer->strength = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s: VIRT STRENGTH val: %d\n", __func__, virtualizer->strength); if (command_config_state == CONFIG_SET) { - *updt_params++ = AUDPROC_MODULE_ID_VIRTUALIZER; + params_length += COMMAND_PAYLOAD_SZ + + VIRTUALIZER_STRENGTH_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "VIRT STRENGTH", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_VIRTUALIZER; *updt_params++ = AUDPROC_PARAM_ID_VIRTUALIZER_STRENGTH; - *updt_params++ = VIRTUALIZER_STRENGTH_PARAM_SZ; - *updt_params++ = virtualizer->strength; - params_length += COMMAND_PAYLOAD_SZ + + *updt_params++ = VIRTUALIZER_STRENGTH_PARAM_SZ; + *updt_params++ = + virtualizer->strength; } break; case VIRTUALIZER_OUT_TYPE: @@ -180,17 +221,26 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, rc = -EINVAL; goto invalid_config; } - virtualizer->out_type = *values++; + virtualizer->out_type = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s: VIRT OUT_TYPE val:%d\n", __func__, virtualizer->out_type); if (command_config_state == CONFIG_SET) { - *updt_params++ = AUDPROC_MODULE_ID_VIRTUALIZER; + params_length += COMMAND_PAYLOAD_SZ + + VIRTUALIZER_OUT_TYPE_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "VIRT OUT_TYPE", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_VIRTUALIZER; *updt_params++ = AUDPROC_PARAM_ID_VIRTUALIZER_OUT_TYPE; - *updt_params++ = VIRTUALIZER_OUT_TYPE_PARAM_SZ; - *updt_params++ = virtualizer->out_type; - params_length += COMMAND_PAYLOAD_SZ + + *updt_params++ = VIRTUALIZER_OUT_TYPE_PARAM_SZ; + *updt_params++ = + virtualizer->out_type; } break; case VIRTUALIZER_GAIN_ADJUST: @@ -199,18 +249,26 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, rc = -EINVAL; goto invalid_config; } - virtualizer->gain_adjust = *values++; + virtualizer->gain_adjust = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s: VIRT GAIN_ADJUST val:%d\n", __func__, virtualizer->gain_adjust); if (command_config_state == CONFIG_SET) { - *updt_params++ = AUDPROC_MODULE_ID_VIRTUALIZER; - *updt_params++ = - AUDPROC_PARAM_ID_VIRTUALIZER_GAIN_ADJUST; - *updt_params++ = - VIRTUALIZER_GAIN_ADJUST_PARAM_SZ; - *updt_params++ = virtualizer->gain_adjust; params_length += COMMAND_PAYLOAD_SZ + VIRTUALIZER_GAIN_ADJUST_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "VIRT GAIN_ADJUST", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_VIRTUALIZER; + *updt_params++ = + AUDPROC_PARAM_ID_VIRTUALIZER_GAIN_ADJUST; + *updt_params++ = + VIRTUALIZER_GAIN_ADJUST_PARAM_SZ; + *updt_params++ = + virtualizer->gain_adjust; } break; default: @@ -218,7 +276,7 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, break; } } - if (params_length && !msm_dts_eagle_is_hpx_on()) + if (params_length && !msm_dts_eagle_is_hpx_on() && (rc == 0)) q6asm_send_audio_effects_params(ac, params, params_length); else @@ -232,15 +290,16 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, struct reverb_params *reverb, long *values) { - int devices = *values++; - int num_commands = *values++; - char *params; + long *param_max_offset = values + MAX_PP_PARAMS_SZ - 1; + char *params = NULL; + int rc = 0; + int devices = GET_NEXT(values, param_max_offset, rc); + int num_commands = GET_NEXT(values, param_max_offset, rc); int *updt_params, i, prev_enable_flag; uint32_t params_length = (MAX_INBAND_PARAM_SZ); - int rc = 0; pr_debug("%s\n", __func__); - if (!ac) { + if (!ac || (devices == -EINVAL) || (num_commands == -EINVAL)) { pr_err("%s: cannot set audio effects\n", __func__); return -EINVAL; } @@ -253,10 +312,14 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, updt_params = (int *)params; params_length = 0; for (i = 0; i < num_commands; i++) { - uint32_t command_id = *values++; - uint32_t command_config_state = *values++; - uint32_t index_offset = *values++; - uint32_t length = *values++; + uint32_t command_id = + GET_NEXT(values, param_max_offset, rc); + uint32_t command_config_state = + GET_NEXT(values, param_max_offset, rc); + uint32_t index_offset = + GET_NEXT(values, param_max_offset, rc); + uint32_t length = + GET_NEXT(values, param_max_offset, rc); switch (command_id) { case REVERB_ENABLE: if (length != 1 || index_offset != 0) { @@ -265,16 +328,26 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, goto invalid_config; } prev_enable_flag = reverb->enable_flag; - reverb->enable_flag = *values++; + reverb->enable_flag = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s:REVERB_ENABLE prev:%d,new:%d\n", __func__, prev_enable_flag, reverb->enable_flag); if (prev_enable_flag != reverb->enable_flag) { - *updt_params++ = AUDPROC_MODULE_ID_REVERB; - *updt_params++ = AUDPROC_PARAM_ID_REVERB_ENABLE; - *updt_params++ = REVERB_ENABLE_PARAM_SZ; - *updt_params++ = reverb->enable_flag; params_length += COMMAND_PAYLOAD_SZ + REVERB_ENABLE_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "REVERB_ENABLE", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_REVERB; + *updt_params++ = + AUDPROC_PARAM_ID_REVERB_ENABLE; + *updt_params++ = + REVERB_ENABLE_PARAM_SZ; + *updt_params++ = + reverb->enable_flag; } break; case REVERB_MODE: @@ -283,16 +356,26 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, rc = -EINVAL; goto invalid_config; } - reverb->mode = *values++; + reverb->mode = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_MODE val:%d\n", __func__, reverb->mode); if (command_config_state == CONFIG_SET) { - *updt_params++ = AUDPROC_MODULE_ID_REVERB; - *updt_params++ = AUDPROC_PARAM_ID_REVERB_MODE; - *updt_params++ = REVERB_MODE_PARAM_SZ; - *updt_params++ = reverb->mode; params_length += COMMAND_PAYLOAD_SZ + REVERB_MODE_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "REVERB_MODE", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_REVERB; + *updt_params++ = + AUDPROC_PARAM_ID_REVERB_MODE; + *updt_params++ = + REVERB_MODE_PARAM_SZ; + *updt_params++ = + reverb->mode; } break; case REVERB_PRESET: @@ -301,16 +384,26 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, rc = -EINVAL; goto invalid_config; } - reverb->preset = *values++; + reverb->preset = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_PRESET val:%d\n", __func__, reverb->preset); if (command_config_state == CONFIG_SET) { - *updt_params++ = AUDPROC_MODULE_ID_REVERB; - *updt_params++ = AUDPROC_PARAM_ID_REVERB_PRESET; - *updt_params++ = REVERB_PRESET_PARAM_SZ; - *updt_params++ = reverb->preset; params_length += COMMAND_PAYLOAD_SZ + REVERB_PRESET_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "REVERB_PRESET", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_REVERB; + *updt_params++ = + AUDPROC_PARAM_ID_REVERB_PRESET; + *updt_params++ = + REVERB_PRESET_PARAM_SZ; + *updt_params++ = + reverb->preset; } break; case REVERB_WET_MIX: @@ -319,17 +412,26 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, rc = -EINVAL; goto invalid_config; } - reverb->wet_mix = *values++; + reverb->wet_mix = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_WET_MIX val:%d\n", __func__, reverb->wet_mix); if (command_config_state == CONFIG_SET) { - *updt_params++ = AUDPROC_MODULE_ID_REVERB; + params_length += COMMAND_PAYLOAD_SZ + + REVERB_WET_MIX_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "REVERB_WET_MIX", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_REVERB; *updt_params++ = AUDPROC_PARAM_ID_REVERB_WET_MIX; - *updt_params++ = REVERB_WET_MIX_PARAM_SZ; - *updt_params++ = reverb->wet_mix; - params_length += COMMAND_PAYLOAD_SZ + + *updt_params++ = REVERB_WET_MIX_PARAM_SZ; + *updt_params++ = + reverb->wet_mix; } break; case REVERB_GAIN_ADJUST: @@ -338,17 +440,26 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, rc = -EINVAL; goto invalid_config; } - reverb->gain_adjust = *values++; + reverb->gain_adjust = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_GAIN_ADJUST val:%d\n", __func__, reverb->gain_adjust); if (command_config_state == CONFIG_SET) { - *updt_params++ = AUDPROC_MODULE_ID_REVERB; + params_length += COMMAND_PAYLOAD_SZ + + REVERB_GAIN_ADJUST_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "REVERB_GAIN_ADJUST", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_REVERB; *updt_params++ = AUDPROC_PARAM_ID_REVERB_GAIN_ADJUST; - *updt_params++ = REVERB_GAIN_ADJUST_PARAM_SZ; - *updt_params++ = reverb->gain_adjust; - params_length += COMMAND_PAYLOAD_SZ + + *updt_params++ = REVERB_GAIN_ADJUST_PARAM_SZ; + *updt_params++ = + reverb->gain_adjust; } break; case REVERB_ROOM_LEVEL: @@ -357,17 +468,26 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, rc = -EINVAL; goto invalid_config; } - reverb->room_level = *values++; + reverb->room_level = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_ROOM_LEVEL val:%d\n", __func__, reverb->room_level); if (command_config_state == CONFIG_SET) { - *updt_params++ = AUDPROC_MODULE_ID_REVERB; + params_length += COMMAND_PAYLOAD_SZ + + REVERB_ROOM_LEVEL_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "REVERB_ROOM_LEVEL", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_REVERB; *updt_params++ = AUDPROC_PARAM_ID_REVERB_ROOM_LEVEL; - *updt_params++ = REVERB_ROOM_LEVEL_PARAM_SZ; - *updt_params++ = reverb->room_level; - params_length += COMMAND_PAYLOAD_SZ + + *updt_params++ = REVERB_ROOM_LEVEL_PARAM_SZ; + *updt_params++ = + reverb->room_level; } break; case REVERB_ROOM_HF_LEVEL: @@ -376,17 +496,26 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, rc = -EINVAL; goto invalid_config; } - reverb->room_hf_level = *values++; + reverb->room_hf_level = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_ROOM_HF_LEVEL val%d\n", __func__, reverb->room_hf_level); if (command_config_state == CONFIG_SET) { - *updt_params++ = AUDPROC_MODULE_ID_REVERB; + params_length += COMMAND_PAYLOAD_SZ + + REVERB_ROOM_HF_LEVEL_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "REVERB_ROOM_HF_LEVEL", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_REVERB; *updt_params++ = AUDPROC_PARAM_ID_REVERB_ROOM_HF_LEVEL; - *updt_params++ = REVERB_ROOM_HF_LEVEL_PARAM_SZ; - *updt_params++ = reverb->room_hf_level; - params_length += COMMAND_PAYLOAD_SZ + + *updt_params++ = REVERB_ROOM_HF_LEVEL_PARAM_SZ; + *updt_params++ = + reverb->room_hf_level; } break; case REVERB_DECAY_TIME: @@ -395,17 +524,26 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, rc = -EINVAL; goto invalid_config; } - reverb->decay_time = *values++; + reverb->decay_time = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_DECAY_TIME val:%d\n", __func__, reverb->decay_time); if (command_config_state == CONFIG_SET) { - *updt_params++ = AUDPROC_MODULE_ID_REVERB; + params_length += COMMAND_PAYLOAD_SZ + + REVERB_DECAY_TIME_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "REVERB_DECAY_TIME", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_REVERB; *updt_params++ = AUDPROC_PARAM_ID_REVERB_DECAY_TIME; - *updt_params++ = REVERB_DECAY_TIME_PARAM_SZ; - *updt_params++ = reverb->decay_time; - params_length += COMMAND_PAYLOAD_SZ + + *updt_params++ = REVERB_DECAY_TIME_PARAM_SZ; + *updt_params++ = + reverb->decay_time; } break; case REVERB_DECAY_HF_RATIO: @@ -414,17 +552,26 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, rc = -EINVAL; goto invalid_config; } - reverb->decay_hf_ratio = *values++; + reverb->decay_hf_ratio = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_DECAY_HF_RATIO val%d\n", __func__, reverb->decay_hf_ratio); if (command_config_state == CONFIG_SET) { - *updt_params++ = AUDPROC_MODULE_ID_REVERB; + params_length += COMMAND_PAYLOAD_SZ + + REVERB_DECAY_HF_RATIO_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "REVERB_DECAY_HF_RATIO", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_REVERB; *updt_params++ = AUDPROC_PARAM_ID_REVERB_DECAY_HF_RATIO; - *updt_params++ = REVERB_DECAY_HF_RATIO_PARAM_SZ; - *updt_params++ = reverb->decay_hf_ratio; - params_length += COMMAND_PAYLOAD_SZ + + *updt_params++ = REVERB_DECAY_HF_RATIO_PARAM_SZ; + *updt_params++ = + reverb->decay_hf_ratio; } break; case REVERB_REFLECTIONS_LEVEL: @@ -433,18 +580,26 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, rc = -EINVAL; goto invalid_config; } - reverb->reflections_level = *values++; + reverb->reflections_level = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_REFLECTIONS_LEVEL val:%d\n", __func__, reverb->reflections_level); if (command_config_state == CONFIG_SET) { - *updt_params++ = AUDPROC_MODULE_ID_REVERB; - *updt_params++ = - AUDPROC_PARAM_ID_REVERB_REFLECTIONS_LEVEL; - *updt_params++ = - REVERB_REFLECTIONS_LEVEL_PARAM_SZ; - *updt_params++ = reverb->reflections_level; params_length += COMMAND_PAYLOAD_SZ + REVERB_REFLECTIONS_LEVEL_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "REVERB_REFLECTIONS_LEVEL", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_REVERB; + *updt_params++ = + AUDPROC_PARAM_ID_REVERB_REFLECTIONS_LEVEL; + *updt_params++ = + REVERB_REFLECTIONS_LEVEL_PARAM_SZ; + *updt_params++ = + reverb->reflections_level; } break; case REVERB_REFLECTIONS_DELAY: @@ -453,18 +608,26 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, rc = -EINVAL; goto invalid_config; } - reverb->reflections_delay = *values++; + reverb->reflections_delay = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_REFLECTIONS_DELAY val:%d\n", __func__, reverb->reflections_delay); if (command_config_state == CONFIG_SET) { - *updt_params++ = AUDPROC_MODULE_ID_REVERB; - *updt_params++ = - AUDPROC_PARAM_ID_REVERB_REFLECTIONS_DELAY; - *updt_params++ = - REVERB_REFLECTIONS_DELAY_PARAM_SZ; - *updt_params++ = reverb->reflections_delay; params_length += COMMAND_PAYLOAD_SZ + REVERB_REFLECTIONS_DELAY_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "REVERB_REFLECTIONS_DELAY", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_REVERB; + *updt_params++ = + AUDPROC_PARAM_ID_REVERB_REFLECTIONS_DELAY; + *updt_params++ = + REVERB_REFLECTIONS_DELAY_PARAM_SZ; + *updt_params++ = + reverb->reflections_delay; } break; case REVERB_LEVEL: @@ -473,16 +636,26 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, rc = -EINVAL; goto invalid_config; } - reverb->level = *values++; + reverb->level = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_LEVEL val:%d\n", __func__, reverb->level); if (command_config_state == CONFIG_SET) { - *updt_params++ = AUDPROC_MODULE_ID_REVERB; - *updt_params++ = AUDPROC_PARAM_ID_REVERB_LEVEL; - *updt_params++ = REVERB_LEVEL_PARAM_SZ; - *updt_params++ = reverb->level; params_length += COMMAND_PAYLOAD_SZ + REVERB_LEVEL_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "REVERB_LEVEL", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_REVERB; + *updt_params++ = + AUDPROC_PARAM_ID_REVERB_LEVEL; + *updt_params++ = + REVERB_LEVEL_PARAM_SZ; + *updt_params++ = + reverb->level; } break; case REVERB_DELAY: @@ -491,16 +664,26 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, rc = -EINVAL; goto invalid_config; } - reverb->delay = *values++; + reverb->delay = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s:REVERB_DELAY val:%d\n", __func__, reverb->delay); if (command_config_state == CONFIG_SET) { - *updt_params++ = AUDPROC_MODULE_ID_REVERB; - *updt_params++ = AUDPROC_PARAM_ID_REVERB_DELAY; - *updt_params++ = REVERB_DELAY_PARAM_SZ; - *updt_params++ = reverb->delay; params_length += COMMAND_PAYLOAD_SZ + REVERB_DELAY_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "REVERB_DELAY", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_REVERB; + *updt_params++ = + AUDPROC_PARAM_ID_REVERB_DELAY; + *updt_params++ = + REVERB_DELAY_PARAM_SZ; + *updt_params++ = + reverb->delay; } break; case REVERB_DIFFUSION: @@ -509,17 +692,26 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, rc = -EINVAL; goto invalid_config; } - reverb->diffusion = *values++; + reverb->diffusion = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_DIFFUSION val:%d\n", __func__, reverb->diffusion); if (command_config_state == CONFIG_SET) { - *updt_params++ = AUDPROC_MODULE_ID_REVERB; + params_length += COMMAND_PAYLOAD_SZ + + REVERB_DIFFUSION_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "REVERB_DIFFUSION", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_REVERB; *updt_params++ = AUDPROC_PARAM_ID_REVERB_DIFFUSION; - *updt_params++ = REVERB_DIFFUSION_PARAM_SZ; - *updt_params++ = reverb->diffusion; - params_length += COMMAND_PAYLOAD_SZ + + *updt_params++ = REVERB_DIFFUSION_PARAM_SZ; + *updt_params++ = + reverb->diffusion; } break; case REVERB_DENSITY: @@ -528,17 +720,26 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, rc = -EINVAL; goto invalid_config; } - reverb->density = *values++; + reverb->density = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_DENSITY val:%d\n", __func__, reverb->density); if (command_config_state == CONFIG_SET) { - *updt_params++ = AUDPROC_MODULE_ID_REVERB; + params_length += COMMAND_PAYLOAD_SZ + + REVERB_DENSITY_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "REVERB_DENSITY", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_REVERB; *updt_params++ = AUDPROC_PARAM_ID_REVERB_DENSITY; - *updt_params++ = REVERB_DENSITY_PARAM_SZ; - *updt_params++ = reverb->density; - params_length += COMMAND_PAYLOAD_SZ + + *updt_params++ = REVERB_DENSITY_PARAM_SZ; + *updt_params++ = + reverb->density; } break; default: @@ -546,7 +747,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, break; } } - if (params_length && !msm_dts_eagle_is_hpx_on()) + if (params_length && !msm_dts_eagle_is_hpx_on() && (rc == 0)) q6asm_send_audio_effects_params(ac, params, params_length); else @@ -560,15 +761,16 @@ int msm_audio_effects_bass_boost_handler(struct audio_client *ac, struct bass_boost_params *bass_boost, long *values) { - int devices = *values++; - int num_commands = *values++; - char *params; + long *param_max_offset = values + MAX_PP_PARAMS_SZ - 1; + char *params = NULL; + int rc = 0; + int devices = GET_NEXT(values, param_max_offset, rc); + int num_commands = GET_NEXT(values, param_max_offset, rc); int *updt_params, i, prev_enable_flag; uint32_t params_length = (MAX_INBAND_PARAM_SZ); - int rc = 0; pr_debug("%s\n", __func__); - if (!ac) { + if (!ac || (devices == -EINVAL) || (num_commands == -EINVAL)) { pr_err("%s: cannot set audio effects\n", __func__); return -EINVAL; } @@ -581,10 +783,14 @@ int msm_audio_effects_bass_boost_handler(struct audio_client *ac, updt_params = (int *)params; params_length = 0; for (i = 0; i < num_commands; i++) { - uint32_t command_id = *values++; - uint32_t command_config_state = *values++; - uint32_t index_offset = *values++; - uint32_t length = *values++; + uint32_t command_id = + GET_NEXT(values, param_max_offset, rc); + uint32_t command_config_state = + GET_NEXT(values, param_max_offset, rc); + uint32_t index_offset = + GET_NEXT(values, param_max_offset, rc); + uint32_t length = + GET_NEXT(values, param_max_offset, rc); switch (command_id) { case BASS_BOOST_ENABLE: if (length != 1 || index_offset != 0) { @@ -593,18 +799,27 @@ int msm_audio_effects_bass_boost_handler(struct audio_client *ac, goto invalid_config; } prev_enable_flag = bass_boost->enable_flag; - bass_boost->enable_flag = *values++; + bass_boost->enable_flag = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s: BASS_BOOST_ENABLE prev:%d new:%d\n", __func__, prev_enable_flag, bass_boost->enable_flag); if (prev_enable_flag != bass_boost->enable_flag) { - *updt_params++ = AUDPROC_MODULE_ID_BASS_BOOST; + params_length += COMMAND_PAYLOAD_SZ + + BASS_BOOST_ENABLE_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "BASS_BOOST_ENABLE", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_BASS_BOOST; *updt_params++ = AUDPROC_PARAM_ID_BASS_BOOST_ENABLE; - *updt_params++ = BASS_BOOST_ENABLE_PARAM_SZ; - *updt_params++ = bass_boost->enable_flag; - params_length += COMMAND_PAYLOAD_SZ + + *updt_params++ = BASS_BOOST_ENABLE_PARAM_SZ; + *updt_params++ = + bass_boost->enable_flag; } break; case BASS_BOOST_MODE: @@ -613,17 +828,26 @@ int msm_audio_effects_bass_boost_handler(struct audio_client *ac, rc = -EINVAL; goto invalid_config; } - bass_boost->mode = *values++; + bass_boost->mode = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s: BASS_BOOST_MODE val:%d\n", __func__, bass_boost->mode); if (command_config_state == CONFIG_SET) { - *updt_params++ = AUDPROC_MODULE_ID_BASS_BOOST; + params_length += COMMAND_PAYLOAD_SZ + + BASS_BOOST_MODE_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "BASS_BOOST_MODE", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_BASS_BOOST; *updt_params++ = AUDPROC_PARAM_ID_BASS_BOOST_MODE; - *updt_params++ = BASS_BOOST_MODE_PARAM_SZ; - *updt_params++ = bass_boost->mode; - params_length += COMMAND_PAYLOAD_SZ + + *updt_params++ = BASS_BOOST_MODE_PARAM_SZ; + *updt_params++ = + bass_boost->mode; } break; case BASS_BOOST_STRENGTH: @@ -632,17 +856,26 @@ int msm_audio_effects_bass_boost_handler(struct audio_client *ac, rc = -EINVAL; goto invalid_config; } - bass_boost->strength = *values++; - pr_debug("%s: BASS_BOOST_STRENGTHi val:%d\n", + bass_boost->strength = + GET_NEXT(values, param_max_offset, rc); + pr_debug("%s: BASS_BOOST_STRENGTH val:%d\n", __func__, bass_boost->strength); if (command_config_state == CONFIG_SET) { - *updt_params++ = AUDPROC_MODULE_ID_BASS_BOOST; + params_length += COMMAND_PAYLOAD_SZ + + BASS_BOOST_STRENGTH_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "BASS_BOOST_STRENGTH", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_BASS_BOOST; *updt_params++ = AUDPROC_PARAM_ID_BASS_BOOST_STRENGTH; - *updt_params++ = BASS_BOOST_STRENGTH_PARAM_SZ; - *updt_params++ = bass_boost->strength; - params_length += COMMAND_PAYLOAD_SZ + + *updt_params++ = BASS_BOOST_STRENGTH_PARAM_SZ; + *updt_params++ = + bass_boost->strength; } break; default: @@ -650,7 +883,7 @@ int msm_audio_effects_bass_boost_handler(struct audio_client *ac, break; } } - if (params_length && !msm_dts_eagle_is_hpx_on()) + if (params_length && !msm_dts_eagle_is_hpx_on() && (rc == 0)) q6asm_send_audio_effects_params(ac, params, params_length); else @@ -664,15 +897,16 @@ int msm_audio_effects_pbe_handler(struct audio_client *ac, struct pbe_params *pbe, long *values) { - int devices = *values++; - int num_commands = *values++; - char *params; + long *param_max_offset = values + MAX_PP_PARAMS_SZ - 1; + char *params = NULL; + int rc = 0; + int devices = GET_NEXT(values, param_max_offset, rc); + int num_commands = GET_NEXT(values, param_max_offset, rc); int *updt_params, i, j, prev_enable_flag; uint32_t params_length = (MAX_INBAND_PARAM_SZ); - int rc = 0; pr_debug("%s\n", __func__); - if (!ac) { + if (!ac || (devices == -EINVAL) || (num_commands == -EINVAL)) { pr_err("%s: cannot set audio effects\n", __func__); return -EINVAL; } @@ -685,10 +919,14 @@ int msm_audio_effects_pbe_handler(struct audio_client *ac, updt_params = (int *)params; params_length = 0; for (i = 0; i < num_commands; i++) { - uint32_t command_id = *values++; - uint32_t command_config_state = *values++; - uint32_t index_offset = *values++; - uint32_t length = *values++; + uint32_t command_id = + GET_NEXT(values, param_max_offset, rc); + uint32_t command_config_state = + GET_NEXT(values, param_max_offset, rc); + uint32_t index_offset = + GET_NEXT(values, param_max_offset, rc); + uint32_t length = + GET_NEXT(values, param_max_offset, rc); switch (command_id) { case PBE_ENABLE: pr_debug("%s: PBE_ENABLE\n", __func__); @@ -698,15 +936,24 @@ int msm_audio_effects_pbe_handler(struct audio_client *ac, goto invalid_config; } prev_enable_flag = pbe->enable_flag; - pbe->enable_flag = *values++; + pbe->enable_flag = + GET_NEXT(values, param_max_offset, rc); if (prev_enable_flag != pbe->enable_flag) { - *updt_params++ = AUDPROC_MODULE_ID_PBE; + params_length += COMMAND_PAYLOAD_SZ + + PBE_ENABLE_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "PBE_ENABLE", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_PBE; *updt_params++ = AUDPROC_PARAM_ID_PBE_ENABLE; - *updt_params++ = PBE_ENABLE_PARAM_SZ; - *updt_params++ = pbe->enable_flag; - params_length += COMMAND_PAYLOAD_SZ + + *updt_params++ = PBE_ENABLE_PARAM_SZ; + *updt_params++ = + pbe->enable_flag; } break; case PBE_CONFIG: @@ -719,15 +966,26 @@ int msm_audio_effects_pbe_handler(struct audio_client *ac, goto invalid_config; } if (command_config_state == CONFIG_SET) { - *updt_params++ = AUDPROC_MODULE_ID_PBE; + params_length += COMMAND_PAYLOAD_SZ + length; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "PBE_PARAM", rc); + if (rc != 0) + break; + *updt_params++ = + AUDPROC_MODULE_ID_PBE; *updt_params++ = AUDPROC_PARAM_ID_PBE_PARAM_CONFIG; - *updt_params++ = length; + *updt_params++ = + length; for (j = 0; j < length; ) { j += sizeof(*updt_params); - *updt_params++ = *values++; + *updt_params++ = + GET_NEXT( + values, + param_max_offset, + rc); } - params_length += COMMAND_PAYLOAD_SZ + length; } break; default: @@ -735,7 +993,7 @@ int msm_audio_effects_pbe_handler(struct audio_client *ac, break; } } - if (params_length) + if (params_length && (rc == 0)) q6asm_send_audio_effects_params(ac, params, params_length); invalid_config: @@ -747,15 +1005,16 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, struct eq_params *eq, long *values) { - int devices = *values++; - int num_commands = *values++; - char *params; + long *param_max_offset = values + MAX_PP_PARAMS_SZ - 1; + char *params = NULL; + int rc = 0; + int devices = GET_NEXT(values, param_max_offset, rc); + int num_commands = GET_NEXT(values, param_max_offset, rc); int *updt_params, i, prev_enable_flag; uint32_t params_length = (MAX_INBAND_PARAM_SZ); - int rc = 0; pr_debug("%s\n", __func__); - if (!ac) { + if (!ac || (devices == -EINVAL) || (num_commands == -EINVAL)) { pr_err("%s: cannot set audio effects\n", __func__); return -EINVAL; } @@ -768,11 +1027,16 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, updt_params = (int *)params; params_length = 0; for (i = 0; i < num_commands; i++) { - uint32_t command_id = *values++; - uint32_t command_config_state = *values++; - uint32_t index_offset = *values++; - uint32_t length = *values++; - int idx, j; + uint32_t command_id = + GET_NEXT(values, param_max_offset, rc); + uint32_t command_config_state = + GET_NEXT(values, param_max_offset, rc); + uint32_t index_offset = + GET_NEXT(values, param_max_offset, rc); + uint32_t length = + GET_NEXT(values, param_max_offset, rc); + uint32_t idx; + int j; switch (command_id) { case EQ_ENABLE: if (length != 1 || index_offset != 0) { @@ -781,17 +1045,26 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, goto invalid_config; } prev_enable_flag = eq->enable_flag; - eq->enable_flag = *values++; + eq->enable_flag = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s: EQ_ENABLE prev:%d new:%d\n", __func__, prev_enable_flag, eq->enable_flag); if (prev_enable_flag != eq->enable_flag) { + params_length += COMMAND_PAYLOAD_SZ + + EQ_ENABLE_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "EQ_ENABLE", rc); + if (rc != 0) + break; *updt_params++ = AUDPROC_MODULE_ID_POPLESS_EQUALIZER; - *updt_params++ = AUDPROC_PARAM_ID_EQ_ENABLE; - *updt_params++ = EQ_ENABLE_PARAM_SZ; - *updt_params++ = eq->enable_flag; - params_length += COMMAND_PAYLOAD_SZ + + *updt_params++ = + AUDPROC_PARAM_ID_EQ_ENABLE; + *updt_params++ = EQ_ENABLE_PARAM_SZ; + *updt_params++ = + eq->enable_flag; } break; case EQ_CONFIG: @@ -805,9 +1078,12 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, eq->config.eq_pregain, eq->config.preset_id); for (idx = 0; idx < MAX_EQ_BANDS; idx++) eq->per_band_cfg[idx].band_idx = -1; - eq->config.eq_pregain = *values++; - eq->config.preset_id = *values++; - eq->config.num_bands = *values++; + eq->config.eq_pregain = + GET_NEXT(values, param_max_offset, rc); + eq->config.preset_id = + GET_NEXT(values, param_max_offset, rc); + eq->config.num_bands = + GET_NEXT(values, param_max_offset, rc); if (eq->config.num_bands > MAX_EQ_BANDS) { pr_err("EQ_CONFIG:invalid num of bands\n"); rc = -EINVAL; @@ -822,48 +1098,59 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, goto invalid_config; } for (j = 0; j < eq->config.num_bands; j++) { - idx = *values++; + idx = GET_NEXT(values, param_max_offset, rc); if (idx >= MAX_EQ_BANDS) { pr_err("EQ_CONFIG:invalid band index\n"); rc = -EINVAL; goto invalid_config; } eq->per_band_cfg[idx].band_idx = idx; - eq->per_band_cfg[idx].filter_type = *values++; + eq->per_band_cfg[idx].filter_type = + GET_NEXT(values, param_max_offset, rc); eq->per_band_cfg[idx].freq_millihertz = - *values++; + GET_NEXT(values, param_max_offset, rc); eq->per_band_cfg[idx].gain_millibels = - *values++; + GET_NEXT(values, param_max_offset, rc); eq->per_band_cfg[idx].quality_factor = - *values++; + GET_NEXT(values, param_max_offset, rc); } if (command_config_state == CONFIG_SET) { int config_param_length = EQ_CONFIG_PARAM_SZ + (EQ_CONFIG_PER_BAND_PARAM_SZ* eq->config.num_bands); + params_length += COMMAND_PAYLOAD_SZ + + config_param_length; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "EQ_CONFIG", rc); + if (rc != 0) + break; *updt_params++ = AUDPROC_MODULE_ID_POPLESS_EQUALIZER; - *updt_params++ = AUDPROC_PARAM_ID_EQ_CONFIG; - *updt_params++ = config_param_length; - *updt_params++ = eq->config.eq_pregain; - *updt_params++ = eq->config.preset_id; - *updt_params++ = eq->config.num_bands; + *updt_params++ = + AUDPROC_PARAM_ID_EQ_CONFIG; + *updt_params++ = + config_param_length; + *updt_params++ = + eq->config.eq_pregain; + *updt_params++ = + eq->config.preset_id; + *updt_params++ = + eq->config.num_bands; for (idx = 0; idx < MAX_EQ_BANDS; idx++) { if (eq->per_band_cfg[idx].band_idx < 0) continue; *updt_params++ = - eq->per_band_cfg[idx].filter_type; + eq->per_band_cfg[idx].filter_type; *updt_params++ = - eq->per_band_cfg[idx].freq_millihertz; + eq->per_band_cfg[idx].freq_millihertz; *updt_params++ = - eq->per_band_cfg[idx].gain_millibels; + eq->per_band_cfg[idx].gain_millibels; *updt_params++ = - eq->per_band_cfg[idx].quality_factor; + eq->per_band_cfg[idx].quality_factor; *updt_params++ = - eq->per_band_cfg[idx].band_idx; + eq->per_band_cfg[idx].band_idx; } - params_length += COMMAND_PAYLOAD_SZ + - config_param_length; } break; case EQ_BAND_INDEX: @@ -872,7 +1159,7 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, rc = -EINVAL; goto invalid_config; } - idx = *values++; + idx = GET_NEXT(values, param_max_offset, rc); if (idx > MAX_EQ_BANDS) { pr_err("EQ_BAND_INDEX:invalid band index\n"); rc = -EINVAL; @@ -882,14 +1169,21 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, pr_debug("%s: EQ_BAND_INDEX val:%d\n", __func__, eq->band_index); if (command_config_state == CONFIG_SET) { + params_length += COMMAND_PAYLOAD_SZ + + EQ_BAND_INDEX_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "EQ_BAND_INDEX", rc); + if (rc != 0) + break; *updt_params++ = AUDPROC_MODULE_ID_POPLESS_EQUALIZER; *updt_params++ = AUDPROC_PARAM_ID_EQ_BAND_INDEX; - *updt_params++ = EQ_BAND_INDEX_PARAM_SZ; - *updt_params++ = eq->band_index; - params_length += COMMAND_PAYLOAD_SZ + + *updt_params++ = EQ_BAND_INDEX_PARAM_SZ; + *updt_params++ = + eq->band_index; } break; case EQ_SINGLE_BAND_FREQ: @@ -902,18 +1196,26 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, pr_err("EQ_SINGLE_BAND_FREQ:invalid index\n"); break; } - eq->freq_millihertz = *values++; + eq->freq_millihertz = + GET_NEXT(values, param_max_offset, rc); pr_debug("%s: EQ_SINGLE_BAND_FREQ idx:%d, val:%d\n", __func__, eq->band_index, eq->freq_millihertz); if (command_config_state == CONFIG_SET) { + params_length += COMMAND_PAYLOAD_SZ + + EQ_SINGLE_BAND_FREQ_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "EQ_SINGLE_BAND_FREQ", rc); + if (rc != 0) + break; *updt_params++ = AUDPROC_MODULE_ID_POPLESS_EQUALIZER; *updt_params++ = AUDPROC_PARAM_ID_EQ_SINGLE_BAND_FREQ; - *updt_params++ = EQ_SINGLE_BAND_FREQ_PARAM_SZ; - *updt_params++ = eq->freq_millihertz; - params_length += COMMAND_PAYLOAD_SZ + + *updt_params++ = EQ_SINGLE_BAND_FREQ_PARAM_SZ; + *updt_params++ = + eq->freq_millihertz; } break; default: @@ -921,7 +1223,7 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, break; } } - if (params_length && !msm_dts_eagle_is_hpx_on()) + if (params_length && !msm_dts_eagle_is_hpx_on() && (rc == 0)) q6asm_send_audio_effects_params(ac, params, params_length); else @@ -938,9 +1240,10 @@ static int __msm_audio_effects_volume_handler(struct audio_client *ac, { int devices; int num_commands; - char *params; + char *params = NULL; int *updt_params, i; uint32_t params_length = (MAX_INBAND_PARAM_SZ); + long *param_max_offset; int rc = 0; pr_debug("%s: instance: %d\n", __func__, instance); @@ -949,9 +1252,11 @@ static int __msm_audio_effects_volume_handler(struct audio_client *ac, __func__); return -EINVAL; } - if (!ac) { - pr_err("%s: cannot set audio effects as audio client is NULL\n", - __func__); + param_max_offset = values + MAX_PP_PARAMS_SZ - 1; + devices = GET_NEXT(values, param_max_offset, rc); + num_commands = GET_NEXT(values, param_max_offset, rc); + if (!ac || (devices == -EINVAL) || (num_commands == -EINVAL)) { + pr_err("%s: cannot set audio effects\n", __func__); return -EINVAL; } params = kzalloc(params_length, GFP_KERNEL); @@ -959,88 +1264,114 @@ static int __msm_audio_effects_volume_handler(struct audio_client *ac, pr_err("%s, params memory alloc failed\n", __func__); return -ENOMEM; } - devices = *values++; - num_commands = *values++; updt_params = (int *)params; params_length = 0; for (i = 0; i < num_commands; i++) { - uint32_t command_id = *values++; - uint32_t command_config_state = *values++; - uint32_t index_offset = *values++; - uint32_t length = *values++; + uint32_t command_id = + GET_NEXT(values, param_max_offset, rc); + uint32_t command_config_state = + GET_NEXT(values, param_max_offset, rc); + uint32_t index_offset = + GET_NEXT(values, param_max_offset, rc); + uint32_t length = + GET_NEXT(values, param_max_offset, rc); switch (command_id) { case SOFT_VOLUME_GAIN_2CH: case SOFT_VOLUME2_GAIN_2CH: if (length != 2 || index_offset != 0) { - pr_err("VOLUME_GAIN_2CH/VOLUME2_GAIN_2CH:invalid params\n"); + pr_err("VOLUME_GAIN_2CH: invalid params\n"); rc = -EINVAL; goto invalid_config; } - vol->left_gain = *values++; - vol->right_gain = *values++; + vol->left_gain = GET_NEXT(values, param_max_offset, rc); + vol->right_gain = + GET_NEXT(values, param_max_offset, rc); vol->master_gain = 0x2000; if (command_config_state == CONFIG_SET) { + params_length += COMMAND_PAYLOAD_SZ + + SOFT_VOLUME_GAIN_2CH_PARAM_SZ; + params_length += COMMAND_PAYLOAD_SZ + + SOFT_VOLUME_GAIN_MASTER_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "VOLUME/VOLUME2_GAIN_2CH", + rc); + if (rc != 0) + break; if (instance == SOFT_VOLUME_INSTANCE_2) *updt_params++ = - ASM_MODULE_ID_VOL_CTRL2; + ASM_MODULE_ID_VOL_CTRL2; else - *updt_params++ = ASM_MODULE_ID_VOL_CTRL; + *updt_params++ = + ASM_MODULE_ID_VOL_CTRL; *updt_params++ = ASM_PARAM_ID_VOL_CTRL_LR_CHANNEL_GAIN; - *updt_params++ = SOFT_VOLUME_GAIN_2CH_PARAM_SZ; - *updt_params++ = (vol->left_gain << 16) | - vol->right_gain; - params_length += COMMAND_PAYLOAD_SZ + - SOFT_VOLUME_GAIN_2CH_PARAM_SZ; + *updt_params++ = + SOFT_VOLUME_GAIN_2CH_PARAM_SZ; + *updt_params++ = + (vol->left_gain << 16) | + vol->right_gain; if (instance == SOFT_VOLUME_INSTANCE_2) *updt_params++ = - ASM_MODULE_ID_VOL_CTRL2; + ASM_MODULE_ID_VOL_CTRL2; else - *updt_params++ = ASM_MODULE_ID_VOL_CTRL; + *updt_params++ = + ASM_MODULE_ID_VOL_CTRL; *updt_params++ = ASM_PARAM_ID_VOL_CTRL_MASTER_GAIN; *updt_params++ = SOFT_VOLUME_GAIN_MASTER_PARAM_SZ; - *updt_params++ = vol->master_gain; - params_length += COMMAND_PAYLOAD_SZ + - SOFT_VOLUME_GAIN_MASTER_PARAM_SZ; + *updt_params++ = + vol->master_gain; } break; case SOFT_VOLUME_GAIN_MASTER: case SOFT_VOLUME2_GAIN_MASTER: if (length != 1 || index_offset != 0) { - pr_err("VOLUME_GAIN_MASTER/VOLUME2_GAIN_MASTER:invalid params\n"); + pr_err("VOLUME_GAIN_MASTER: invalid params\n"); rc = -EINVAL; goto invalid_config; } vol->left_gain = 0x2000; vol->right_gain = 0x2000; - vol->master_gain = *values++; + vol->master_gain = + GET_NEXT(values, param_max_offset, rc); if (command_config_state == CONFIG_SET) { + params_length += COMMAND_PAYLOAD_SZ + + SOFT_VOLUME_GAIN_2CH_PARAM_SZ; + params_length += COMMAND_PAYLOAD_SZ + + SOFT_VOLUME_GAIN_MASTER_PARAM_SZ; + CHECK_PARAM_LEN(params_length, + MAX_INBAND_PARAM_SZ, + "VOLUME/VOLUME2_GAIN_MASTER", + rc); + if (rc != 0) + break; if (instance == SOFT_VOLUME_INSTANCE_2) *updt_params++ = - ASM_MODULE_ID_VOL_CTRL2; + ASM_MODULE_ID_VOL_CTRL2; else - *updt_params++ = ASM_MODULE_ID_VOL_CTRL; + *updt_params++ = + ASM_MODULE_ID_VOL_CTRL; *updt_params++ = ASM_PARAM_ID_VOL_CTRL_LR_CHANNEL_GAIN; - *updt_params++ = SOFT_VOLUME_GAIN_2CH_PARAM_SZ; - *updt_params++ = (vol->left_gain << 16) | - vol->right_gain; - params_length += COMMAND_PAYLOAD_SZ + - SOFT_VOLUME_GAIN_2CH_PARAM_SZ; + *updt_params++ = + SOFT_VOLUME_GAIN_2CH_PARAM_SZ; + *updt_params++ = + (vol->left_gain << 16) | + vol->right_gain; if (instance == SOFT_VOLUME_INSTANCE_2) *updt_params++ = - ASM_MODULE_ID_VOL_CTRL2; + ASM_MODULE_ID_VOL_CTRL2; else - *updt_params++ = ASM_MODULE_ID_VOL_CTRL; + *updt_params++ = + ASM_MODULE_ID_VOL_CTRL; *updt_params++ = ASM_PARAM_ID_VOL_CTRL_MASTER_GAIN; *updt_params++ = SOFT_VOLUME_GAIN_MASTER_PARAM_SZ; - *updt_params++ = vol->master_gain; - params_length += COMMAND_PAYLOAD_SZ + - SOFT_VOLUME_GAIN_MASTER_PARAM_SZ; + *updt_params++ = + vol->master_gain; } break; default: @@ -1049,7 +1380,7 @@ static int __msm_audio_effects_volume_handler(struct audio_client *ac, break; } } - if (params_length) + if (params_length && (rc == 0)) q6asm_send_audio_effects_params(ac, params, params_length); invalid_config: diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c index f814434..b4bd43d 100644 --- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c @@ -2839,7 +2839,7 @@ static int msm_compr_audio_effects_config_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 128; + uinfo->count = MAX_PP_PARAMS_SZ; uinfo->value.integer.min = 0; uinfo->value.integer.max = 0xFFFFFFFF; return 0; -- cgit v1.1