[Pal/Linux] Allocate threads' stacks using malloc

_DkVirtualMemoryAlloc() can allocate memory overlapping with
pal_control.user_address. In this case, thread stack could get corrupted
by LibOS, typically resulting in SEGV.
This commit is contained in:
Isaku Yamahata
2019-09-28 16:32:59 +02:00
committed by Michał Kowalczyk
parent 0b6809fc19
commit 912761b1e0
2 changed files with 16 additions and 16 deletions
+3 -3
View File
@@ -236,12 +236,12 @@ void pal_linux_main (void * args)
INIT_FAIL(PAL_ERROR_NOMEM, "Out of memory");
SET_HANDLE_TYPE(first_thread, thread);
first_thread->thread.tid = INLINE_SYSCALL(gettid, 0);
first_thread->thread.stack = NULL;
void * alt_stack = NULL;
_DkVirtualMemoryAlloc(&alt_stack, ALT_STACK_SIZE, 0, PAL_PROT_READ|PAL_PROT_WRITE);
void * alt_stack = malloc(ALT_STACK_SIZE);
if (!alt_stack)
INIT_FAIL(PAL_ERROR_NOMEM, "Out of memory");
memset(alt_stack, 0, ALT_STACK_SIZE);
first_thread->thread.stack = alt_stack;
// Initialize TCB at the top of the alternative stack.
PAL_TCB_LINUX * tcb = alt_stack + ALT_STACK_SIZE - sizeof(PAL_TCB_LINUX);
+13 -13
View File
@@ -83,15 +83,18 @@ int pal_thread_init (void * tcbptr)
int _DkThreadCreate (PAL_HANDLE * handle, int (*callback) (void *),
const void * param)
{
void * stack = NULL;
int ret = _DkVirtualMemoryAlloc(&stack, THREAD_STACK_SIZE + ALT_STACK_SIZE,
0, PAL_PROT_READ|PAL_PROT_WRITE);
if (ret < 0)
return ret;
int ret = 0;
PAL_HANDLE hdl = NULL;
void * stack = malloc(THREAD_STACK_SIZE + ALT_STACK_SIZE);
if (!stack) {
ret = -ENOMEM;
goto err;
}
memset(stack, 0, THREAD_STACK_SIZE + ALT_STACK_SIZE);
void * child_stack = stack + THREAD_STACK_SIZE;
PAL_HANDLE hdl = malloc(HANDLE_SIZE(thread));
hdl = malloc(HANDLE_SIZE(thread));
if (!hdl) {
ret = -ENOMEM;
goto err;
@@ -124,10 +127,8 @@ int _DkThreadCreate (PAL_HANDLE * handle, int (*callback) (void *),
*handle = hdl;
return 0;
err:
if (stack)
_DkVirtualMemoryFree(stack, THREAD_STACK_SIZE + ALT_STACK_SIZE);
if (hdl)
free(hdl);
free(stack);
free(hdl);
return ret;
}
@@ -181,12 +182,11 @@ noreturn void _DkThreadExit (void)
// Take precautions to unset the TCB and alternative stack first.
INLINE_SYSCALL(arch_prctl, 2, ARCH_SET_GS, 0);
INLINE_SYSCALL(sigaltstack, 2, &ss, NULL);
INLINE_SYSCALL(munmap, 2, tcb->alt_stack, ALT_STACK_SIZE);
}
if (handle && handle->thread.stack) {
if (handle) {
// Free the thread stack
INLINE_SYSCALL(munmap, 2, handle->thread.stack, THREAD_STACK_SIZE);
free(handle->thread.stack);
// After this line, needs to exit the thread immediately
}