merge in jb-mr2-release history after reset to master
diff --git a/libc/Android.mk b/libc/Android.mk
index 8ae1419..c0b3b68 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -182,7 +182,6 @@
bionic/md5.c \
bionic/memchr.c \
bionic/memmem.c \
- bionic/memmove_words.c \
bionic/memrchr.c \
bionic/memswap.c \
bionic/mmap.c \
@@ -725,8 +724,8 @@
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := bionic/ssp.cpp
-LOCAL_CFLAGS := $(libc_common_cflags) -fno-stack-protector
+LOCAL_SRC_FILES := bionic/__stack_chk_fail.cpp bionic/__stack_chk_guard.cpp
+LOCAL_CFLAGS := $(libc_common_cflags) -fno-stack-protector -Werror
LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_MODULE := libbionic_ssp
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
diff --git a/libc/arch-arm/bionic/clone.S b/libc/arch-arm/bionic/clone.S
index 39bd79d..13bc7d7 100644
--- a/libc/arch-arm/bionic/clone.S
+++ b/libc/arch-arm/bionic/clone.S
@@ -29,10 +29,10 @@
#include <machine/asm.h>
#include <sys/linux-syscalls.h>
-// int __pthread_clone(int (*fn)(void*), void* child_stack, int flags, void* arg);
+// int __pthread_clone(void* (*fn)(void*), void* child_stack, int flags, void* arg);
ENTRY(__pthread_clone)
# Copy the args onto the new stack.
- stmdb r1!, {r0, r3}
+ stmdb r1!, {r0, r3}
# The sys_clone system call only takes two arguments: 'flags' and 'child_stack'.
# 'child_stack' is already in r1, but we need to move 'flags' into position.
diff --git a/libc/arch-mips/bionic/clone.S b/libc/arch-mips/bionic/clone.S
index 30fef8d..007e909 100644
--- a/libc/arch-mips/bionic/clone.S
+++ b/libc/arch-mips/bionic/clone.S
@@ -28,15 +28,15 @@
#include <linux/sched.h>
#include <sys/linux-syscalls.h>
#include <linux/errno.h>
-
+
.text
.type __pthread_clone, @function
.global __pthread_clone
.align 4
.ent __pthread_clone
-
+
/*
- * int __pthread_clone(int (*fn)(void*), void *child_stack,
+ * int __pthread_clone(void* (*fn)(void*), void *child_stack,
* int flags, void *arg);
*/
@@ -69,7 +69,7 @@
bnez $a3,.L__error
beqz $v0,.L__thread_start
-
+
j $ra
.L__thread_start:
@@ -77,7 +77,7 @@
lw $a1,4($sp) # arg
addu $a2,$sp,16 # tls
- # void __thread_entry(int (*func)(void*), void *arg, void *tls)
+ # void __thread_entry(void* (*func)(void*), void *arg, void *tls)
la $t9, __thread_entry
j $t9
@@ -125,7 +125,7 @@
bnez $a3,.L__error_bc
beqz $v0,.L__thread_start_bc
-
+
j $ra
.L__thread_start_bc:
@@ -142,4 +142,3 @@
j $t9
.end __bionic_clone
-
diff --git a/libc/arch-x86/bionic/clone.S b/libc/arch-x86/bionic/clone.S
index e7bc3ee..80e3c75 100644
--- a/libc/arch-x86/bionic/clone.S
+++ b/libc/arch-x86/bionic/clone.S
@@ -1,7 +1,7 @@
#include <machine/asm.h>
#include <sys/linux-syscalls.h>
-// int __pthread_clone(int (*fn)(void*), void* tls, int flags, void* arg);
+// int __pthread_clone(void* (*fn)(void*), void* tls, int flags, void* arg);
ENTRY(__pthread_clone)
pushl %ebx
pushl %ecx
diff --git a/libc/bionic/__stack_chk_fail.cpp b/libc/bionic/__stack_chk_fail.cpp
new file mode 100644
index 0000000..cae66b1
--- /dev/null
+++ b/libc/bionic/__stack_chk_fail.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+
+#include "bionic_ssp.h"
+#include "debug_format.h"
+#include "logd.h"
+
+void __stack_chk_fail() {
+ __libc_format_log(ANDROID_LOG_FATAL, "libc", "stack corruption detected");
+ abort();
+}
diff --git a/libc/bionic/__stack_chk_guard.cpp b/libc/bionic/__stack_chk_guard.cpp
new file mode 100644
index 0000000..a695caf
--- /dev/null
+++ b/libc/bionic/__stack_chk_guard.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "bionic_ssp.h"
+
+#include <sys/auxv.h>
+
+uintptr_t __stack_chk_guard = 0;
+
+static void __attribute__((constructor)) __init_stack_check_guard() {
+ // AT_RANDOM is a pointer to 16 bytes of randomness on the stack.
+ __stack_chk_guard = *reinterpret_cast<uintptr_t*>(getauxval(AT_RANDOM));
+}
diff --git a/libc/bionic/bionic_clone.c b/libc/bionic/bionic_clone.c
index 187b60d..8412057 100644
--- a/libc/bionic/bionic_clone.c
+++ b/libc/bionic/bionic_clone.c
@@ -58,9 +58,8 @@
int *parent_tidptr = NULL;
void *new_tls = NULL;
int *child_tidptr = NULL;
- int ret;
- /* extract optional parameters - they are cummulative */
+ /* extract optional parameters - they are cumulative. */
va_start(args, arg);
if (flags & (CLONE_PARENT_SETTID|CLONE_SETTLS|CLONE_CHILD_SETTID)) {
parent_tidptr = va_arg(args, int*);
@@ -73,6 +72,5 @@
}
va_end(args);
- ret = __bionic_clone(flags, child_stack, parent_tidptr, new_tls, child_tidptr, fn, arg);
- return ret;
+ return __bionic_clone(flags, child_stack, parent_tidptr, new_tls, child_tidptr, fn, arg);
}
diff --git a/libc/bionic/fork.c b/libc/bionic/fork.c
index 2d5a10a..d83c535 100644
--- a/libc/bionic/fork.c
+++ b/libc/bionic/fork.c
@@ -9,7 +9,7 @@
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
+ * the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
@@ -19,7 +19,7 @@
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
@@ -49,8 +49,8 @@
__timer_table_start_stop(0);
__bionic_atfork_run_parent();
} else {
- /* Adjusting the kernel id after a fork */
- (void)__pthread_settid(pthread_self(), gettid());
+ // Fix the tid in the pthread_internal_t struct after a fork.
+ __pthread_settid(pthread_self(), gettid());
/*
* Newly created process must update cpu accounting.
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index 266d6fa..6038056 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -73,14 +73,15 @@
unsigned stack_size = 128 * 1024;
unsigned stack_bottom = stack_top - stack_size;
+ static void* tls[BIONIC_TLS_SLOTS];
static pthread_internal_t thread;
+ thread.tid = gettid();
+ thread.tls = tls;
pthread_attr_init(&thread.attr);
pthread_attr_setstack(&thread.attr, (void*) stack_bottom, stack_size);
- _init_thread(&thread, gettid(), false);
-
- static void* tls_area[BIONIC_TLS_SLOTS];
- __init_tls(tls_area, &thread);
- tls_area[TLS_SLOT_BIONIC_PREINIT] = &args;
+ _init_thread(&thread, false);
+ __init_tls(&thread);
+ tls[TLS_SLOT_BIONIC_PREINIT] = &args;
}
void __libc_init_common(KernelArgumentBlock& args) {
diff --git a/libc/bionic/memmove_words.c b/libc/bionic/memmove_words.c
deleted file mode 100644
index 26df7fa..0000000
--- a/libc/bionic/memmove_words.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <assert.h>
-
-/*
- * Works like memmove(), except:
- * - if all arguments are at least 32-bit aligned, we guarantee that we
- * will use operations that preserve atomicity of 32-bit values
- * - if not, we guarantee atomicity of 16-bit values
- *
- * If all three arguments are not at least 16-bit aligned, the behavior
- * of this function is undefined. (We could remove this restriction by
- * testing for unaligned values and punting to memmove(), but that's
- * not currently useful.)
- *
- * TODO: add loop for 64-bit alignment
- * TODO: use __builtin_prefetch
- * TODO: write an ARM-optimized version
- */
-void _memmove_words(void* dest, const void* src, size_t n)
-{
- assert((((uintptr_t) dest | (uintptr_t) src | n) & 0x01) == 0);
-
- char* d = (char*) dest;
- const char* s = (const char*) src;
- size_t copyCount;
-
- /*
- * If the source and destination pointers are the same, this is
- * an expensive no-op. Testing for an empty move now allows us
- * to skip a check later.
- */
- if (n == 0 || d == s)
- return;
-
- /*
- * Determine if the source and destination buffers will overlap if
- * we copy data forward (i.e. *dest++ = *src++).
- *
- * It's okay if the destination buffer starts before the source and
- * there is some overlap, because the reader is always ahead of the
- * writer.
- */
- if (__builtin_expect((d < s) || ((size_t)(d - s) >= n), 1)) {
- /*
- * Copy forward. We prefer 32-bit loads and stores even for 16-bit
- * data, so sort that out.
- */
- if ((((uintptr_t) d | (uintptr_t) s) & 0x03) != 0) {
- /*
- * Not 32-bit aligned. Two possibilities:
- * (1) Congruent, we can align to 32-bit by copying one 16-bit val
- * (2) Non-congruent, we can do one of:
- * a. copy whole buffer as a series of 16-bit values
- * b. load/store 32 bits, using shifts to ensure alignment
- * c. just copy the as 32-bit values and assume the CPU
- * will do a reasonable job
- *
- * We're currently using (a), which is suboptimal.
- */
- if ((((uintptr_t) d ^ (uintptr_t) s) & 0x03) != 0) {
- copyCount = n;
- } else {
- copyCount = 2;
- }
- n -= copyCount;
- copyCount /= sizeof(uint16_t);
-
- while (copyCount--) {
- *(uint16_t*)d = *(uint16_t*)s;
- d += sizeof(uint16_t);
- s += sizeof(uint16_t);
- }
- }
-
- /*
- * Copy 32-bit aligned words.
- */
- copyCount = n / sizeof(uint32_t);
- while (copyCount--) {
- *(uint32_t*)d = *(uint32_t*)s;
- d += sizeof(uint32_t);
- s += sizeof(uint32_t);
- }
-
- /*
- * Check for leftovers. Either we finished exactly, or we have
- * one remaining 16-bit chunk.
- */
- if ((n & 0x02) != 0) {
- *(uint16_t*)d = *(uint16_t*)s;
- }
- } else {
- /*
- * Copy backward, starting at the end.
- */
- d += n;
- s += n;
-
- if ((((uintptr_t) d | (uintptr_t) s) & 0x03) != 0) {
- /* try for 32-bit alignment */
- if ((((uintptr_t) d ^ (uintptr_t) s) & 0x03) != 0) {
- copyCount = n;
- } else {
- copyCount = 2;
- }
- n -= copyCount;
- copyCount /= sizeof(uint16_t);
-
- while (copyCount--) {
- d -= sizeof(uint16_t);
- s -= sizeof(uint16_t);
- *(uint16_t*)d = *(uint16_t*)s;
- }
- }
-
- /* copy 32-bit aligned words */
- copyCount = n / sizeof(uint32_t);
- while (copyCount--) {
- d -= sizeof(uint32_t);
- s -= sizeof(uint32_t);
- *(uint32_t*)d = *(uint32_t*)s;
- }
-
- /* copy leftovers */
- if ((n & 0x02) != 0) {
- d -= sizeof(uint16_t);
- s -= sizeof(uint16_t);
- *(uint16_t*)d = *(uint16_t*)s;
- }
- }
-}
diff --git a/libc/bionic/pthread-rwlocks.c b/libc/bionic/pthread-rwlocks.c
index ca3e95c..deee577 100644
--- a/libc/bionic/pthread-rwlocks.c
+++ b/libc/bionic/pthread-rwlocks.c
@@ -42,7 +42,7 @@
* - trying to get the read-lock while there is a writer blocks
* - a single thread can acquire the lock multiple times in the same mode
*
- * - Posix states that behaviour is undefined it a thread tries to acquire
+ * - Posix states that behavior is undefined it a thread tries to acquire
* the lock in two distinct modes (e.g. write after read, or read after write).
*
* - This implementation tries to avoid writer starvation by making the readers
@@ -61,12 +61,6 @@
extern pthread_internal_t* __get_thread(void);
-/* Return a global kernel ID for the current thread */
-static int __get_thread_id(void)
-{
- return __get_thread()->kernel_id;
-}
-
int pthread_rwlockattr_init(pthread_rwlockattr_t *attr)
{
if (!attr)
@@ -150,8 +144,6 @@
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
{
- int ret;
-
if (rwlock == NULL)
return EINVAL;
@@ -164,7 +156,7 @@
}
/* Returns TRUE iff we can acquire a read lock. */
-static __inline__ int read_precondition(pthread_rwlock_t *rwlock, int thread_id)
+static __inline__ int read_precondition(pthread_rwlock_t* rwlock, int tid)
{
/* We can't have the lock if any writer is waiting for it (writer bias).
* This tries to avoid starvation when there are multiple readers racing.
@@ -174,7 +166,7 @@
/* We can have the lock if there is no writer, or if we write-own it */
/* The second test avoids a self-dead lock in case of buggy code. */
- if (rwlock->writerThreadId == 0 || rwlock->writerThreadId == thread_id)
+ if (rwlock->writerThreadId == 0 || rwlock->writerThreadId == tid)
return 1;
/* Otherwise, we can't have it */
@@ -182,14 +174,14 @@
}
/* returns TRUE iff we can acquire a write lock. */
-static __inline__ int write_precondition(pthread_rwlock_t *rwlock, int thread_id)
+static __inline__ int write_precondition(pthread_rwlock_t* rwlock, int tid)
{
/* We can get the lock if nobody has it */
if (rwlock->numLocks == 0)
return 1;
/* Or if we already own it */
- if (rwlock->writerThreadId == thread_id)
+ if (rwlock->writerThreadId == tid)
return 1;
/* Otherwise, not */
@@ -220,7 +212,7 @@
return EINVAL;
pthread_mutex_lock(&rwlock->lock);
- if (__unlikely(!read_precondition(rwlock, __get_thread_id())))
+ if (__unlikely(!read_precondition(rwlock, __get_thread()->tid)))
ret = EBUSY;
else
rwlock->numLocks ++;
@@ -231,18 +223,18 @@
int pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, const struct timespec *abs_timeout)
{
- int thread_id, ret = 0;
+ int ret = 0;
if (rwlock == NULL)
return EINVAL;
pthread_mutex_lock(&rwlock->lock);
- thread_id = __get_thread_id();
- if (__unlikely(!read_precondition(rwlock, thread_id))) {
+ int tid = __get_thread()->tid;
+ if (__unlikely(!read_precondition(rwlock, tid))) {
rwlock->pendingReaders += 1;
do {
ret = pthread_cond_timedwait(&rwlock->cond, &rwlock->lock, abs_timeout);
- } while (ret == 0 && !read_precondition(rwlock, thread_id));
+ } while (ret == 0 && !read_precondition(rwlock, tid));
rwlock->pendingReaders -= 1;
if (ret != 0)
goto EXIT;
@@ -261,18 +253,18 @@
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
{
- int thread_id, ret = 0;
+ int ret = 0;
if (rwlock == NULL)
return EINVAL;
pthread_mutex_lock(&rwlock->lock);
- thread_id = __get_thread_id();
- if (__unlikely(!write_precondition(rwlock, thread_id))) {
+ int tid = __get_thread()->tid;
+ if (__unlikely(!write_precondition(rwlock, tid))) {
ret = EBUSY;
} else {
rwlock->numLocks ++;
- rwlock->writerThreadId = thread_id;
+ rwlock->writerThreadId = tid;
}
pthread_mutex_unlock(&rwlock->lock);
return ret;
@@ -280,14 +272,14 @@
int pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock, const struct timespec *abs_timeout)
{
- int thread_id, ret = 0;
+ int ret = 0;
if (rwlock == NULL)
return EINVAL;
pthread_mutex_lock(&rwlock->lock);
- thread_id = __get_thread_id();
- if (__unlikely(!write_precondition(rwlock, thread_id))) {
+ int tid = __get_thread()->tid;
+ if (__unlikely(!write_precondition(rwlock, tid))) {
/* If we can't read yet, wait until the rwlock is unlocked
* and try again. Increment pendingReaders to get the
* cond broadcast when that happens.
@@ -295,13 +287,13 @@
rwlock->pendingWriters += 1;
do {
ret = pthread_cond_timedwait(&rwlock->cond, &rwlock->lock, abs_timeout);
- } while (ret == 0 && !write_precondition(rwlock, thread_id));
+ } while (ret == 0 && !write_precondition(rwlock, tid));
rwlock->pendingWriters -= 1;
if (ret != 0)
goto EXIT;
}
rwlock->numLocks ++;
- rwlock->writerThreadId = thread_id;
+ rwlock->writerThreadId = tid;
EXIT:
pthread_mutex_unlock(&rwlock->lock);
return ret;
@@ -332,7 +324,7 @@
* must be ourselves.
*/
else {
- if (rwlock->writerThreadId != __get_thread_id()) {
+ if (rwlock->writerThreadId != __get_thread()->tid) {
ret = EPERM;
goto EXIT;
}
diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c
index d5f8187..5848215 100644
--- a/libc/bionic/pthread.c
+++ b/libc/bionic/pthread.c
@@ -36,7 +36,6 @@
#include "bionic_atomic_inline.h"
#include "bionic_futex.h"
#include "bionic_pthread.h"
-#include "bionic_ssp.h"
#include "bionic_tls.h"
#include "pthread_internal.h"
#include "thread_private.h"
@@ -314,9 +313,9 @@
int old_errno = errno;
pthread_internal_t * thread = (pthread_internal_t *)thid;
- int err = sched_getparam(thread->kernel_id, param);
+ int err = sched_getparam(thread->tid, param);
if (!err) {
- *policy = sched_getscheduler(thread->kernel_id);
+ *policy = sched_getscheduler(thread->tid);
} else {
err = errno;
errno = old_errno;
@@ -331,7 +330,7 @@
int old_errno = errno;
int ret;
- ret = sched_setscheduler(thread->kernel_id, policy, param);
+ ret = sched_setscheduler(thread->tid, policy, param);
if (ret < 0) {
ret = errno;
errno = old_errno;
@@ -343,7 +342,7 @@
/* a mutex is implemented as a 32-bit integer holding the following fields
*
* bits: name description
- * 31-16 tid owner thread's kernel id (recursive and errorcheck only)
+ * 31-16 tid owner thread's tid (recursive and errorcheck only)
* 15-14 type mutex type
* 13 shared process-shared flag
* 12-2 counter counter of recursive mutexes
@@ -453,8 +452,8 @@
/* Mutex owner field:
*
* This is only used for recursive and errorcheck mutexes. It holds the
- * kernel TID of the owning thread. Note that this works because the Linux
- * kernel _only_ uses 16-bit values for thread ids.
+ * tid of the owning thread. Note that this works because the Linux
+ * kernel _only_ uses 16-bit values for tids.
*
* More specifically, it will wrap to 10000 when it reaches over 32768 for
* application processes. You can check this by running the following inside
@@ -784,7 +783,7 @@
}
/* Do we already own this recursive or error-check mutex ? */
- tid = __get_thread()->kernel_id;
+ tid = __get_thread()->tid;
if ( tid == MUTEX_OWNER_FROM_BITS(mvalue) )
return _recursive_increment(mutex, mvalue, mtype);
@@ -878,7 +877,7 @@
}
/* Do we already own this recursive or error-check mutex ? */
- tid = __get_thread()->kernel_id;
+ tid = __get_thread()->tid;
if ( tid != MUTEX_OWNER_FROM_BITS(mvalue) )
return EPERM;
@@ -952,7 +951,7 @@
}
/* Do we already own this recursive or error-check mutex ? */
- tid = __get_thread()->kernel_id;
+ tid = __get_thread()->tid;
if ( tid == MUTEX_OWNER_FROM_BITS(mvalue) )
return _recursive_increment(mutex, mvalue, mtype);
@@ -1061,7 +1060,7 @@
}
/* Do we already own this recursive or error-check mutex ? */
- tid = __get_thread()->kernel_id;
+ tid = __get_thread()->tid;
if ( tid == MUTEX_OWNER_FROM_BITS(mvalue) )
return _recursive_increment(mutex, mvalue, mtype);
@@ -1380,7 +1379,7 @@
int old_errno = errno;
pthread_internal_t * thread = (pthread_internal_t *)tid;
- ret = tgkill(getpid(), thread->kernel_id, sig);
+ ret = tgkill(getpid(), thread->tid, sig);
if (ret < 0) {
ret = errno;
errno = old_errno;
@@ -1398,7 +1397,7 @@
if (!thread)
return ESRCH;
- *clockid = CLOCK_THREAD_CPUTIME_ID | (thread->kernel_id << CLOCK_IDTYPE_BITS);
+ *clockid = CLOCK_THREAD_CPUTIME_ID | (thread->tid << CLOCK_IDTYPE_BITS);
return 0;
}
@@ -1475,25 +1474,18 @@
return 0;
}
-/* Return the kernel thread ID for a pthread.
- * This is only defined for implementations where pthread <-> kernel is 1:1, which this is.
- * Not the same as pthread_getthreadid_np, which is commonly defined to be opaque.
- * Internal, not an NDK API.
- */
-
-pid_t __pthread_gettid(pthread_t thid)
-{
- pthread_internal_t* thread = (pthread_internal_t*)thid;
- return thread->kernel_id;
+pid_t __pthread_gettid(pthread_t thid) {
+ pthread_internal_t* thread = (pthread_internal_t*) thid;
+ return thread->tid;
}
-int __pthread_settid(pthread_t thid, pid_t tid)
-{
- if (thid == 0)
- return EINVAL;
+int __pthread_settid(pthread_t thid, pid_t tid) {
+ if (thid == 0) {
+ return EINVAL;
+ }
- pthread_internal_t* thread = (pthread_internal_t*)thid;
- thread->kernel_id = tid;
+ pthread_internal_t* thread = (pthread_internal_t*) thid;
+ thread->tid = tid;
- return 0;
+ return 0;
}
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 6e4fe45..368c46d 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -41,7 +41,7 @@
#include "private/ErrnoRestorer.h"
#include "private/ScopedPthreadMutexLocker.h"
-extern "C" int __pthread_clone(int (*fn)(void*), void* child_stack, int flags, void* arg);
+extern "C" int __pthread_clone(void* (*fn)(void*), void* child_stack, int flags, void* arg);
#ifdef __i386__
#define ATTRIBUTES __attribute__((noinline)) __attribute__((fastcall))
@@ -57,25 +57,23 @@
static pthread_mutex_t gDebuggerNotificationLock = PTHREAD_MUTEX_INITIALIZER;
-void __init_tls(void** tls, void* thread) {
- ((pthread_internal_t*) thread)->tls = tls;
-
+void __init_tls(pthread_internal_t* thread) {
// Zero-initialize all the slots.
for (size_t i = 0; i < BIONIC_TLS_SLOTS; ++i) {
- tls[i] = NULL;
+ thread->tls[i] = NULL;
}
// Slot 0 must point to itself. The x86 Linux kernel reads the TLS from %fs:0.
- tls[TLS_SLOT_SELF] = tls;
- tls[TLS_SLOT_THREAD_ID] = thread;
+ thread->tls[TLS_SLOT_SELF] = thread->tls;
+ thread->tls[TLS_SLOT_THREAD_ID] = thread;
// GCC looks in the TLS for the stack guard on x86, so copy it there from our global.
- tls[TLS_SLOT_STACK_GUARD] = (void*) __stack_chk_guard;
+ thread->tls[TLS_SLOT_STACK_GUARD] = (void*) __stack_chk_guard;
- __set_tls((void*) tls);
+ __set_tls(thread->tls);
}
// This trampoline is called from the assembly _pthread_clone() function.
-extern "C" void __thread_entry(int (*func)(void*), void *arg, void **tls) {
+extern "C" void __thread_entry(void* (*func)(void*), void* arg, void** tls) {
// Wait for our creating thread to release us. This lets it have time to
// notify gdb about this thread before we start doing anything.
// This also provides the memory barrier needed to ensure that all memory
@@ -85,27 +83,26 @@
pthread_mutex_destroy(start_mutex);
pthread_internal_t* thread = (pthread_internal_t*) tls[TLS_SLOT_THREAD_ID];
- __init_tls(tls, thread);
+ thread->tls = tls;
+ __init_tls(thread);
if ((thread->internal_flags & kPthreadInitFailed) != 0) {
pthread_exit(NULL);
}
- int result = func(arg);
- pthread_exit((void*) result);
+ void* result = func(arg);
+ pthread_exit(result);
}
__LIBC_ABI_PRIVATE__
-int _init_thread(pthread_internal_t* thread, pid_t kernel_id, bool add_to_thread_list) {
+int _init_thread(pthread_internal_t* thread, bool add_to_thread_list) {
int error = 0;
- thread->kernel_id = kernel_id;
-
// Set the scheduling policy/priority of the thread.
if (thread->attr.sched_policy != SCHED_NORMAL) {
struct sched_param param;
param.sched_priority = thread->attr.sched_priority;
- if (sched_setscheduler(kernel_id, thread->attr.sched_policy, ¶m) == -1) {
+ if (sched_setscheduler(thread->tid, thread->attr.sched_policy, ¶m) == -1) {
// For backwards compatibility reasons, we just warn about failures here.
// error = errno;
const char* msg = "pthread_create sched_setscheduler call failed: %s\n";
@@ -198,9 +195,9 @@
tls[TLS_SLOT_THREAD_ID] = thread;
- int flags = CLONE_FILES | CLONE_FS | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM | CLONE_DETACHED;
- int tid = __pthread_clone((int(*)(void*))start_routine, tls, flags, arg);
+ int flags = CLONE_FILES | CLONE_FS | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM;
+ int tid = __pthread_clone(start_routine, tls, flags, arg);
if (tid < 0) {
int clone_errno = errno;
if ((thread->attr.flags & PTHREAD_ATTR_FLAG_USER_STACK) == 0) {
@@ -210,7 +207,9 @@
return clone_errno;
}
- int init_errno = _init_thread(thread, tid, true);
+ thread->tid = tid;
+
+ int init_errno = _init_thread(thread, true);
if (init_errno != 0) {
// Mark the thread detached and let its __thread_entry run to
// completion. (It'll just exit immediately, cleaning up its resources.)
@@ -222,7 +221,7 @@
// Notify any debuggers about the new thread.
{
ScopedPthreadMutexLocker debugger_locker(&gDebuggerNotificationLock);
- _thread_created_hook(tid);
+ _thread_created_hook(thread->tid);
}
// Publish the pthread_t and let the thread run.
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index a17c37d..9122a74 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -38,7 +38,7 @@
struct pthread_internal_t* next;
struct pthread_internal_t* prev;
pthread_attr_t attr;
- pid_t kernel_id;
+ pid_t tid;
bool allocated_on_heap;
pthread_cond_t join_cond;
int join_count;
@@ -55,7 +55,8 @@
char dlerror_buffer[__BIONIC_DLERROR_BUFFER_SIZE];
} pthread_internal_t;
-int _init_thread(pthread_internal_t* thread, pid_t kernel_id, bool add_to_thread_list);
+int _init_thread(pthread_internal_t* thread, bool add_to_thread_list);
+void __init_tls(pthread_internal_t* thread);
void _pthread_internal_add( pthread_internal_t* thread );
pthread_internal_t* __get_thread(void);
diff --git a/libc/bionic/pthread_setname_np.cpp b/libc/bionic/pthread_setname_np.cpp
index 88b86ec..6162aea 100644
--- a/libc/bionic/pthread_setname_np.cpp
+++ b/libc/bionic/pthread_setname_np.cpp
@@ -40,7 +40,7 @@
// This value is not exported by kernel headers.
#define MAX_TASK_COMM_LEN 16
-#define TASK_COMM_FMT "/proc/self/task/%u/comm"
+#define TASK_COMM_FMT "/proc/self/task/%d/comm"
int pthread_setname_np(pthread_t thread, const char* thread_name) {
ErrnoRestorer errno_restorer;
@@ -56,14 +56,14 @@
// Changing our own name is an easy special case.
if (thread == pthread_self()) {
- return prctl(PR_SET_NAME, (unsigned long)thread_name, 0, 0, 0) ? errno : 0;
+ return prctl(PR_SET_NAME, thread_name) ? errno : 0;
}
// Have to change another thread's name.
pthread_internal_t* t = reinterpret_cast<pthread_internal_t*>(thread);
char comm_name[sizeof(TASK_COMM_FMT) + 8];
- snprintf(comm_name, sizeof(comm_name), TASK_COMM_FMT, (unsigned int) t->kernel_id);
- int fd = open(comm_name, O_RDWR);
+ snprintf(comm_name, sizeof(comm_name), TASK_COMM_FMT, t->tid);
+ int fd = open(comm_name, O_WRONLY);
if (fd == -1) {
return errno;
}
diff --git a/libc/bionic/ssp.cpp b/libc/bionic/ssp.cpp
deleted file mode 100644
index f01fee6..0000000
--- a/libc/bionic/ssp.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <ctype.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/auxv.h>
-#include <unistd.h>
-
-#include "bionic_ssp.h"
-#include "logd.h"
-
-uintptr_t __stack_chk_guard = NULL;
-
-static void __attribute__((constructor)) __init_stack_check_guard() {
- // AT_RANDOM is a pointer to 16 bytes of randomness on the stack.
- __stack_chk_guard = *reinterpret_cast<uintptr_t*>(getauxval(AT_RANDOM));
-}
-
-// This is the crash handler.
-// Does a best effort at logging and calls _exit to terminate
-// the process immediately (without atexit handlers, etc.).
-void __stack_chk_fail() {
- // Immediately block all (but SIGABRT) signal handlers from running code.
- sigset_t sigmask;
- sigfillset(&sigmask);
- sigdelset(&sigmask, SIGABRT);
- sigprocmask(SIG_BLOCK, &sigmask, NULL);
-
- // Use /proc/self/exe link to obtain the program name for logging
- // purposes. If it's not available, we set it to "<unknown>".
- char path[PATH_MAX];
- int count;
- if ((count = readlink("/proc/self/exe", path, sizeof(path) - 1)) == -1) {
- strlcpy(path, "<unknown>", sizeof(path));
- } else {
- path[count] = '\0';
- }
-
- // Do a best effort at logging.
- __libc_android_log_write(ANDROID_LOG_FATAL, path, "stack corruption detected: aborted");
-
- // Make sure there is no default action for SIGABRT.
- struct sigaction sa;
- memset(&sa, 0, sizeof(sa));
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sa.sa_handler = SIG_DFL;
- sigaction(SIGABRT, &sa, NULL);
-
- // Terminate the process and exit immediately.
- kill(getpid(), SIGABRT);
-
- _exit(127);
-}
diff --git a/libc/kernel/common/linux/securebits.h b/libc/kernel/common/linux/securebits.h
new file mode 100644
index 0000000..7bde365
--- /dev/null
+++ b/libc/kernel/common/linux/securebits.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _LINUX_SECUREBITS_H
+#define _LINUX_SECUREBITS_H 1
+#define issecure_mask(X) (1 << (X))
+#define SECUREBITS_DEFAULT 0x00000000
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define SECURE_NOROOT 0
+#define SECURE_NOROOT_LOCKED 1
+#define SECBIT_NOROOT (issecure_mask(SECURE_NOROOT))
+#define SECBIT_NOROOT_LOCKED (issecure_mask(SECURE_NOROOT_LOCKED))
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define SECURE_NO_SETUID_FIXUP 2
+#define SECURE_NO_SETUID_FIXUP_LOCKED 3
+#define SECBIT_NO_SETUID_FIXUP (issecure_mask(SECURE_NO_SETUID_FIXUP))
+#define SECBIT_NO_SETUID_FIXUP_LOCKED (issecure_mask(SECURE_NO_SETUID_FIXUP_LOCKED))
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define SECURE_KEEP_CAPS 4
+#define SECURE_KEEP_CAPS_LOCKED 5
+#define SECBIT_KEEP_CAPS (issecure_mask(SECURE_KEEP_CAPS))
+#define SECBIT_KEEP_CAPS_LOCKED (issecure_mask(SECURE_KEEP_CAPS_LOCKED))
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define SECURE_ALL_BITS (issecure_mask(SECURE_NOROOT) | issecure_mask(SECURE_NO_SETUID_FIXUP) | issecure_mask(SECURE_KEEP_CAPS))
+#define SECURE_ALL_LOCKS (SECURE_ALL_BITS << 1)
+#endif
diff --git a/libc/private/bionic_ssp.h b/libc/private/bionic_ssp.h
index d34b6ab..9883d72 100644
--- a/libc/private/bionic_ssp.h
+++ b/libc/private/bionic_ssp.h
@@ -29,6 +29,9 @@
#ifndef _PRIVATE_SSP_H
#define _PRIVATE_SSP_H
+#include <stdint.h>
+#include <sys/cdefs.h>
+
__BEGIN_DECLS
/* GCC uses this on ARM and MIPS; we use it on x86 to set the guard in TLS. */
diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h
index dfbb142..dd6b932 100644
--- a/libc/private/bionic_tls.h
+++ b/libc/private/bionic_tls.h
@@ -78,9 +78,6 @@
#define GLOBAL_INIT_THREAD_LOCAL_BUFFER_COUNT 4
#define BIONIC_TLS_SLOTS 64
-/* set the Thread Local Storage, must contain at least BIONIC_TLS_SLOTS pointers */
-extern void __init_tls(void** tls, void* thread_info);
-
/* syscall only, do not call directly */
extern int __set_tls(void* ptr);
diff --git a/libthread_db/libthread_db.c b/libthread_db/libthread_db.c
index e749377..bd78ae6 100644
--- a/libthread_db/libthread_db.c
+++ b/libthread_db/libthread_db.c
@@ -161,7 +161,7 @@
td_thr_get_info(td_thrhandle_t const * handle, td_thrinfo_t * info)
{
info->ti_tid = handle->tid;
- info->ti_lid = handle->tid; // Our pthreads uses kernel ids for tids
+ info->ti_lid = handle->tid;
info->ti_state = TD_THR_SLEEP; /* XXX this needs to be read from /proc/<pid>/task/<tid>.
This is only used to see if the thread is a zombie or not */
return TD_OK;
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 931a4c7..aebf477 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -149,12 +149,12 @@
pthread_exit(NULL);
}
-// We have to say "DeathTest" here so gtest knows to run this test (which exits)
-// in its own process.
+// Even though this isn't really a death test, we have to say "DeathTest" here so gtest knows to
+// run this test (which exits normally) in its own process.
TEST(pthread_DeathTest, pthread_bug_37410) {
// http://code.google.com/p/android/issues/detail?id=37410
::testing::FLAGS_gtest_death_test_style = "threadsafe";
- EXPECT_EXIT(TestBug37410(), ::testing::ExitedWithCode(0), "");
+ ASSERT_EXIT(TestBug37410(), ::testing::ExitedWithCode(0), "");
}
#endif
@@ -187,7 +187,7 @@
}
#if __BIONIC__
-extern "C" int __pthread_clone(int (*fn)(void*), void* child_stack, int flags, void* arg);
+extern "C" int __pthread_clone(void* (*fn)(void*), void* child_stack, int flags, void* arg);
TEST(pthread, __pthread_clone) {
uintptr_t fake_child_stack[16];
errno = 0;
@@ -210,9 +210,20 @@
#if __BIONIC__ // Not all build servers have a new enough glibc? TODO: remove when they're on gprecise.
TEST(pthread, pthread_setname_np__other) {
- pthread_t t1;
- ASSERT_EQ(0, pthread_create(&t1, NULL, SleepFn, reinterpret_cast<void*>(5)));
- ASSERT_EQ(0, pthread_setname_np(t1, "short 2"));
+ // Emulator kernels don't currently support setting the name of other threads.
+ char* filename = NULL;
+ asprintf(&filename, "/proc/self/task/%d/comm", gettid());
+ struct stat sb;
+ bool has_comm = (stat(filename, &sb) != -1);
+ free(filename);
+
+ if (has_comm) {
+ pthread_t t1;
+ ASSERT_EQ(0, pthread_create(&t1, NULL, SleepFn, reinterpret_cast<void*>(5)));
+ ASSERT_EQ(0, pthread_setname_np(t1, "short 2"));
+ } else {
+ fprintf(stderr, "skipping test: this kernel doesn't have /proc/self/task/tid/comm files!\n");
+ }
}
#endif
diff --git a/tests/stack_protector_test.cpp b/tests/stack_protector_test.cpp
index 664a11e..7946bbc 100644
--- a/tests/stack_protector_test.cpp
+++ b/tests/stack_protector_test.cpp
@@ -36,7 +36,7 @@
#ifdef __i386__
-// For x86, bionic and glibc have per-thread stack guard values.
+// For x86, bionic and glibc have per-thread stack guard values (all identical).
static uint32_t GetGuardFromTls() {
uint32_t guard;
@@ -117,11 +117,9 @@
__stack_chk_guard = 0x12345678;
}
-// We have to say "DeathTest" here so gtest knows to run this test (which exits)
-// in its own process.
TEST(stack_protector_DeathTest, modify_stack_protector) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
- ASSERT_EXIT(do_modify_stack_chk_guard(), testing::KilledBySignal(SIGABRT), "");
+ ASSERT_EXIT(do_modify_stack_chk_guard(), testing::KilledBySignal(SIGSEGV), "");
}
#endif