From a89c4c5c4e9906ea312303c5a530189d86971c08 Mon Sep 17 00:00:00 2001 From: Tomasz Leman Date: Tue, 20 Oct 2026 15:23:21 +0200 Subject: [PATCH 1/2] ipc4: helper: reject module drivers without a create op INIT_MODULE_INSTANCE carries a host-controlled module_id. module_id 0 is BaseFW: on hardware ipc4_get_comp_drv(0) resolves the manifest entry to the registered comp_basefw driver, which only implements get/set_large_config and has no create op. comp_new_ipc4() then calls drv->ops.create() through a NULL function pointer. Reject any resolved driver without a create op before the call and return NULL so the handler reports IPC4_MOD_NOT_INITIALIZED. Apply the same check on the kernel-side lookup that precedes forwarding INIT to the user-space LL thread, so a query-only driver is never handed to comp_new_ipc4_user(). Reproduced on native_sim with a framed INIT for module 0 / instance 0, ppl_instance_id = IPC4_INVALID_PIPELINE_ID: comp_new_ipc4() now returns NULL and ipc4_init_module_instance() returns 104 (gdb-confirmed that the resolved driver is comp_basefw with ops.create == NULL). Signed-off-by: Tomasz Leman --- src/ipc/ipc4/handler-user.c | 2 +- src/ipc/ipc4/helper.c | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/ipc/ipc4/handler-user.c b/src/ipc/ipc4/handler-user.c index 8aee53d382b3..225af13abe6c 100644 --- a/src/ipc/ipc4/handler-user.c +++ b/src/ipc/ipc4/handler-user.c @@ -1582,7 +1582,7 @@ __cold int ipc4_user_process_module_message(struct ipc4_message_request *ipc4, mi->primary.r.instance_id); const struct comp_driver *drv = ipc4_get_comp_drv(IPC4_MOD_ID(comp_id)); - if (!drv) { + if (!drv || !drv->ops.create) { ret = IPC4_MOD_NOT_INITIALIZED; break; } diff --git a/src/ipc/ipc4/helper.c b/src/ipc/ipc4/helper.c index 18bc4904464c..bd1e305a2eb9 100644 --- a/src/ipc/ipc4/helper.c +++ b/src/ipc/ipc4/helper.c @@ -201,6 +201,12 @@ __cold struct comp_dev *comp_new_ipc4(const struct ipc4_module_init_instance *mo if (!drv) return NULL; + if (!drv->ops.create) { + tr_err(&ipc_tr, "comp 0x%x: module %u is not instantiable", comp_id, + (uint32_t)IPC4_MOD_ID(comp_id)); + return NULL; + } + if (drv->type == SOF_COMP_MODULE_ADAPTER) { const struct ipc_config_process spec = { .data = data, From ead21f7f6e450c5057e2f703426f72bbfe72eab7 Mon Sep 17 00:00:00 2001 From: Tomasz Leman Date: Tue, 20 Oct 2026 15:31:06 +0200 Subject: [PATCH 2/2] ipc4: helper: route module_id 0 to BaseFW in fuzz builds native_sim fuzz builds have no rimage manifest, so ipc4_get_comp_drv() falls back to ipc4_get_fuzzer_drv(), which returned NULL for module_id 0. Every LARGE_CONFIG_GET/SET addressed to BaseFW therefore failed with IPC4_INVALID_RESOURCE_ID and src/audio/base_fw.c, one of the largest host-facing IPC4 parsers, received zero fuzzing (0.7 % line coverage over a 19-night campaign). The comment claiming BaseFW messages are "dispatched directly by base_fw.c" was wrong: the handlers resolve the driver and call drv->ops.get/set_large_config() with dev == NULL. Resolve module_id 0 the way the manifest does on hardware: by the BaseFW registry UUID through ipc4_search_for_drv(), never by list position. The 1-based module-adapter mapping for module_id > 0 and the exclusion of internal host/DAI drivers are unchanged. BaseFW remains non-instantiable because comp_new_ipc4() rejects drivers without a create op. Signed-off-by: Tomasz Leman --- src/ipc/ipc4/helper.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/ipc/ipc4/helper.c b/src/ipc/ipc4/helper.c index bd1e305a2eb9..c135f43a4e97 100644 --- a/src/ipc/ipc4/helper.c +++ b/src/ipc/ipc4/helper.c @@ -1367,19 +1367,16 @@ __cold static const struct comp_driver *ipc4_get_drv(const void *uuid) * 1-based index into the runtime component driver list, counting only * instantiable module-adapter drivers so the fuzzer's module_id space matches * what a real signed manifest would expose. - * - * module_id 0 (BaseFW) is deliberately not mapped: BaseFW is never created as - * a pipeline component - its messages are dispatched directly by base_fw.c - - * so returning NULL for it here is correct. */ static const struct comp_driver *ipc4_get_fuzzer_drv(uint32_t module_id) { + static const struct sof_uuid basefw_reg_uuid = SOF_REG_UUID(basefw); struct comp_driver_list *dlist = comp_drivers_get(); struct list_item *iter; uint32_t idx = 0; if (!module_id) - return NULL; + return ipc4_search_for_drv(&basefw_reg_uuid); list_for_item(iter, &dlist->list) { struct comp_driver_info *inf =