aboutsummaryrefslogtreecommitdiffstats
path: root/libc
diff options
context:
space:
mode:
Diffstat (limited to 'libc')
-rw-r--r--libc/Android.mk2
-rw-r--r--libc/bionic/pthread.c7
-rw-r--r--libc/bionic/ssp.c100
-rw-r--r--libc/bionic/ssp.cpp81
-rw-r--r--libc/private/bionic_ssp.h76
-rw-r--r--libc/private/bionic_tls.h15
6 files changed, 168 insertions, 113 deletions
diff --git a/libc/Android.mk b/libc/Android.mk
index 780f478b4..a037e7a1d 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -740,7 +740,7 @@ WITH_MALLOC_CHECK_LIBC_A := $(strip $(WITH_MALLOC_CHECK_LIBC_A))
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := bionic/ssp.c
+LOCAL_SRC_FILES := bionic/ssp.cpp
LOCAL_CFLAGS := $(libc_common_cflags) -fno-stack-protector
LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_MODULE := libbionic_ssp
diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c
index 719bc83b5..7c22b45b2 100644
--- a/libc/bionic/pthread.c
+++ b/libc/bionic/pthread.c
@@ -48,6 +48,7 @@
#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"
@@ -171,12 +172,14 @@ void __init_tls(void** tls, void* thread) {
tls[i] = NULL;
}
- // Slot 0 must point to the tls area, this is required by the implementation
- // of the x86 Linux kernel thread-local-storage.
+ // Slot 0 must point to itself. The x86 Linux kernel reads the TLS from %fs:0.
tls[TLS_SLOT_SELF] = (void*) tls;
tls[TLS_SLOT_THREAD_ID] = thread;
+ // Stack guard generation may make system calls, and those system calls may fail.
+ // If they do, they'll try to set errno, so we can only do this after calling __set_tls.
__set_tls((void*) tls);
+ tls[TLS_SLOT_STACK_GUARD] = __generate_stack_chk_guard();
}
diff --git a/libc/bionic/ssp.c b/libc/bionic/ssp.c
deleted file mode 100644
index f83b2a447..000000000
--- a/libc/bionic/ssp.c
+++ /dev/null
@@ -1,100 +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 <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include "logd.h"
-
-void *__stack_chk_guard = 0;
-
-/* Initialize the canary with a random value from /dev/urandom.
- * If that fails, use the "terminator canary". */
-static void __attribute__ ((constructor))
-__guard_setup(void)
-{
- int fd;
-
- fd = open("/dev/urandom", O_RDONLY);
- if (fd != -1) {
- ssize_t len = read(fd, &__stack_chk_guard,
- sizeof(__stack_chk_guard));
- close(fd);
- if (len == sizeof(__stack_chk_guard))
- return;
- }
-
- /* If that failed, switch to 'terminator canary' */
- ((unsigned char *)&__stack_chk_guard)[0] = 0;
- ((unsigned char *)&__stack_chk_guard)[1] = 0;
- ((unsigned char *)&__stack_chk_guard)[2] = '\n';
- ((unsigned char *)&__stack_chk_guard)[3] = 255;
-}
-
-/* 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(void)
-{
- struct sigaction sa;
- sigset_t sigmask;
- static const char message[] = "stack corruption detected: aborted";
- char path[PATH_MAX];
- int count;
-
- /* Immediately block all (but SIGABRT) signal handlers from running code */
- 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>" */
- 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. This ends up calling writev(2) */
- __libc_android_log_print(ANDROID_LOG_FATAL, path, message);
-
- /* Make sure there is no default action for SIGABRT */
- bzero(&sa, sizeof(struct sigaction));
- 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/bionic/ssp.cpp b/libc/bionic/ssp.cpp
new file mode 100644
index 000000000..fdf88328b
--- /dev/null
+++ b/libc/bionic/ssp.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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 <unistd.h>
+
+#include "bionic_ssp.h"
+#include "logd.h"
+
+void* __stack_chk_guard = NULL;
+
+static void __attribute__((constructor)) __init_stack_check_guard() {
+ __stack_chk_guard = __generate_stack_chk_guard();
+}
+
+// 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. This ends up calling writev(2).
+ __libc_android_log_print(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/private/bionic_ssp.h b/libc/private/bionic_ssp.h
new file mode 100644
index 000000000..697216c18
--- /dev/null
+++ b/libc/private/bionic_ssp.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef _PRIVATE_SSP_H
+#define _PRIVATE_SSP_H
+
+#include <errno.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/** WARNING WARNING WARNING
+ **
+ ** This header file is *NOT* part of the public Bionic ABI/API
+ ** and should not be used/included by user-serviceable parts of
+ ** the system (e.g. applications).
+ **/
+
+/* GCC uses this on ARM and MIPS. */
+extern void* __stack_chk_guard;
+
+/* GCC calls this if a stack guard check fails. */
+extern void __stack_chk_fail();
+
+__inline__ static void* __attribute__((always_inline)) __generate_stack_chk_guard(void) {
+ union {
+ uintptr_t value;
+ char bytes[sizeof(uintptr_t)];
+ } u;
+
+ /* Try pulling random bytes from /dev/urandom. */
+ int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY));
+ if (fd != -1) {
+ ssize_t byte_count = TEMP_FAILURE_RETRY(read(fd, &u.bytes, sizeof(u)));
+ close(fd);
+ if (byte_count == sizeof(u)) {
+ return (void*) u.value;
+ }
+ }
+
+ /* If that failed, switch to 'terminator canary'. */
+ u.bytes[0] = 0;
+ u.bytes[1] = 0;
+ u.bytes[2] = '\n';
+ u.bytes[3] = 255;
+ return (void*) u.value;
+}
+
+__END_DECLS
+
+#endif
diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h
index a626d2172..f661ccf24 100644
--- a/libc/private/bionic_tls.h
+++ b/libc/private/bionic_tls.h
@@ -43,24 +43,19 @@ __BEGIN_DECLS
** pre-allocated slot directly for performance reason).
**/
-/* maximum number of elements in the TLS array */
+/* Maximum number of elements in the TLS array. */
#define BIONIC_TLS_SLOTS 64
-/* note that slot 0, called TLS_SLOT_SELF must point to itself.
- * this is required to implement thread-local storage with the x86
- * Linux kernel, that reads the TLS from fs:[0], where 'fs' is a
- * thread-specific segment descriptor...
- */
-
-/* Well-known TLS slots. */
-#define TLS_SLOT_SELF 0
+/* Well-known TLS slots. What data goes in which slot is arbitrary unless otherwise noted. */
+#define TLS_SLOT_SELF 0 /* The kernel requires this specific slot for x86. */
#define TLS_SLOT_THREAD_ID 1
#define TLS_SLOT_ERRNO 2
#define TLS_SLOT_OPENGL_API 3
#define TLS_SLOT_OPENGL 4
-#define TLS_SLOT_DLERROR 5
+#define TLS_SLOT_STACK_GUARD 5 /* GCC requires this specific slot for x86. */
+#define TLS_SLOT_DLERROR 6
#define TLS_SLOT_MAX_WELL_KNOWN TLS_SLOT_DLERROR