From 5b577fb3ed312d7eab153ed197caac3dbc64cef8 Mon Sep 17 00:00:00 2001 From: Tomasz Leman Date: Tue, 27 Oct 2026 17:13:04 +0100 Subject: [PATCH 1/2] audio: copier: bound DMIC gateway blob before reading fade params copier_gain_set_params() casts the copier gateway blob to a struct dmic_config_data and reads the fade-in and silence periods from its global config, 20 bytes into the blob. The blob is copied into the copier instance with the host-supplied gtw_cfg.config_length (in dwords), and nothing required that length to cover the global config: ipc4_find_dma_config() only looks for a DMA-config TLV. An IPC4 INIT_INSTANCE for a copier with a DMIC link input gateway and config_length = 0 therefore reads past the end of the instance allocation. ASan reports it on native_sim as: use-after-poison ... READ of size 4 copier_gain_set_params src/audio/copier/copier_gain.c:43 copier_dai_init src/audio/copier/copier_dai.c:262 copier_dai_create src/audio/copier/copier_dai.c:380 copier_init src/audio/copier/copier.c:237 Require the blob to be at least as long as the global config before dereferencing it, and reject the malformed gateway configuration otherwise. Assisted-by: Copilot:claude-opus-4.8 Signed-off-by: Tomasz Leman --- src/audio/copier/copier_gain.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/audio/copier/copier_gain.c b/src/audio/copier/copier_gain.c index 842f92997108..dfb677b57bfa 100644 --- a/src/audio/copier/copier_gain.c +++ b/src/audio/copier/copier_gain.c @@ -16,6 +16,18 @@ LOG_MODULE_DECLARE(copier, CONFIG_SOF_LOG_LEVEL); +/** + * \brief Minimum DMIC gateway blob size, in dwords, holding the global config. + * + * The gateway blob length is host-controlled and expressed in dwords. The DMIC + * fade/silence parameters live in the global config part of the blob, so a blob + * shorter than this cannot be dereferenced for them. + */ +#define DMIC_GLOBAL_CFG_MIN_BLOB_WORDS \ + ((offsetof(struct dmic_config_data, dmic_blob) + \ + offsetof(struct dmic_config_blob, global_cfg) + \ + sizeof(union dmic_global_cfg)) / sizeof(uint32_t)) + __cold int copier_gain_set_params(struct comp_dev *dev, struct copier_gain_params *gain_params, uint32_t fade_period, enum sof_ipc_dai_type dai_type) { @@ -34,10 +46,17 @@ __cold int copier_gain_set_params(struct comp_dev *dev, struct copier_gain_param switch (dai_type) { case SOF_DAI_INTEL_DMIC: { - struct dmic_config_data *dmic_cfg = - (void *)cd->config.gtw_cfg.config_data; + struct dmic_config_data *dmic_cfg; + union dmic_global_cfg *dmic_glb_cfg; + + if (cd->config.gtw_cfg.config_length < DMIC_GLOBAL_CFG_MIN_BLOB_WORDS) { + comp_err(dev, "DMIC gateway blob too short: %u dwords", + cd->config.gtw_cfg.config_length); + return -EINVAL; + } - union dmic_global_cfg *dmic_glb_cfg = &dmic_cfg->dmic_blob.global_cfg; + dmic_cfg = (void *)cd->config.gtw_cfg.config_data; + dmic_glb_cfg = &dmic_cfg->dmic_blob.global_cfg; /* Get fade period from DMIC blob */ fade_period = dmic_glb_cfg->ext_global_cfg.fade_in_period; From 00ed003d2693e7c115ec16a6b5b98a8b6bc8b0f6 Mon Sep 17 00:00:00 2001 From: Tomasz Leman Date: Tue, 27 Oct 2026 17:27:39 +0100 Subject: [PATCH 2/2] audio: copier: skip fade step calculation for a zero fade length copier_gain_set_fade_params() divides INT64_MAX by fade_sg_length, which is computed as frames * fade_period where frames is the host-supplied sampling frequency divided by the pipeline period and fade_period comes from the DMIC gateway blob. Both inputs are host-controlled, so the product can be zero: a DMIC copier created with a sampling frequency below the pipeline period rate makes frames zero and the division faults (SIGFPE in __udivdi3, reported by ASan as "FPE on unknown address"). A zero fade length simply means no fade segment, which is already the documented behaviour of the GAIN_ZERO_TRANS_MS case just above, so return early with the fade disabled instead of computing a step for it. Apply the same guard to the generic and HiFi implementations. Found while verifying a well-formed DMIC gateway blob against the preceding blob-length fix on an IPC4 + ASan native_sim build. Assisted-by: Copilot:claude-opus-4.8 Signed-off-by: Tomasz Leman --- src/audio/copier/copier_generic.c | 8 ++++++++ src/audio/copier/copier_hifi.c | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/src/audio/copier/copier_generic.c b/src/audio/copier/copier_generic.c index bb5918819e5b..d056cef9a167 100644 --- a/src/audio/copier/copier_generic.c +++ b/src/audio/copier/copier_generic.c @@ -95,6 +95,14 @@ __cold int copier_gain_set_fade_params(struct comp_dev *dev, struct copier_gain_ gain_params->fade_sg_length = frames * fade_period; } + /* + * fade_sg_length derives from the host-supplied sampling frequency, + * pipeline period and fade period, so it can legitimately round down to + * zero. Leave the fade disabled rather than dividing by it below. + */ + if (!gain_params->fade_sg_length) + return 0; + /* High precision step for fade-in calculation, keeps accurate precision */ gain_params->step_i64 = INT64_MAX / gain_params->fade_sg_length; step_i64_to_i16 = gain_params->step_i64 >> I64_TO_I16_SHIFT; diff --git a/src/audio/copier/copier_hifi.c b/src/audio/copier/copier_hifi.c index 14c91b632f5b..aae0f497c2ff 100644 --- a/src/audio/copier/copier_hifi.c +++ b/src/audio/copier/copier_hifi.c @@ -120,6 +120,14 @@ __cold int copier_gain_set_fade_params(struct comp_dev *dev, struct copier_gain_ gain_params->fade_sg_length = frames * fade_period; } + /* + * fade_sg_length derives from the host-supplied sampling frequency, + * pipeline period and fade period, so it can legitimately round down to + * zero. Leave the fade disabled rather than dividing by it below. + */ + if (!gain_params->fade_sg_length) + return 0; + /* High precision step for fade-in calculation, keeps accurate precision */ gain_params->step_i64 = INT64_MAX / gain_params->fade_sg_length; step_i64_to_i16 = gain_params->step_i64 >> I64_TO_I16_SHIFT;