git: 49e0c6270c73 - main - libthr: fix the race between pthread_getname_np() and thread exit
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 30 Oct 2026 13:52:35 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=49e0c6270c73f1570efc67028004db9da56da2d1
commit 49e0c6270c73f1570efc67028004db9da56da2d1
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-10-19 21:59:52 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-10-30 13:51:02 +0000
libthr: fix the race between pthread_getname_np() and thread exit
The exiting thread frees the thread name in exit_thread() without
holding the thread lock. This makes it possible for a thread doing
pthread_getname_np() to observe the non-null thread->name and try to
copy its content, accessing the memory after free.
Set the thread->name to NULL under the thread lock. Note that other
thread might still set the exiting thread name, until the PS_DEAD state
is assigned. Since code should not call free() after
_malloc_thread_cleanup(), re-check thread->name in _thr_free().
Reviewed by: aokblast, markj
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D60838
---
lib/libthr/thread/thr_exit.c | 2 ++
lib/libthr/thread/thr_list.c | 4 ++++
2 files changed, 6 insertions(+)
diff --git a/lib/libthr/thread/thr_exit.c b/lib/libthr/thread/thr_exit.c
index 5a9dcf99fa21..4c9692ccf1a5 100644
--- a/lib/libthr/thread/thr_exit.c
+++ b/lib/libthr/thread/thr_exit.c
@@ -278,8 +278,10 @@ exit_thread(void)
{
struct pthread *curthread = _get_curthread();
+ THR_LOCK(curthread);
free(curthread->name);
curthread->name = NULL;
+ THR_UNLOCK(curthread);
/* Check if there is thread specific data: */
if (curthread->specific != NULL) {
diff --git a/lib/libthr/thread/thr_list.c b/lib/libthr/thread/thr_list.c
index cbf16179f619..62fb6e3a3b45 100644
--- a/lib/libthr/thread/thr_list.c
+++ b/lib/libthr/thread/thr_list.c
@@ -203,6 +203,10 @@ _thr_free(struct pthread *curthread, struct pthread *thread)
_tcb_dtor(thread->tcb);
}
thread->tcb = NULL;
+ if (thread->name != NULL) {
+ free(thread->name);
+ thread->name = NULL;
+ }
if ((curthread == NULL) || (free_thread_count >= MAX_CACHED_THREADS)) {
thr_destroy(curthread, thread);
atomic_add_int(&total_threads, -1);