From 166f17746c2272d5e4bdbc7faa01cb4919589105 Mon Sep 17 00:00:00 2001 From: yushuailong Date: Wed, 16 Sep 2026 15:51:46 +0800 Subject: [PATCH] libc/elf: Always free the module symbol table on removal. libelf_uninit() only called libelf_freesymtab() when the module had an uninitializer. But the exported symbol table is built by libelf_insertsymtab() for every loaded module, and nothing in the tree sets modinfo.uninitializer anymore: modules have registered their teardown through .fini_array since a9cb28cd23. The condition is therefore always false and every rmmod()/dlclose() leaks the exports array together with the strdup-ed symbol names. Call libelf_freesymtab() unconditionally, and clear the exports pointers next to it instead of under a vestigial procfs guard that dates back to the removed module initializer field. Assisted-by: OpenAI Codex Signed-off-by: yushuailong --- libs/libc/elf/elf_remove.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libs/libc/elf/elf_remove.c b/libs/libc/elf/elf_remove.c index fd004f0584e..8393e6b1f83 100644 --- a/libs/libc/elf/elf_remove.c +++ b/libs/libc/elf/elf_remove.c @@ -81,18 +81,20 @@ int libelf_uninit(FAR struct module_s *modp) return ret; } - libelf_freesymtab(modp); - /* Nullify so that the uninitializer cannot be called again */ modp->modinfo.uninitializer = NULL; -#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE) modp->modinfo.arg = NULL; - modp->modinfo.exports = NULL; - modp->modinfo.nexports = 0; -#endif } + /* Free the symbol table that the module exports. It is built for + * every loaded module, whether or not it has an uninitializer. + */ + + libelf_freesymtab(modp); + modp->modinfo.exports = NULL; + modp->modinfo.nexports = 0; + /* Release resources held by the module */ if (modp->textalloc != NULL || modp->dataalloc != NULL)