* commit 'df7f24f310ee3ceb1dc9413d59d5a8816eb584ef': Per-thread -fstack-protector guards for x86.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
81
libc/bionic/ssp.cpp
Normal file
81
libc/bionic/ssp.cpp
Normal file
@@ -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);
|
||||
}
|
||||
76
libc/private/bionic_ssp.h
Normal file
76
libc/private/bionic_ssp.h
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user