From a63d2832f4223b24fb10a6144fc787bd5e2a654b Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Jun 2026 10:19:07 +0200 Subject: [PATCH 1/2] lib-manager: check total claimed library size when loading A corrupted or malformed library can provide the required page count that overflows 32-bit multiplication. Check once when loading. Signed-off-by: Guennadi Liakhovetski --- src/library_manager/lib_manager.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/library_manager/lib_manager.c b/src/library_manager/lib_manager.c index 56cd616cd9f5..4ba538453bfa 100644 --- a/src/library_manager/lib_manager.c +++ b/src/library_manager/lib_manager.c @@ -949,9 +949,17 @@ static int lib_manager_store_library(struct lib_manager_dma_ext *dma_ext, void __sparse_cache *library_base_address; const struct sof_man_fw_desc *man_desc = (struct sof_man_fw_desc *) ((__sparse_force uint8_t *)man_buffer + SOF_MAN_ELF_TEXT_OFFSET); - uint32_t preload_size = man_desc->header.preload_page_count * PAGE_SZ; int ret; + /* Zephyr UINT_MAX is explicitly 32 bits, and so is preload_page_count */ + if (man_desc->header.preload_page_count >= UINT_MAX / PAGE_SZ) { + tr_err(&lib_manager_tr, "Invalid preload page count %u.", + man_desc->header.preload_page_count); + return -EINVAL; + } + + uint32_t preload_size = man_desc->header.preload_page_count * PAGE_SZ; + /* * The module manifest structure always has its maximum size regardless of * the actual size of the manifest. @@ -961,10 +969,10 @@ static int lib_manager_store_library(struct lib_manager_dma_ext *dma_ext, return -EINVAL; } - /* Prepare storage memory, note: it is never freed, library unloading is unsupported */ /* - * Prepare storage memory, note: it is never freed, it is assumed, that this - * memory is abundant, so we store all loaded modules there permanently + * Prepare storage memory, note: it is never freed, it is assumed, that + * this memory is abundant, so we store all loaded modules there + * permanently, unloading is unsupported */ library_base_address = lib_manager_allocate_store_mem(preload_size, 0); if (!library_base_address) From 941a4387d95dd72308066ae2f03196d06635a746 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 16 Jun 2026 14:06:30 +0200 Subject: [PATCH 2/2] llext: check number of module entries in libraries Validate module entry number to avoid out of boundary memory access. Signed-off-by: Guennadi Liakhovetski --- src/library_manager/llext_manager.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/library_manager/llext_manager.c b/src/library_manager/llext_manager.c index a370a5f1c7f7..4c1e4f02d5b5 100644 --- a/src/library_manager/llext_manager.c +++ b/src/library_manager/llext_manager.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -457,9 +458,22 @@ static int llext_manager_mod_init(struct lib_manager_mod_ctx *ctx, { struct sof_man_module *mod_array = (struct sof_man_module *)((uint8_t *)desc + SOF_MAN_MODULE_OFFSET(0)); + /* preload_page_count was checked when library was loaded */ + size_t lib_size = desc->header.preload_page_count * PAGE_SZ; unsigned int i, n_mod; size_t offs; + /* We'll check overflows below */ + uintptr_t mod_end_addr = (uintptr_t)(mod_array + desc->header.num_module_entries); + uintptr_t img_end_addr = (uintptr_t)desc - SOF_MAN_ELF_TEXT_OFFSET + lib_size; + + if (mod_end_addr < (uintptr_t)mod_array || img_end_addr < (uintptr_t)desc || + mod_end_addr >= img_end_addr) { + tr_err(&lib_manager_tr, "invalid module entry count: %u", + desc->header.num_module_entries); + return -EOVERFLOW; + } + /* count modules */ for (i = 0, n_mod = 0, offs = ~0; i < desc->header.num_module_entries; i++) if (mod_array[i].segment[LIB_MANAGER_TEXT].file_offset != offs) { @@ -1055,9 +1069,13 @@ int llext_manager_add_library(uint32_t module_id) const struct sof_man_fw_desc *desc = lib_manager_get_library_manifest(module_id); unsigned int i; + int ret; - if (!ctx->mod) - llext_manager_mod_init(ctx, desc); + if (!ctx->mod) { + ret = llext_manager_mod_init(ctx, desc); + if (ret < 0) + return ret; + } for (i = 0; i < ctx->n_mod; i++) { const struct sof_man_module *mod = lib_manager_get_module_manifest(module_id + i); @@ -1065,9 +1083,9 @@ int llext_manager_add_library(uint32_t module_id) if (mod->type.load_type == SOF_MAN_MOD_TYPE_LLEXT_AUX) { const struct sof_man_module_manifest *mod_manifest; const struct sof_module_api_build_info *buildinfo; - int ret = llext_manager_link_single(module_id + i, desc, ctx, - (const void **)&buildinfo, &mod_manifest); + ret = llext_manager_link_single(module_id + i, desc, ctx, + (const void **)&buildinfo, &mod_manifest); if (ret < 0) return ret; }