From e4ca08c9ea7b4499901da19771574b8c5cd55458 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Wed, 2 Sep 2026 15:43:18 +0300 Subject: [PATCH] llext: userspace: clear cold segment descriptors when sections are absent llext_manager_rm_mod_domain() removes the .cold and .coldrodata memory partitions of a module from its domain if the corresponding mctx->segment[] descriptor has a non-zero address. Those descriptors are only ever populated by llext_manager_add_mod_domain() when the module actually contains a .cold / .coldrodata section. The module context array is allocated with rmalloc() (non-zeroing) and llext_manager_mod_init() initialises every field except the segment[] array. The LIB_MANAGER_TEXT/RODATA/DATA/BSS descriptors are filled in during linking, but LIB_MANAGER_COLD / LIB_MANAGER_COLDRODATA are left holding uninitialised heap data for any module that has no such section. As a result, when such a module is freed, rm_mod_domain() sees a garbage non-zero address and tries to remove a partition that was never added: os.k_mem_domain_remove_partition: no matching partition found lib_manager.llext_manager_rm_mod_domain: failed to remove .coldrodata memory partition: -2 Reproduced at end-of-stream of a DMIC capture (arecord -Dhw:0,4), whose EQIIR / TDFB / DRC modules carry no .coldrodata section. Make add_mod_domain() the sole owner of these descriptors: explicitly zero them when the section is absent, so rm_mod_domain() only ever removes partitions that were really added. Signed-off-by: Kai Vehmanen --- src/library_manager/llext_manager.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/library_manager/llext_manager.c b/src/library_manager/llext_manager.c index 69e27c0c964e..e2c035e35254 100644 --- a/src/library_manager/llext_manager.c +++ b/src/library_manager/llext_manager.c @@ -955,6 +955,16 @@ static int llext_manager_add_mod_domain(struct lib_manager_module *mctx, struct goto e_data; mctx->segment[LIB_MANAGER_COLD].addr = (uintptr_t)text_addr + text_offset; mctx->segment[LIB_MANAGER_COLD].size = shdr_cold.sh_size; + } else { + /* + * No .cold section: make sure the descriptor is empty so that + * llext_manager_rm_mod_domain() doesn't later try to remove a + * partition that was never added. The module context is + * allocated with rmalloc() and these fields are otherwise left + * uninitialised. + */ + mctx->segment[LIB_MANAGER_COLD].addr = 0; + mctx->segment[LIB_MANAGER_COLD].size = 0; } if (rodata) { @@ -967,6 +977,10 @@ static int llext_manager_add_mod_domain(struct lib_manager_module *mctx, struct goto e_cold; mctx->segment[LIB_MANAGER_COLDRODATA].addr = (uintptr_t)rodata_addr + rodata_offset; mctx->segment[LIB_MANAGER_COLDRODATA].size = shdr_coldrodata.sh_size; + } else { + /* No .coldrodata section, see the comment above */ + mctx->segment[LIB_MANAGER_COLDRODATA].addr = 0; + mctx->segment[LIB_MANAGER_COLDRODATA].size = 0; } return 0;