|
|
@@ -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(__clang__)
|
|
|
+#pragma clang optimize off
|
|
|
+#endif
|
|
|
#if defined(__GNUC__)
|
|
|
-__attribute__((no_sanitize_address)) static uint32
|
|
|
-#else
|
|
|
-static uint32
|
|
|
+#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();
|
|
|
-
|
|
|
- os_mprotect(stack_min_addr, page_size * guard_page_count,
|
|
|
- MMAP_PROT_READ | MMAP_PROT_WRITE);
|
|
|
- stack_guard_pages_inited = false;
|
|
|
- }
|
|
|
+ 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);
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
-}
|
|
|
|
|
|
-static int
|
|
|
-os_thread_signal_init()
|
|
|
-{
|
|
|
- assert(signal_handler);
|
|
|
- /* Use the global signal handler registered previously */
|
|
|
- return os_signal_init(signal_handler);
|
|
|
+ destroy_stack_guard_pages();
|
|
|
+
|
|
|
+ thread_signal_inited = false;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
-os_thread_signal_destroy()
|
|
|
+bool
|
|
|
+os_thread_signal_inited()
|
|
|
{
|
|
|
- os_signal_destroy();
|
|
|
+ return thread_signal_inited;
|
|
|
}
|
|
|
|
|
|
void
|