diff options
Diffstat (limited to 'libc')
-rw-r--r-- | libc/Android.mk | 2 | ||||
-rw-r--r-- | libc/bionic/pthread.c | 7 | ||||
-rw-r--r-- | libc/bionic/ssp.c | 100 | ||||
-rw-r--r-- | libc/bionic/ssp.cpp | 81 | ||||
-rw-r--r-- | libc/private/bionic_ssp.h | 76 | ||||
-rw-r--r-- | libc/private/bionic_tls.h | 15 |
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 |