From 8112cf291f2ee825e0992ddb5da159c480799442 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 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/audio/copier/copier.c b/src/audio/copier/copier.c index 93e018408bf3..a6566892fe41 100644 --- a/src/audio/copier/copier.c +++ b/src/audio/copier/copier.c @@ -147,6 +147,18 @@ __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. + * cfg_total_size is at least sizeof(*copier), so this also rejects an + * empty (md->cfg.size == 0) or otherwise too-small init payload. + */ + if (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 950e2b1f5c30a18a83746fde768c7c8bc468247e 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 41c285fc014b4c60a9d11b90a187737135a07df1 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 adea8a71c04f9823de88761e2dc0b5e07304c5ac 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 a6566892fe41..1a7a0b5be959 100644 --- a/src/audio/copier/copier.c +++ b/src/audio/copier/copier.c @@ -797,9 +797,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 c48d2a223ee80b0b417120cc612c0bb563a89cdc 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..115c9a4a7e2d 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 < + SOF_DIV_ROUND_UP(sizeof(struct ipc4_gateway_config_data) + + sizeof(struct ipc4_ipc_gateway_config_blob), + 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 */