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 <yyyusl@qq.com>
This commit is contained in:
yushuailong 2026-09-16 15:51:46 +08:00 • committed by Xiang Xiao
parent a9683532b5
commit 166f17746c

View file

@ -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)