Skip to content

Commit 11200e5

Browse files
tmlemankv2019i
authored andcommitted
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 was only bounded by the mapping[] array size, not the actual blob size, so a malformed blob could make the mapping walk read past config_data and underflow dma_config_length in the HDA branch. Validate that the blob contains the fixed header before reading count, then ensure count is within the mapping[] bound and that its computed ALH configuration size fits in the blob. This rejects malformed configurations before any mapping[] access. HDA always reads mapping[0], including for a single gateway. Reject a zero count in this path so a header-only blob cannot cause that out-of-bounds read. Keep zero-count behavior unchanged for single ALH, which does not access mapping[]. Use %zu when logging blob_size to preserve size_t values on 64-bit builds. Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>
1 parent ab4d585 commit 11200e5

1 file changed

Lines changed: 19 additions & 9 deletions

File tree

src/audio/copier/copier_dai.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,28 +77,38 @@ static int copier_alh_assign_dai_index(struct comp_dev *dev,
7777
struct copier_data *cd = module_get_private_data(mod);
7878
const struct sof_alh_configuration_blob *alh_blob = gtw_cfg_data;
7979
uint8_t *dma_config;
80-
size_t alh_cfg_size, dma_config_length;
80+
size_t alh_cfg_size, dma_config_length, blob_size;
81+
uint32_t alh_count;
8182
int i, dai_num, ret;
8283

8384
if (!cd->config.gtw_cfg.config_length) {
8485
comp_err(mod->dev, "No gateway config found in blob!");
8586
return -EINVAL;
8687
}
8788

89+
blob_size = (size_t)cd->config.gtw_cfg.config_length << 2;
90+
if (blob_size < sizeof(alh_blob->gtw_attributes) + sizeof(alh_blob->alh_cfg.count)) {
91+
comp_err(mod->dev, "Invalid ALH gateway config: blob=%zu bytes", blob_size);
92+
return -EINVAL;
93+
}
94+
95+
alh_count = alh_blob->alh_cfg.count;
96+
if (alh_count > IPC4_ALH_MAX_NUMBER_OF_GTW ||
97+
get_alh_config_size(alh_blob) > blob_size) {
98+
comp_err(mod->dev, "Invalid ALH gateway config: count=%u, blob=%zu bytes",
99+
alh_count, blob_size);
100+
return -EINVAL;
101+
}
102+
alh_cfg_size = get_alh_config_size(alh_blob);
103+
88104
switch (dai->type) {
89105
case SOF_DAI_INTEL_HDA:
90106
/* We use DAI_INTEL_HDA for ACE 2.0 platforms */
91-
/*
92-
* alh_cfg.count is host-controlled and scales the config size
93-
* and mapping[] walk below; bound it before any arithmetic so a
94-
* crafted blob cannot read past the gateway config.
95-
*/
96-
if (alh_blob->alh_cfg.count > IPC4_ALH_MAX_NUMBER_OF_GTW) {
107+
if (!alh_count) {
97108
comp_err(mod->dev, "Invalid ALH count: %u",
98-
alh_blob->alh_cfg.count);
109+
alh_count);
99110
return -EINVAL;
100111
}
101-
alh_cfg_size = get_alh_config_size(alh_blob);
102112
dma_config = (uint8_t *)gtw_cfg_data + alh_cfg_size;
103113
dma_config_length = (cd->config.gtw_cfg.config_length << 2) - alh_cfg_size;
104114

0 commit comments

Comments
 (0)