diff --git a/src/audio/volume/volume_ipc3.c b/src/audio/volume/volume_ipc3.c index 6a88b68e6ae8..66f71ffe1c5c 100644 --- a/src/audio/volume/volume_ipc3.c +++ b/src/audio/volume/volume_ipc3.c @@ -157,8 +157,11 @@ int volume_init(struct processing_module *mod) break; default: comp_err(dev, "invalid ramp type %d", vol->ramp); - mod_free(mod, cd); + /* free cd->vol before cd: freeing cd first would leave the + * following cd->vol read dereferencing freed memory + */ mod_free(mod, cd->vol); + mod_free(mod, cd); return -EINVAL; } diff --git a/src/audio/volume/volume_ipc4.c b/src/audio/volume/volume_ipc4.c index 57a5f427903e..ca694b908338 100644 --- a/src/audio/volume/volume_ipc4.c +++ b/src/audio/volume/volume_ipc4.c @@ -127,6 +127,15 @@ int volume_init(struct processing_module *mod) return -EINVAL; } + /* the per-channel config[] array is read below for every channel, so + * the init payload must be large enough to hold them all + */ + if (cfg->size < sizeof(*vol) + channels_count * sizeof(vol->config[0])) { + comp_err(dev, "Invalid init payload size %zu for %u channels", + cfg->size, channels_count); + return -EINVAL; + } + cd = mod_zalloc(mod, sizeof(struct vol_data)); if (!cd) return -ENOMEM; @@ -268,8 +277,10 @@ static int volume_set_attenuation(struct processing_module *mod, const uint8_t * struct comp_dev *dev = mod->dev; uint32_t attenuation; - /* only support attenuation in format of 32bit */ - if (data_size > sizeof(uint32_t)) { + /* only support attenuation in format of 32bit; the payload is + * dereferenced as a uint32_t below so it must be exactly that size + */ + if (data_size < (int)sizeof(uint32_t) || data_size > sizeof(uint32_t)) { comp_err(dev, "attenuation data size %d is incorrect", data_size); return -EINVAL; }