diff --git a/src/audio/copier/copier.c b/src/audio/copier/copier.c index 93e018408bf3..2e3cbcfaac30 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; @@ -785,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; } 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; 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]); } 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 */