From e972ba94ee6c0885e9dbadf86c4501d3a93ea10c Mon Sep 17 00:00:00 2001 From: Shrushti P K Date: Sat, 24 Oct 2026 15:30:59 +0530 Subject: [PATCH] audio: mux: cap IPC3 mux routes at the lookup table size mux_prepare_look_up_table() puts every set mask bit of every stream into the single lookup[0] table, and mux_prepare_active_look_up() copies the routes that match the connected channels into active_lookup. Both tables hold PLATFORM_MAX_CHANNELS entries and neither loop is bounded. mux_set_values() limits each mask to one bit, and mux_mix_check() rejects a stream that reuses an output bit or two streams that set the same bit at the same mask index. A blob where two streams route different input channels to the same output passes both checks, so num_streams = 2 with mask[j] = BIT(j) and BIT((j + 1) % 8) gives 16 routes, and num_streams = 4 gives 32. With 8 channel sources and sink, mux_prepare_active_look_up() then writes past active_lookup over model_handler, comp_type and config, and past the end of the component data allocation. Reject a mux configuration with more than PLATFORM_MAX_CHANNELS routes in total. Demux is unaffected, as each stream has its own table bounded by the one bit per mask check. --- src/audio/mux/mux_ipc3.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/audio/mux/mux_ipc3.c b/src/audio/mux/mux_ipc3.c index a3d3beb4b708..8cfa20293b24 100644 --- a/src/audio/mux/mux_ipc3.c +++ b/src/audio/mux/mux_ipc3.c @@ -38,6 +38,7 @@ static int mux_set_values(struct processing_module *mod) struct comp_data *cd = module_get_private_data(mod); struct comp_dev *dev = mod->dev; struct sof_mux_config *cfg = &cd->config; + unsigned int routes = 0; unsigned int i; unsigned int j; @@ -76,6 +77,18 @@ static int mux_set_values(struct processing_module *mod) comp_err(dev, "mux component is not able to mix channels"); return -EINVAL; } + + /* all mux routes go to the single lookup[0] table */ + for (i = 0; i < cfg->num_streams; i++) { + for (j = 0; j < PLATFORM_MAX_CHANNELS; j++) + routes += popcount(cfg->streams[i].mask[j]); + } + + if (routes > PLATFORM_MAX_CHANNELS) { + comp_err(dev, "%u routes exceed maximum = " + STRINGIFY(PLATFORM_MAX_CHANNELS), routes); + return -EINVAL; + } } for (i = 0; i < cfg->num_streams; i++) {