From e75b60f25d6b815416f70511815a32c785b596a7 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 11 Jun 2026 13:07:54 +0100 Subject: [PATCH 1/5] copier: bound gateway config length to init payload size The gateway configuration length from the init payload was multiplied and used as a copy length from the mailbox without checking it against the actual payload size. Reject a configuration that would read past the init payload. Signed-off-by: Liam Girdwood --- src/audio/copier/copier.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/audio/copier/copier.c b/src/audio/copier/copier.c index 93e018408bf3..0cc5f2340a7c 100644 --- a/src/audio/copier/copier.c +++ b/src/audio/copier/copier.c @@ -147,6 +147,16 @@ __cold static int copier_init(struct processing_module *mod) cfg_total_size += gtw_cfg_var_size; } + /* + * gtw_cfg.config_length is host-controlled; make sure the resulting + * copy length does not read past the init payload in the mailbox. + */ + if (md->cfg.size && cfg_total_size > md->cfg.size) { + comp_err(dev, "copier_init(): cfg size %zu exceeds init payload %zu", + cfg_total_size, md->cfg.size); + return -EINVAL; + } + cd = mod_zalloc(mod, sizeof(*cd) + gtw_cfg_var_size); if (!cd) return -ENOMEM; From 02eca4be65cd9f6db2523bb6f6e741b35d1c086d Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 11 Jun 2026 13:07:54 +0100 Subject: [PATCH 2/5] copier: validate gateway count before computing config size The multi-gateway count from the gateway config was used to compute sizes and walk the mapping array before being bounded. Reject a count above the supported maximum before any arithmetic. Signed-off-by: Liam Girdwood --- src/audio/copier/copier_dai.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/audio/copier/copier_dai.c b/src/audio/copier/copier_dai.c index dfd2590c7108..eaf178f255a3 100644 --- a/src/audio/copier/copier_dai.c +++ b/src/audio/copier/copier_dai.c @@ -88,6 +88,16 @@ static int copier_alh_assign_dai_index(struct comp_dev *dev, switch (dai->type) { case SOF_DAI_INTEL_HDA: /* We use DAI_INTEL_HDA for ACE 2.0 platforms */ + /* + * alh_cfg.count is host-controlled and scales the config size + * and mapping[] walk below; bound it before any arithmetic so a + * crafted blob cannot read past the gateway config. + */ + if (alh_blob->alh_cfg.count > IPC4_ALH_MAX_NUMBER_OF_GTW) { + comp_err(mod->dev, "Invalid ALH count: %u", + alh_blob->alh_cfg.count); + return -EINVAL; + } alh_cfg_size = get_alh_config_size(alh_blob); dma_config = (uint8_t *)gtw_cfg_data + alh_cfg_size; dma_config_length = (cd->config.gtw_cfg.config_length << 2) - alh_cfg_size; From 957cc9f2d17ab985724634c466e3365ed852735a Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 11 Jun 2026 13:07:54 +0100 Subject: [PATCH 3/5] copier: bound output format index by sink queue id The sink queue id was used directly to index the output format array when updating parameters, unlike the other call sites which bound it. Skip a sink whose queue id exceeds the output pin count. Signed-off-by: Liam Girdwood --- src/audio/copier/copier_generic.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/audio/copier/copier_generic.c b/src/audio/copier/copier_generic.c index 89805f25af0c..bb5918819e5b 100644 --- a/src/audio/copier/copier_generic.c +++ b/src/audio/copier/copier_generic.c @@ -330,6 +330,12 @@ void copier_update_params(struct copier_data *cd, struct comp_dev *dev, int j; j = IPC4_SRC_QUEUE_ID(buf_get_id(sink)); + /* src_queue id is host-controlled; bound it before indexing out_fmt[] */ + if (j >= IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT) { + comp_err(dev, "invalid src_queue id %d", j); + continue; + } + ipc4_update_buffer_format(sink, &cd->out_fmt[j]); } From cf12086a0961d65ca01382cb515ca19ee71cab83 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 11 Jun 2026 14:30:13 +0100 Subject: [PATCH 4/5] copier: 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 payload shorter than that read past the mailbox. Require exactly a 32-bit payload. Signed-off-by: Liam Girdwood --- src/audio/copier/copier.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/audio/copier/copier.c b/src/audio/copier/copier.c index 0cc5f2340a7c..2e3cbcfaac30 100644 --- a/src/audio/copier/copier.c +++ b/src/audio/copier/copier.c @@ -795,9 +795,11 @@ __cold static int set_attenuation(struct comp_dev *dev, uint32_t data_offset, co assert_can_be_cold(); - /* only support attenuation in format of 32bit */ - if (data_offset > sizeof(uint32_t)) { - comp_err(dev, "attenuation data size %d is incorrect", data_offset); + /* 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_offset != sizeof(uint32_t)) { + comp_err(dev, "attenuation data size %u is incorrect", data_offset); return -EINVAL; } From 971fc962740abe118dc12847116a2de8e53013f8 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 11 Jun 2026 14:30:13 +0100 Subject: [PATCH 5/5] copier: validate ipc gateway config length covers the blob The IPC gateway path read a config blob from the gateway data without checking the declared config length covered it, over-reading the mailbox tail. Reject a config length too small for the gateway config header and blob. Signed-off-by: Liam Girdwood --- src/audio/copier/copier_ipcgtw.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/audio/copier/copier_ipcgtw.c b/src/audio/copier/copier_ipcgtw.c index ed365c1e50d8..3efda681768a 100644 --- a/src/audio/copier/copier_ipcgtw.c +++ b/src/audio/copier/copier_ipcgtw.c @@ -223,6 +223,20 @@ __cold int copier_ipcgtw_create(struct processing_module *mod, return -EINVAL; } + /* config_length is in dwords; require enough dwords to cover the + * gateway config header and the blob read below. Compare dword counts + * (rather than scaling config_length by 4) so a large host-supplied + * value cannot overflow the multiplication on 32-bit size_t. + */ + if (gtw_cfg->config_length < + (sizeof(struct ipc4_gateway_config_data) + + sizeof(struct ipc4_ipc_gateway_config_blob) + + sizeof(uint32_t) - 1) / sizeof(uint32_t)) { + comp_err(dev, "ipc4_gateway_config_data too small: %u", + gtw_cfg->config_length); + return -EINVAL; + } + cd->ipc_gtw = true; /* The IPC gateway is treated as a host gateway */