diff --git a/src/audio/copier/copier.c b/src/audio/copier/copier.c index 6e7b379a1f33..e64f98705b7f 100644 --- a/src/audio/copier/copier.c +++ b/src/audio/copier/copier.c @@ -176,6 +176,16 @@ __cold static int copier_init(struct processing_module *mod) node_id = copier->gtw_cfg.node_id; /* copier is linked to gateway */ if (node_id.dw != IPC4_INVALID_NODE_ID) { + /* 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; + } + cd->direction = get_gateway_direction(node_id.f.dma_type); switch (node_id.f.dma_type) { diff --git a/src/include/ipc4/module.h b/src/include/ipc4/module.h index 4e60ebc9bc13..f026f837801a 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..d5c09c3f7bf7 100644 --- a/src/ipc/ipc4/helper.c +++ b/src/ipc/ipc4/helper.c @@ -145,6 +145,20 @@ __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 *)