From fc0d6b61757bdfaf9c99fdd609a2fcd72cbf28de Mon Sep 17 00:00:00 2001 From: Tomasz Leman Date: Tue, 8 Sep 2026 12:09:25 +0200 Subject: [PATCH] audio: mixin_mixout: reject prepare of an unconnected instance mixin_prepare() and mixout_prepare() dereferenced sinks[0] without checking num_of_sinks. The connection arrays in struct processing_module are only populated by module_adapter_bind(), and module_adapter_sink_src_prepare() forwards them verbatim, so a module instance that the host created but never bound is still prepared with num_of_sinks == 0 and sinks[0] == NULL. A host that issues CREATE_PIPELINE, INIT_MODULE_INSTANCE (mixin/mixout) and then SET_PIPELINE_STATE without any BIND therefore made pipeline_prepare() walk into mixout_params(), where sink_set_valid_fmt(mod->sinks[0], ...) faulted while writing sink->audio_stream_params (SEGV on NULL + 0x14). mixin_prepare() has the same unguarded sink_get_valid_fmt(sinks[0]) one function later; both are fixed here. Reject an instance with no sink in .prepare() with -ENOTCONN before the dereference, matching the existing guards in rtnr_prepare() and mux_process(). This cannot reject a valid configuration: a functional mixin/mixout must have at least one bound sink. The mixout_prepare() entry trace is moved above the check so the rejected case is traced too. Found by the IPC4 libFuzzer harness on native_sim under ASan. Signed-off-by: Tomasz Leman --- src/audio/mixin_mixout/mixin_mixout.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/audio/mixin_mixout/mixin_mixout.c b/src/audio/mixin_mixout/mixin_mixout.c index 78cea04daf19..a6f1eaba6023 100644 --- a/src/audio/mixin_mixout/mixin_mixout.c +++ b/src/audio/mixin_mixout/mixin_mixout.c @@ -717,6 +717,12 @@ static int mixin_prepare(struct processing_module *mod, int ret; comp_info(dev, "entry"); + + if (!num_of_sinks) { + comp_err(dev, "no sink buffer"); + return -ENOTCONN; + } + #if CONFIG_XRUN_NOTIFICATIONS_ENABLE md->eos_delay_configured = false; #endif @@ -787,12 +793,17 @@ static int mixout_prepare(struct processing_module *mod, struct mixout_data *md; int ret, i; + comp_dbg(dev, "entry"); + + if (!num_of_sinks) { + comp_err(dev, "no sink buffer"); + return -ENOTCONN; + } + ret = mixout_params(mod); if (ret < 0) return ret; - comp_dbg(dev, "entry"); - /* * Since mixout sink buffer stream is reset on .prepare(), let's * reset counters for not yet produced frames in that buffer.