diff --git a/src/audio/module_adapter/module/cadence_ipc4.c b/src/audio/module_adapter/module/cadence_ipc4.c index 17069b97113a..107a6895b212 100644 --- a/src/audio/module_adapter/module/cadence_ipc4.c +++ b/src/audio/module_adapter/module/cadence_ipc4.c @@ -245,6 +245,16 @@ static int cadence_codec_init(struct processing_module *mod) if (codec->state == MODULE_DISABLED && ext_data->module_data_size > 0) { int size = ext_data->module_data_size; uint8_t *init_bytes; + uint32_t direction; + + /* the init payload holds the codec params followed by the + * direction word; validate the size up front before using it + */ + if (size < (int)(sizeof(struct snd_codec) + sizeof(uint32_t))) { + comp_err(dev, "setup config too small: %d", size); + ret = -EINVAL; + goto free_cd; + } setup_cfg = &cd->setup_cfg; @@ -265,9 +275,13 @@ static int cadence_codec_init(struct processing_module *mod) setup_cfg->avail = true; codec->cfg.avail = false; - /* direction follows the codec params in init data */ + /* direction follows the codec params; copy it out rather than + * dereferencing a possibly unaligned uint32_t pointer + */ init_bytes = (uint8_t *)ext_data->module_data; - cd->direction = *(uint32_t *)(init_bytes + sizeof(struct snd_codec)); + memcpy(&direction, init_bytes + sizeof(struct snd_codec), + sizeof(direction)); + cd->direction = direction; comp_info(dev, "codec direction set to %u", cd->direction); } diff --git a/src/audio/module_adapter/module/waves/waves.c b/src/audio/module_adapter/module/waves/waves.c index d328d9e5167f..aa800b32f992 100644 --- a/src/audio/module_adapter/module/waves/waves.c +++ b/src/audio/module_adapter/module/waves/waves.c @@ -612,6 +612,15 @@ static int waves_effect_apply_config(struct processing_module *mod) for (index = 0; index < cfg->size && (!ret); param_number++) { uint32_t param_data_size; + /* make sure a whole param header remains before reading + * param->size / param->id below + */ + if (index + header_size > cfg->size) { + comp_err(dev, "module_param header at index %u (header %u) exceeds cfg size %zu", + index, header_size, cfg->size); + return -EINVAL; + } + param = (struct module_param *)((char *)cfg->data + index); param_data_size = param->size - sizeof(param->size) - sizeof(param->id); diff --git a/src/audio/module_adapter/module_adapter_ipc3.c b/src/audio/module_adapter/module_adapter_ipc3.c index 74c8f02afa2f..e6098dec0799 100644 --- a/src/audio/module_adapter/module_adapter_ipc3.c +++ b/src/audio/module_adapter/module_adapter_ipc3.c @@ -184,21 +184,25 @@ static int module_adapter_get_set_params(struct comp_dev *dev, struct sof_ipc_ct const struct module_interface *const interface = mod->dev->drv->adapter_ops; enum module_cfg_fragment_position pos; uint32_t data_offset_size; - static uint32_t size; comp_dbg(dev, "num_of_elem %d, elem remain %d msg_index %u", cdata->num_elems, cdata->elems_remaining, cdata->msg_index); - /* set the fragment position, data offset and config data size */ + /* + * The total fragmented-transfer size is kept per instance in + * mod->runtime_params_size; a file-scope static would be shared across + * all module_adapter components and corrupted by interleaved transfers. + */ if (!cdata->msg_index) { - size = cdata->num_elems + cdata->elems_remaining; - data_offset_size = size; + mod->runtime_params_size = cdata->num_elems + cdata->elems_remaining; + data_offset_size = mod->runtime_params_size; if (cdata->elems_remaining) pos = MODULE_CFG_FRAGMENT_FIRST; else pos = MODULE_CFG_FRAGMENT_SINGLE; } else { - data_offset_size = size - (cdata->num_elems + cdata->elems_remaining); + data_offset_size = mod->runtime_params_size - + (cdata->num_elems + cdata->elems_remaining); if (cdata->elems_remaining) pos = MODULE_CFG_FRAGMENT_MIDDLE; else diff --git a/src/include/module/module/base.h b/src/include/module/module/base.h index 657673099d60..8818ffb9f212 100644 --- a/src/include/module/module/base.h +++ b/src/include/module/module/base.h @@ -203,6 +203,13 @@ struct processing_module { struct userspace_context *user_ctx; struct k_mem_domain *mdom; #endif /* CONFIG_USERSPACE */ + + /* total size of a fragmented runtime-params (get/set) transfer, kept + * per instance so concurrent transfers to different components do not + * corrupt each other's reassembly state. Appended here to avoid shifting + * the offsets of the fields above. + */ + uint32_t runtime_params_size; #endif /* SOF_MODULE_PRIVATE */ };