[PATCH 09/10] ASoC: Intel: avs: Refactor and fix init_config access
Cezary Rojewski <[email protected]>
| Newsgroups | gmane.linux.sound |
|---|---|
| Message-ID | <[email protected]> |
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 <[email protected]>
---
sound/soc/intel/avs/path.c | 10 +++-----
sound/soc/intel/avs/topology.c | 47 +++++++++++++++++++---------------
sound/soc/intel/avs/topology.h | 4 +--
3 files changed, 33 insertions(+), 28 deletions(-)
diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c
index 213d6ecdd7cc..2207996d2552 100644
--- a/sound/soc/intel/avs/path.c
+++ b/sound/soc/intel/avs/path.c
@@ -836,15 +836,13 @@ 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_tplg_module *template = mod->template;
struct avs_soc_component *acomp;
- acomp = to_avs_soc_component(mod->template->owner->owner->owner->owner->comp);
+ acomp = to_avs_soc_component(template->owner->owner->owner->owner->comp);
- u32 num_ids = mod->template->num_config_ids;
- u32 *ids = mod->template->config_ids;
-
- 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;
--
2.34.1