Skip to content

audio: mux: cap IPC3 mux routes at the lookup table size - #11354

Open
Shrusti-pk wants to merge 1 commit into
thesofproject:mainfrom
Shrusti-pk:mux-ipc3-route-cap
Open

Shrusti-pk wants to merge 1 commit into
thesofproject:mainfrom
Shrusti-pk:mux-ipc3-route-cap

Conversation

@Shrusti-pk

Copy link
Copy Markdown
Contributor

The IPC3 mux builds its routing from the bytes control blob: mux_prepare_look_up_table() turns every set mask bit of every stream into an entry of lookup[0], and mux_prepare_active_look_up() copies the routes that match the connected channels into active_lookup, both sized for PLATFORM_MAX_CHANNELS entries with no bound on either loop. mux_set_values() only limits each mask to one bit, and mux_mix_check() only rejects a stream reusing an output bit or two streams setting the same bit at the same mask index. Two streams routing different input channels to the same output pass both checks, so num_streams = 2 with mask[j] = BIT(j) and BIT((j + 1) % 8) yields 16 routes, and four streams yield 32. With 8 channel sources and sink every route survives the active filter, and the copy runs over model_handler, comp_type and config and then past the end of the component data allocation. I confirmed it with an ASan harness built from the same validation and lookup code, which reports a heap-buffer-overflow WRITE in mux_prepare_active_look_up() right after the comp_data region. The check sits in mux_set_values() next to the existing mask checks, so a blob with more routes than the table holds is rejected before any table is built; demux keeps per-stream tables already bounded by the one bit per mask rule, and the mux_copy test masks all stay within 8 routes.

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.
@Shrusti-pk
Shrusti-pk requested a review from fkwasowi as a code owner October 24, 2026 13:33
@sofci

sofci commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator

Can one of the admins verify this patch?

reply test this please to run this test once

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants