This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 47dfaad8057 sched/tls: Free the pthread_atfork() entries in the heap
of the process.
47dfaad8057 is described below
commit 47dfaad80574edb11df710522029a4b11d03534b
Author: Marco Casaroli <[email protected]>
AuthorDate: Thu Oct 22 09:21:51 2026 +0200
sched/tls: Free the pthread_atfork() entries in the heap of the process.
pthread_atfork() allocates its entries with lib_malloc() in the heap of
the calling process. task_uninit_info() freed them with lib_free(),
which is kmm_free() in the kernel. In a protected or kernel build with
CONFIG_PTHREAD_ATFORK, the exit of a process that called
pthread_atfork() then gave a user pointer to the kernel heap: an
assertion in kmm_free() with CONFIG_DEBUG_ASSERTIONS, else a corrupt
kernel heap.
Free the entries with group_free(), which selects the heap of the
group. In a kernel build, do not free the entries of an unprivileged
group: they lie in its user heap, which goes away with its address
environment (as task_uninit_stream() does for the streams).
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <[email protected]>
---
sched/tls/task_uninitinfo.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/sched/tls/task_uninitinfo.c b/sched/tls/task_uninitinfo.c
index 6212cce8551..b83f2f2f151 100644
--- a/sched/tls/task_uninitinfo.c
+++ b/sched/tls/task_uninitinfo.c
@@ -136,7 +136,21 @@ void task_uninit_info(FAR struct task_group_s *group)
entry = list_first_entry(list,
struct pthread_atfork_s, node);
list_delete_init(&entry->node);
- lib_free(entry);
+
+ /* pthread_atfork() allocated the entry in the heap of the process:
+ * the user heap, unless the process is privileged.
+ */
+
+#ifdef CONFIG_BUILD_KERNEL
+ /* The user heap of an unprivileged group goes away with its address
+ * environment.
+ */
+
+ if ((group->tg_flags & GROUP_FLAG_PRIVILEGED) != 0)
+#endif
+ {
+ group_free(group, entry);
+ }
}
#endif