summaryrefslogtreecommitdiff
path: root/sound/soc/intel/avs
diff options
context:
space:
mode:
authorCezary Rojewski <cezary.rojewski@intel.com>2026-09-02 10:18:13 +0200
committerMark Brown <broonie@kernel.org>2026-09-03 22:51:40 +0100
commit681e91035dc794896a904852040837190e5041f5 (patch)
tree33802011adff2919088513b5e266d2b02439c4a0 /sound/soc/intel/avs
parentd4fa6f94b91137e329ea3f5b360e140b227bb696 (diff)
downloadlinux-next-681e91035dc794896a904852040837190e5041f5.tar.gz
linux-next-681e91035dc794896a904852040837190e5041f5.zip
ASoC: Intel: avs: Refactor and fix init_config access
Existing code accesses enties found in ->init_configs array through indexes that are part of ->config_ids array. Those two are limited by: ->num_init_configs and ->num_config_ids respectively. Using ID larger or equal to ->num_init_configs leads to out-of-bounds access: avs_path_module_send_init_configs() loop: (...) &acomp->tplg->init_configs[ids[i]] ^ out-of-bounds candidate Rather than adding another if-statement, refactor the code. There is no need to store the IDs, have a list of pointers to actual config-entries instead. As the verification of ->init_config entries does not differ from verification of other types that are part of the topology.c file, simply reuse the code. Fixes: 8a49ef789b1b ("ASoC: Intel: avs: Send initial config to module if present") Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com> Link: https://patch.msgid.link/20260902081814.1590883-10-cezary.rojewski@intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/intel/avs')
-rw-r--r--sound/soc/intel/avs/path.c11
-rw-r--r--sound/soc/intel/avs/topology.c47
-rw-r--r--sound/soc/intel/avs/topology.h4
3 files changed, 32 insertions, 30 deletions
diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c
index 213d6ecdd7cc..a8a2b3484338 100644
--- a/sound/soc/intel/avs/path.c
+++ b/sound/soc/intel/avs/path.c
@@ -836,15 +836,10 @@ static int avs_path_module_type_create(struct avs_dev *adev, struct avs_path_mod
static int avs_path_module_send_init_configs(struct avs_dev *adev, struct avs_path_module *mod)
{
- struct avs_soc_component *acomp;
-
- acomp = to_avs_soc_component(mod->template->owner->owner->owner->owner->comp);
-
- u32 num_ids = mod->template->num_config_ids;
- u32 *ids = mod->template->config_ids;
+ struct avs_tplg_module *template = mod->template;
- for (int i = 0; i < num_ids; i++) {
- struct avs_tplg_init_config *config = &acomp->tplg->init_configs[ids[i]];
+ for (int i = 0; i < template->num_init_configs; i++) {
+ struct avs_tplg_init_config *config = template->init_configs[i];
size_t len = config->length;
void *data = config->data;
u32 param = config->param;
diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c
index d5e641c73faf..5d70be63a4a7 100644
--- a/sound/soc/intel/avs/topology.c
+++ b/sound/soc/intel/avs/topology.c
@@ -350,6 +350,7 @@ AVS_DEFINE_PTR_PARSER(modcfg_base, struct avs_tplg_modcfg_base, modcfgs_base);
AVS_DEFINE_PTR_PARSER(modcfg_ext, struct avs_tplg_modcfg_ext, modcfgs_ext);
AVS_DEFINE_PTR_PARSER(pplcfg, struct avs_tplg_pplcfg, pplcfgs);
AVS_DEFINE_PTR_PARSER(binding, struct avs_tplg_binding, bindings);
+AVS_DEFINE_PTR_PARSER(init_config, struct avs_tplg_init_config, init_configs);
AVS_DEFINE_PTR_PARSER(nhlt_config, struct avs_tplg_nhlt_config, nhlt_configs);
static int
@@ -1198,7 +1199,7 @@ static const struct avs_tplg_token_parser module_parsers[] = {
{
.token = AVS_TKN_MOD_INIT_CONFIG_NUM_IDS_U32,
.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
- .offset = offsetof(struct avs_tplg_module, num_config_ids),
+ .offset = offsetof(struct avs_tplg_module, num_init_configs),
.parse = avs_parse_byte_token,
},
{
@@ -1214,10 +1215,32 @@ static const struct avs_tplg_token_parser init_config_parsers[] = {
.token = AVS_TKN_MOD_INIT_CONFIG_ID_U32,
.type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
.offset = 0,
- .parse = avs_parse_word_token,
+ .parse = avs_parse_init_config_ptr,
},
};
+static int avs_tplg_module_init_configs(struct snd_soc_component *comp,
+ struct avs_tplg_module *module,
+ struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
+{
+ struct avs_tplg_init_config **cfgs;
+ int ret;
+
+ if (!module->num_init_configs)
+ return -EINVAL;
+
+ cfgs = devm_kcalloc(comp->card->dev, module->num_init_configs, sizeof(*cfgs), GFP_KERNEL);
+ if (!cfgs)
+ return -ENOMEM;
+
+ ret = parse_dictionary_entries(comp, tuples, block_size, cfgs, module->num_init_configs,
+ sizeof(*cfgs), AVS_TKN_MOD_INIT_CONFIG_ID_U32,
+ init_config_parsers, ARRAY_SIZE(init_config_parsers));
+ if (!ret)
+ module->init_configs = cfgs;
+ return ret;
+}
+
static struct avs_tplg_module *
avs_tplg_module_create(struct snd_soc_component *comp, struct avs_tplg_pipeline *owner,
struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
@@ -1244,27 +1267,11 @@ avs_tplg_module_create(struct snd_soc_component *comp, struct avs_tplg_pipeline
block_size -= esize;
/* Parse trailing config ids if any. */
if (block_size) {
- u32 num_config_ids = module->num_config_ids;
- u32 *config_ids;
-
- if (!num_config_ids)
- return ERR_PTR(-EINVAL);
-
- config_ids = devm_kcalloc(comp->card->dev, num_config_ids, sizeof(*config_ids),
- GFP_KERNEL);
- if (!config_ids)
- return ERR_PTR(-ENOMEM);
-
tuples = avs_tplg_vendor_array_at(tuples, esize);
- ret = parse_dictionary_entries(comp, tuples, block_size,
- config_ids, num_config_ids, sizeof(*config_ids),
- AVS_TKN_MOD_INIT_CONFIG_ID_U32,
- init_config_parsers,
- ARRAY_SIZE(init_config_parsers));
+
+ ret = avs_tplg_module_init_configs(comp, module, tuples, block_size);
if (ret)
return ERR_PTR(ret);
-
- module->config_ids = config_ids;
}
module->owner = owner;
diff --git a/sound/soc/intel/avs/topology.h b/sound/soc/intel/avs/topology.h
index b5799c994b88..189984ce7b51 100644
--- a/sound/soc/intel/avs/topology.h
+++ b/sound/soc/intel/avs/topology.h
@@ -221,8 +221,8 @@ struct avs_tplg_module {
u8 domain;
struct avs_tplg_modcfg_ext *cfg_ext;
u32 ctl_id;
- u32 num_config_ids;
- u32 *config_ids;
+ u32 num_init_configs;
+ struct avs_tplg_init_config **init_configs;
struct avs_tplg_nhlt_config *nhlt_config;
struct avs_tplg_pipeline *owner;