From 8ee41d7bf5f8763b7bec13a11fbd4db0fc94b3a5 Mon Sep 17 00:00:00 2001 From: Tomasz Leman Date: Mon, 27 Jul 2026 23:02:23 +0200 Subject: [PATCH] audio: copier: bound ALH mapping count to the gateway config size copier_alh_assign_dai_index() reads alh_cfg.count from the host-supplied gateway config blob and walks alh_cfg.mapping[0..count). count is only clamped to the mapping[] array size (IPC4_ALH_MAX_NUMBER_OF_GTW), never to the actual blob size, so a blob that advertises more mappings than it holds makes the walk read past the config_data allocation. The same unchecked count also underflows dma_config_length in the HDA branch (config_length * 4 - get_alh_config_size()). A fuzzer-crafted IPC4 copier init (config_length=13 -> 52-byte blob, count=15 -> 128 bytes needed) triggers a heap out-of-bounds read reported by AddressSanitizer at the SOF_DAI_INTEL_ALH mapping[] load. Validate up front that the blob holds the fixed header (so count can be read safely), that count is within the array bound, and that get_alh_config_size() fits in the blob before touching mapping[]. Valid ALH/HDA blobs are unaffected. This completes the earlier count guards by bounding count against the actual blob size. Also reject a gateway blob shorter than the fixed ALH header before reading or logging alh_cfg.count. Although the original compound check short-circuited the count validation safely, its error message still dereferenced count for a truncated blob. Capture and report count only after the header-size check succeeds. Signed-off-by: Tomasz Leman --- src/audio/copier/copier_dai.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/audio/copier/copier_dai.c b/src/audio/copier/copier_dai.c index 109bc2a4a6b2..663856d7e033 100644 --- a/src/audio/copier/copier_dai.c +++ b/src/audio/copier/copier_dai.c @@ -77,7 +77,8 @@ static int copier_alh_assign_dai_index(struct comp_dev *dev, struct copier_data *cd = module_get_private_data(mod); const struct sof_alh_configuration_blob *alh_blob = gtw_cfg_data; uint8_t *dma_config; - size_t alh_cfg_size, dma_config_length; + size_t alh_cfg_size, dma_config_length, blob_size; + uint32_t alh_count; int i, dai_num, ret; if (!cd->config.gtw_cfg.config_length) { @@ -85,6 +86,21 @@ static int copier_alh_assign_dai_index(struct comp_dev *dev, return -EINVAL; } + blob_size = (size_t)cd->config.gtw_cfg.config_length << 2; + if (blob_size < sizeof(alh_blob->gtw_attributes) + sizeof(alh_blob->alh_cfg.count)) { + comp_err(mod->dev, "Invalid ALH gateway config: blob=%u bytes", + (uint32_t)blob_size); + return -EINVAL; + } + + alh_count = alh_blob->alh_cfg.count; + if (alh_count > IPC4_ALH_MAX_NUMBER_OF_GTW || + get_alh_config_size(alh_blob) > blob_size) { + comp_err(mod->dev, "Invalid ALH gateway config: count=%u, blob=%u bytes", + alh_count, (uint32_t)blob_size); + return -EINVAL; + } + switch (dai->type) { case SOF_DAI_INTEL_HDA: /* We use DAI_INTEL_HDA for ACE 2.0 platforms */