From 92f8396b0c8e4f146563b87f46137484cfb36e31 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 11 Jul 2012 23:36:46 -0400 Subject: fix potential race condition in detached threads after the thread unmaps its own stack/thread structure, the kernel, performing child tid clear and futex wake, could clobber a new mapping made at the same location as the just-removed thread's tid field. disable kernel clearing of child tid to prevent this. --- src/thread/pthread_create.c | 10 ++++++++-- src/thread/pthread_detach.c | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c index 48290d35..ae2f9e4e 100644 --- a/src/thread/pthread_create.c +++ b/src/thread/pthread_create.c @@ -36,6 +36,8 @@ void pthread_exit(void *result) if (!n) exit(0); if (self->detached && self->map_base) { + if (self->detached == 2) + __syscall(SYS_set_tid_address, 0); __syscall(SYS_rt_sigprocmask, SIG_BLOCK, (uint64_t[]){-1},0,8); __unmapself(self->map_base, self->map_size); } @@ -87,6 +89,7 @@ int pthread_create(pthread_t *res, const pthread_attr_t *attr, void *(*entry)(vo size_t guard = DEFAULT_GUARD_SIZE; struct pthread *self = pthread_self(), *new; unsigned char *map, *stack, *tsd; + unsigned flags = 0x7d8f00; if (!self) return ENOSYS; if (!libc.threaded) { @@ -121,7 +124,10 @@ int pthread_create(pthread_t *res, const pthread_attr_t *attr, void *(*entry)(vo new->start_arg = arg; new->self = new; new->tsd = (void *)tsd; - if (attr) new->detached = attr->_a_detach; + if (attr && attr->_a_detach) { + new->detached = 1; + flags -= 0x200000; + } new->unblock_cancel = self->cancel; new->canary = self->canary ^ (uintptr_t)&new; stack = (void *)new; @@ -129,7 +135,7 @@ int pthread_create(pthread_t *res, const pthread_attr_t *attr, void *(*entry)(vo __synccall_lock(); a_inc(&libc.threads_minus_1); - ret = __clone(start, stack, 0x7d8f00, new, &new->tid, new, &new->tid); + ret = __clone(start, stack, flags, new, &new->tid, new, &new->tid); __synccall_unlock(); diff --git a/src/thread/pthread_detach.c b/src/thread/pthread_detach.c index 8ef03d51..e8032398 100644 --- a/src/thread/pthread_detach.c +++ b/src/thread/pthread_detach.c @@ -5,7 +5,7 @@ int pthread_detach(pthread_t t) /* Cannot detach a thread that's already exiting */ if (a_swap(&t->exitlock, 1)) return pthread_join(t, 0); - t->detached = 1; - t->exitlock = 0; + t->detached = 2; + a_store(&t->exitlock, 0); return 0; } -- cgit v1.2.1