diff --git a/src/audio/copier/copier.c b/src/audio/copier/copier.c index 6e7b379a1f33..de5baca01b11 100644 --- a/src/audio/copier/copier.c +++ b/src/audio/copier/copier.c @@ -178,6 +178,17 @@ __cold static int copier_init(struct processing_module *mod) if (node_id.dw != IPC4_INVALID_NODE_ID) { cd->direction = get_gateway_direction(node_id.f.dma_type); + /* + * A gateway copier wires itself into the pipeline graph, so it needs a + * valid parent pipeline (base FW modules using IPC4_INVALID_PIPELINE_ID + * are exempt in comp_new_ipc4()). Reject here to avoid a NULL deref. + */ + if (!dev->pipeline) { + comp_err(dev, "gateway copier requires a valid parent pipeline"); + ret = -EINVAL; + goto error; + } + switch (node_id.f.dma_type) { case ipc4_hda_host_output_class: case ipc4_hda_host_input_class: diff --git a/src/include/ipc4/module.h b/src/include/ipc4/module.h index 4e60ebc9bc13..11d548fb4161 100644 --- a/src/include/ipc4/module.h +++ b/src/include/ipc4/module.h @@ -151,6 +151,10 @@ struct ipc4_module_init_data { \remark hide_methods */ + +/** Reserved ppl_instance_id: module has no parent pipeline (e.g. probe). */ +#define IPC4_INVALID_PIPELINE_ID 0xFF + struct ipc4_module_init_instance { union { diff --git a/src/ipc/ipc4/helper.c b/src/ipc/ipc4/helper.c index 5881fbbfb0b5..017df21288b9 100644 --- a/src/ipc/ipc4/helper.c +++ b/src/ipc/ipc4/helper.c @@ -145,6 +145,21 @@ __cold struct comp_dev *comp_new_ipc4(struct ipc4_module_init_instance *module_i ipc_config.ipc_config_size); return NULL; } + + /* + * Reject a module naming a non-existent parent pipeline: otherwise + * dev->pipeline stays NULL and a later init path (e.g. the copier) + * dereferences it. IPC4_INVALID_PIPELINE_ID is exempt - it marks base FW + * modules with no parent pipeline. IPC_COMP_ALL: the pipeline may run on a + * different core than this module. + */ + if (ipc_config.pipeline_id != IPC4_INVALID_PIPELINE_ID && + !ipc_get_comp_by_ppl_id(ipc_get(), COMP_TYPE_PIPELINE, ipc_config.pipeline_id, + IPC_COMP_ALL)) { + tr_err(&ipc_tr, "comp 0x%x: parent pipeline %u does not exist", comp_id, + (uint32_t)ipc_config.pipeline_id); + return NULL; + } #ifdef CONFIG_DCACHE_LINE_SIZE if (!IS_ENABLED(CONFIG_LIBRARY)) sys_cache_data_invd_range((__sparse_force void __sparse_cache *)