From 13daa9299ebf06b9db6d6a06fa8724df274fc84f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Sun, 14 Jan 2018 09:54:25 +0100 Subject: [PATCH] Fix initial stack alignment on 64-bit systems. gcc does re-align the stack in the main() function prologue, however, we still need to set the right alignment for other cases: thread entry, .init and .fini code that is executed before main() is called or after it has returned, and signal handlers which may use a separate stack. Part of #10509 --- src/system/kernel/arch/x86/64/thread.cpp | 27 ++++++++++++++---------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/system/kernel/arch/x86/64/thread.cpp b/src/system/kernel/arch/x86/64/thread.cpp index 9e535fefbe..1aab1a43a1 100644 --- a/src/system/kernel/arch/x86/64/thread.cpp +++ b/src/system/kernel/arch/x86/64/thread.cpp @@ -101,12 +101,16 @@ arch_randomize_stack_pointer(addr_t value) static_assert(MAX_RANDOM_VALUE >= B_PAGE_SIZE - 1, "randomization range is too big"); value -= random_value() & (B_PAGE_SIZE - 1); - return value & ~addr_t(0xf); + return (value & ~addr_t(0xf)) - 8; + // This means, result % 16 == 8, which is what rsp should adhere to + // when a function is entered for the stack to be considered aligned to + // 16 byte. } static uint8* -get_signal_stack(Thread* thread, iframe* frame, struct sigaction* action) +get_signal_stack(Thread* thread, iframe* frame, struct sigaction* action, + size_t spaceNeeded) { // Use the alternate signal stack if we should and can. if (thread->signal_stack_enabled @@ -115,14 +119,15 @@ get_signal_stack(Thread* thread, iframe* frame, struct sigaction* action) || frame->user_sp >= thread->signal_stack_base + thread->signal_stack_size)) { addr_t stackTop = thread->signal_stack_base + thread->signal_stack_size; - return (uint8*)arch_randomize_stack_pointer(stackTop); + return (uint8*)arch_randomize_stack_pointer(stackTop - spaceNeeded); } // We are going to use the stack that we are already on. We must not touch // the red zone (128 byte area below the stack pointer, reserved for use // by functions to store temporary data and guaranteed not to be modified // by signal handlers). - return (uint8*)(frame->user_sp - 128); + return (uint8*)((frame->user_sp - 128 - spaceNeeded) & ~addr_t(0xf)) - 8; + // align stack pointer (cf. arch_randomize_stack_pointer()) } @@ -207,19 +212,19 @@ arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1, void* args2) { addr_t stackTop = thread->user_stack_base + thread->user_stack_size; + addr_t codeAddr; TRACE("arch_thread_enter_userspace: entry %#lx, args %p %p, " "stackTop %#lx\n", entry, args1, args2, stackTop); - stackTop = arch_randomize_stack_pointer(stackTop); + stackTop = arch_randomize_stack_pointer(stackTop - sizeof(codeAddr)); // Copy the address of the stub that calls exit_thread() when the thread // entry function returns to the top of the stack to act as the return // address. The stub is inside commpage. addr_t commPageAddress = (addr_t)thread->team->commpage_address; - addr_t codeAddr = ((addr_t*)commPageAddress)[COMMPAGE_ENTRY_X86_THREAD_EXIT] + codeAddr = ((addr_t*)commPageAddress)[COMMPAGE_ENTRY_X86_THREAD_EXIT] + commPageAddress; - stackTop -= sizeof(codeAddr); if (user_memcpy((void*)stackTop, (const void*)&codeAddr, sizeof(codeAddr)) != B_OK) return B_BAD_ADDRESS; @@ -315,10 +320,11 @@ arch_setup_signal_frame(Thread* thread, struct sigaction* action, signalFrameData->syscall_restart_return_value = frame->orig_rax; // Get the stack to use and copy the frame data to it. - uint8* userStack = get_signal_stack(thread, frame, action); + uint8* userStack = get_signal_stack(thread, frame, action, + sizeof(*signalFrameData) + sizeof(frame->ip)); - userStack -= sizeof(*signalFrameData); - signal_frame_data* userSignalFrameData = (signal_frame_data*)userStack; + signal_frame_data* userSignalFrameData + = (signal_frame_data*)(userStack + sizeof(frame->ip)); if (user_memcpy(userSignalFrameData, signalFrameData, sizeof(*signalFrameData)) != B_OK) { @@ -326,7 +332,6 @@ arch_setup_signal_frame(Thread* thread, struct sigaction* action, } // Copy a return address to the stack so that backtraces will be correct. - userStack -= sizeof(frame->ip); if (user_memcpy(userStack, &frame->ip, sizeof(frame->ip)) != B_OK) return B_BAD_ADDRESS;