Merge "bionic: Allocate a shadow call stack for each thread."
This commit is contained in:
commit
c2d3e67a77
|
@ -101,5 +101,5 @@ void __libc_init_main_thread(KernelArgumentBlock& args) {
|
|||
|
||||
__init_thread(&main_thread);
|
||||
|
||||
__init_alternate_signal_stack(&main_thread);
|
||||
__init_additional_stacks(&main_thread);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/random.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "pthread_internal.h"
|
||||
|
@ -86,7 +87,7 @@ void __init_thread_stack_guard(pthread_internal_t* thread) {
|
|||
thread->tls[TLS_SLOT_STACK_GUARD] = reinterpret_cast<void*>(__stack_chk_guard);
|
||||
}
|
||||
|
||||
void __init_alternate_signal_stack(pthread_internal_t* thread) {
|
||||
static void __init_alternate_signal_stack(pthread_internal_t* thread) {
|
||||
// Create and set an alternate signal stack.
|
||||
void* stack_base = mmap(nullptr, SIGNAL_STACK_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||
if (stack_base != MAP_FAILED) {
|
||||
|
@ -109,6 +110,25 @@ void __init_alternate_signal_stack(pthread_internal_t* thread) {
|
|||
}
|
||||
}
|
||||
|
||||
static void __init_shadow_call_stack(pthread_internal_t* thread __unused) {
|
||||
#ifdef __aarch64__
|
||||
// Allocate the stack and store its address in register x18.
|
||||
// TODO(pcc): We ought to allocate a guard region here and then allocate the SCS at a random
|
||||
// location within it. This will provide greater security since it would mean that an attacker who
|
||||
// can read the pthread_internal_t won't be able to discover the address of the SCS. However,
|
||||
// doing so is blocked on a solution to b/118642754.
|
||||
char* scs = reinterpret_cast<char*>(
|
||||
mmap(nullptr, SCS_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0));
|
||||
thread->shadow_call_stack_guard_region = scs;
|
||||
__asm__ __volatile__("mov x18, %0" ::"r"(scs));
|
||||
#endif
|
||||
}
|
||||
|
||||
void __init_additional_stacks(pthread_internal_t* thread) {
|
||||
__init_alternate_signal_stack(thread);
|
||||
__init_shadow_call_stack(thread);
|
||||
}
|
||||
|
||||
int __init_thread(pthread_internal_t* thread) {
|
||||
thread->cleanup_stack = nullptr;
|
||||
|
||||
|
@ -252,7 +272,7 @@ static int __pthread_start(void* arg) {
|
|||
// accesses previously made by the creating thread are visible to us.
|
||||
thread->startup_handshake_lock.lock();
|
||||
|
||||
__init_alternate_signal_stack(thread);
|
||||
__init_additional_stacks(thread);
|
||||
|
||||
void* result = thread->start_routine(thread->start_routine_arg);
|
||||
pthread_exit(result);
|
||||
|
|
|
@ -103,6 +103,11 @@ void pthread_exit(void* return_value) {
|
|||
thread->alternate_signal_stack = nullptr;
|
||||
}
|
||||
|
||||
#ifdef __aarch64__
|
||||
// Free the shadow call stack and guard pages.
|
||||
munmap(thread->shadow_call_stack_guard_region, SCS_SIZE);
|
||||
#endif
|
||||
|
||||
ThreadJoinState old_state = THREAD_NOT_JOINED;
|
||||
while (old_state == THREAD_NOT_JOINED &&
|
||||
!atomic_compare_exchange_weak(&thread->join_state, &old_state, THREAD_EXITED_NOT_JOINED)) {
|
||||
|
|
|
@ -155,7 +155,7 @@ class pthread_internal_t {
|
|||
__LIBC_HIDDEN__ int __init_thread(pthread_internal_t* thread);
|
||||
__LIBC_HIDDEN__ bool __init_tls(pthread_internal_t* thread);
|
||||
__LIBC_HIDDEN__ void __init_thread_stack_guard(pthread_internal_t* thread);
|
||||
__LIBC_HIDDEN__ void __init_alternate_signal_stack(pthread_internal_t*);
|
||||
__LIBC_HIDDEN__ void __init_additional_stacks(pthread_internal_t*);
|
||||
|
||||
__LIBC_HIDDEN__ pthread_t __pthread_internal_add(pthread_internal_t* thread);
|
||||
__LIBC_HIDDEN__ pthread_internal_t* __pthread_internal_find(pthread_t pthread_id);
|
||||
|
@ -209,6 +209,9 @@ __LIBC_HIDDEN__ void pthread_key_clean_all(void);
|
|||
// Leave room for a guard page in the internally created signal stacks.
|
||||
#define SIGNAL_STACK_SIZE (SIGNAL_STACK_SIZE_WITHOUT_GUARD + PTHREAD_GUARD_SIZE)
|
||||
|
||||
// Size of the shadow call stack.
|
||||
#define SCS_SIZE (8 * 1024)
|
||||
|
||||
// Needed by fork.
|
||||
__LIBC_HIDDEN__ extern void __bionic_atfork_run_prepare();
|
||||
__LIBC_HIDDEN__ extern void __bionic_atfork_run_child();
|
||||
|
|
Loading…
Reference in New Issue