diff options
Diffstat (limited to 'toolchain/musl/patches/500-0001-reorder-thread-list-unlink-in-pthread_exit-after-all.patch')
-rw-r--r-- | toolchain/musl/patches/500-0001-reorder-thread-list-unlink-in-pthread_exit-after-all.patch | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/toolchain/musl/patches/500-0001-reorder-thread-list-unlink-in-pthread_exit-after-all.patch b/toolchain/musl/patches/500-0001-reorder-thread-list-unlink-in-pthread_exit-after-all.patch new file mode 100644 index 0000000000..d47f2f4108 --- /dev/null +++ b/toolchain/musl/patches/500-0001-reorder-thread-list-unlink-in-pthread_exit-after-all.patch @@ -0,0 +1,51 @@ +From 4d5aa20a94a2d3fae3e69289dc23ecafbd0c16c4 Mon Sep 17 00:00:00 2001 +From: Rich Felker <dalias@aerifal.cx> +Date: Fri, 22 May 2020 17:35:14 -0400 +Subject: [PATCH 1/4] reorder thread list unlink in pthread_exit after all + locks + +since the backend for LOCK() skips locking if single-threaded, it's +unsafe to make the process appear single-threaded before the last use +of lock. + +this fixes potential unsynchronized access to a linked list via +__dl_thread_cleanup. +--- + src/thread/pthread_create.c | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +--- a/src/thread/pthread_create.c ++++ b/src/thread/pthread_create.c +@@ -90,14 +90,7 @@ _Noreturn void __pthread_exit(void *resu + exit(0); + } + +- /* At this point we are committed to thread termination. Unlink +- * the thread from the list. This change will not be visible +- * until the lock is released, which only happens after SYS_exit +- * has been called, via the exit futex address pointing at the lock. */ +- libc.threads_minus_1--; +- self->next->prev = self->prev; +- self->prev->next = self->next; +- self->prev = self->next = self; ++ /* At this point we are committed to thread termination. */ + + /* Process robust list in userspace to handle non-pshared mutexes + * and the detached thread case where the robust list head will +@@ -121,6 +114,16 @@ _Noreturn void __pthread_exit(void *resu + __do_orphaned_stdio_locks(); + __dl_thread_cleanup(); + ++ /* Last, unlink thread from the list. This change will not be visible ++ * until the lock is released, which only happens after SYS_exit ++ * has been called, via the exit futex address pointing at the lock. ++ * This needs to happen after any possible calls to LOCK() that might ++ * skip locking if libc.threads_minus_1 is zero. */ ++ libc.threads_minus_1--; ++ self->next->prev = self->prev; ++ self->prev->next = self->next; ++ self->prev = self->next = self; ++ + /* This atomic potentially competes with a concurrent pthread_detach + * call; the loser is responsible for freeing thread resources. */ + int state = a_cas(&self->detach_state, DT_JOINABLE, DT_EXITING); |