From 0e01eaf532bf8517624e2b542a3af21407b50731 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 11 Jun 2026 14:30:37 +0100 Subject: [PATCH 1/3] volume: avoid use-after-free in init error path On an invalid ramp type the init error path freed the component data then read a field from it. Free the dependent allocation before the component data and stop dereferencing it afterwards. Signed-off-by: Liam Girdwood --- src/audio/volume/volume_ipc3.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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; } From 3b88571c744f4da20eb6e43e05f9af8e8ca84f5f Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 11 Jun 2026 14:32:42 +0100 Subject: [PATCH 2/3] volume: validate init payload covers per-channel config Init read a per-channel config array sized by the channel count from the init payload without checking the payload was large enough, reading past the mailbox. Require the payload to cover the base config and all per-channel entries. Signed-off-by: Liam Girdwood --- src/audio/volume/volume_ipc4.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/audio/volume/volume_ipc4.c b/src/audio/volume/volume_ipc4.c index 57a5f427903e..a1e6e6eff25f 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; From 87fb018eaaf57c8c3420ddf98ce7d87db0c8250f Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 11 Jun 2026 14:32:42 +0100 Subject: [PATCH 3/3] volume: require a full word for the attenuation control The attenuation setter only rejected oversized payloads, then dereferenced the data as a 32-bit value; a shorter payload read past the mailbox. Require exactly a 32-bit payload. Signed-off-by: Liam Girdwood --- src/audio/volume/volume_ipc4.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/audio/volume/volume_ipc4.c b/src/audio/volume/volume_ipc4.c index a1e6e6eff25f..ca694b908338 100644 --- a/src/audio/volume/volume_ipc4.c +++ b/src/audio/volume/volume_ipc4.c @@ -277,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; }