Re-org thread env init/destroy for HW bound check (#631)

And fix cmake_minimum_required() deprecation warning since envoy is using cmake 3.16 or higher version.
This commit is contained in:
Wenyong Huang
2021-05-14 11:13:12 +08:00
committed by GitHub
parent 17a2167485
commit a14a4487bb
16 changed files with 205 additions and 126 deletions

View File

@ -11,12 +11,15 @@
typedef struct {
thread_start_routine_t start;
void* arg;
void *arg;
#ifdef OS_ENABLE_HW_BOUND_CHECK
os_signal_handler signal_handler;
#endif
} thread_wrapper_arg;
#ifdef OS_ENABLE_HW_BOUND_CHECK
static int os_thread_signal_init();
static void os_thread_signal_destroy();
/* The signal handler passed to os_thread_signal_init() */
static os_thread_local_attribute os_signal_handler signal_handler;
#endif
static void *os_thread_wrapper(void *arg)
@ -24,16 +27,18 @@ static void *os_thread_wrapper(void *arg)
thread_wrapper_arg *targ = arg;
thread_start_routine_t start_func = targ->start;
void *thread_arg = targ->arg;
#ifdef OS_ENABLE_HW_BOUND_CHECK
os_signal_handler handler = targ->signal_handler;
#endif
os_printf("THREAD CREATED %p\n", pthread_self());
BH_FREE(targ);
#ifdef OS_ENABLE_HW_BOUND_CHECK
if (os_thread_signal_init() != 0)
if (os_thread_signal_init(handler) != 0)
return NULL;
#endif
start_func(thread_arg);
#ifdef OS_ENABLE_HW_BOUND_CHECK
os_thread_destroy_stack_guard_pages();
os_thread_signal_destroy();
#endif
return NULL;
@ -66,6 +71,9 @@ int os_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start,
targ->start = start;
targ->arg = arg;
#ifdef OS_ENABLE_HW_BOUND_CHECK
targ->signal_handler = signal_handler;
#endif
if (pthread_create(tid, &tattr, os_thread_wrapper, targ) != 0) {
pthread_attr_destroy(&tattr);
@ -250,7 +258,6 @@ int os_thread_detach(korp_tid thread)
void os_thread_exit(void *retval)
{
#ifdef OS_ENABLE_HW_BOUND_CHECK
os_thread_destroy_stack_guard_pages();
os_thread_signal_destroy();
#endif
return pthread_exit(retval);
@ -313,20 +320,25 @@ uint8 *os_thread_get_stack_boundary()
#define SIG_ALT_STACK_SIZE (32 * 1024)
/* Whether the stack pages are touched and guard pages are set */
static os_thread_local_attribute bool stack_guard_pages_inited = false;
/**
* Whether thread signal enviornment is initialized:
* the signal handler is registered, the stack pages are touched,
* the stack guard pages are set and signal alternate stack are set.
*/
static os_thread_local_attribute bool thread_signal_inited = false;
/* The signal alternate stack base addr */
static os_thread_local_attribute uint8 *sigalt_stack_base_addr;
/* The signal handler passed to os_signal_init() */
static os_signal_handler signal_handler;
#if defined(__GNUC__)
__attribute__((no_sanitize_address)) static uint32
#else
static uint32
#if defined(__clang__)
#pragma clang optimize off
#endif
#if defined(__GNUC__)
#pragma GCC push_options
#pragma GCC optimize("O0")
__attribute__((no_sanitize_address))
#endif
static uint32
touch_pages(uint8 *stack_min_addr, uint32 page_size)
{
uint8 sum = 0;
@ -342,40 +354,40 @@ touch_pages(uint8 *stack_min_addr, uint32 page_size)
}
return sum;
}
#if defined(__GNUC__)
#pragma GCC pop_options
#endif
#if defined(__clang__)
#pragma clang optimize on
#endif
bool
os_thread_init_stack_guard_pages()
static bool
init_stack_guard_pages()
{
uint32 page_size = os_getpagesize();
uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
uint8 *stack_min_addr = os_thread_get_stack_boundary();
if (!stack_guard_pages_inited) {
/* Touch each stack page to ensure that it has been mapped: the OS
may lazily grow the stack mapping as a guard page is hit. */
(void)touch_pages(stack_min_addr, page_size);
/* First time to call aot function, protect guard pages */
if (os_mprotect(stack_min_addr, page_size * guard_page_count,
MMAP_PROT_NONE) != 0) {
return false;
}
stack_guard_pages_inited = true;
/* Touch each stack page to ensure that it has been mapped: the OS
may lazily grow the stack mapping as a guard page is hit. */
(void)touch_pages(stack_min_addr, page_size);
/* First time to call aot function, protect guard pages */
if (os_mprotect(stack_min_addr, page_size * guard_page_count,
MMAP_PROT_NONE) != 0) {
return false;
}
return true;
}
void
os_thread_destroy_stack_guard_pages()
static void
destroy_stack_guard_pages()
{
if (stack_guard_pages_inited) {
uint32 page_size = os_getpagesize();
uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
uint8 *stack_min_addr = os_thread_get_stack_boundary();
uint32 page_size = os_getpagesize();
uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
uint8 *stack_min_addr = os_thread_get_stack_boundary();
os_mprotect(stack_min_addr, page_size * guard_page_count,
MMAP_PROT_READ | MMAP_PROT_WRITE);
stack_guard_pages_inited = false;
}
os_mprotect(stack_min_addr, page_size * guard_page_count,
MMAP_PROT_READ | MMAP_PROT_WRITE);
}
static void
@ -419,20 +431,27 @@ signal_callback(int sig_num, siginfo_t *sig_info, void *sig_ucontext)
}
int
os_signal_init(os_signal_handler handler)
os_thread_signal_init(os_signal_handler handler)
{
int ret = -1;
struct sigaction sig_act;
stack_t sigalt_stack_info;
uint32 map_size = SIG_ALT_STACK_SIZE;
uint8 *map_addr;
if (thread_signal_inited)
return 0;
if (!init_stack_guard_pages()) {
os_printf("Failed to init stack guard pages\n");
return -1;
}
/* Initialize memory for signal alternate stack of current thread */
if (!(map_addr = os_mmap(NULL, map_size,
MMAP_PROT_READ | MMAP_PROT_WRITE,
MMAP_MAP_NONE))) {
os_printf("Failed to mmap memory for alternate stack\n");
return -1;
goto fail1;
}
/* Initialize signal alternate stack */
@ -440,38 +459,46 @@ os_signal_init(os_signal_handler handler)
sigalt_stack_info.ss_sp = map_addr;
sigalt_stack_info.ss_size = map_size;
sigalt_stack_info.ss_flags = 0;
if ((ret = sigaltstack(&sigalt_stack_info, NULL)) != 0) {
goto fail1;
if (sigaltstack(&sigalt_stack_info, NULL) != 0) {
os_printf("Failed to init signal alternate stack\n");
goto fail2;
}
/* Install signal hanlder */
sig_act.sa_sigaction = signal_callback;
sig_act.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_NODEFER;
sigemptyset(&sig_act.sa_mask);
if ((ret = sigaction(SIGSEGV, &sig_act, NULL)) != 0
|| (ret = sigaction(SIGBUS, &sig_act, NULL)) != 0) {
goto fail2;
if (sigaction(SIGSEGV, &sig_act, NULL) != 0
|| sigaction(SIGBUS, &sig_act, NULL) != 0) {
os_printf("Failed to register signal handler\n");
goto fail3;
}
sigalt_stack_base_addr = map_addr;
signal_handler = handler;
thread_signal_inited = true;
return 0;
fail2:
fail3:
memset(&sigalt_stack_info, 0, sizeof(stack_t));
sigalt_stack_info.ss_flags = SS_DISABLE;
sigalt_stack_info.ss_size = map_size;
sigaltstack(&sigalt_stack_info, NULL);
fail1:
fail2:
os_munmap(map_addr, map_size);
return ret;
fail1:
destroy_stack_guard_pages();
return -1;
}
void
os_signal_destroy()
os_thread_signal_destroy()
{
stack_t sigalt_stack_info;
if (!thread_signal_inited)
return;
/* Disable signal alternate stack */
memset(&sigalt_stack_info, 0, sizeof(stack_t));
sigalt_stack_info.ss_flags = SS_DISABLE;
@ -479,20 +506,16 @@ os_signal_destroy()
sigaltstack(&sigalt_stack_info, NULL);
os_munmap(sigalt_stack_base_addr, SIG_ALT_STACK_SIZE);
destroy_stack_guard_pages();
thread_signal_inited = false;
}
static int
os_thread_signal_init()
bool
os_thread_signal_inited()
{
assert(signal_handler);
/* Use the global signal handler registered previously */
return os_signal_init(signal_handler);
}
static void
os_thread_signal_destroy()
{
os_signal_destroy();
return thread_signal_inited;
}
void