From 3a3d6c4ae2900d921c48ed7df53b8280265c7504 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Mon, 2 Sep 2019 22:06:22 -0400 Subject: [PATCH] kernel/x86: Check the frame address really is a user address before copying. On x86_64, it is possible for a frame address to be in non-canonical form (i.e. have bits 48-63 not all zero) if one writes hand-generated assembly which does not use registers for their intended purpose, as there is no processor requirement about the contents of those registers or stack portions except when using "ret" or similar such instructions. As it turns out, OpenSSL's libcrypto has such hand-generated assembly for cryptography routines; so on 64-bit this caused a GPE when running the profiler on applications that used OpenSSL. Fixes #14530. --- src/system/kernel/arch/x86/arch_debug.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/system/kernel/arch/x86/arch_debug.cpp b/src/system/kernel/arch/x86/arch_debug.cpp index d864f0da58..2ab6b2e5b0 100644 --- a/src/system/kernel/arch/x86/arch_debug.cpp +++ b/src/system/kernel/arch/x86/arch_debug.cpp @@ -72,10 +72,12 @@ get_next_frame_no_debugger(addr_t bp, addr_t* _next, addr_t* _ip, // TODO: Do this more efficiently in assembly. stack_frame frame; if (onKernelStack - && is_kernel_stack_address(thread, bp + sizeof(frame) - 1)) + && is_kernel_stack_address(thread, bp + sizeof(frame) - 1)) { memcpy(&frame, (void*)bp, sizeof(frame)); - else if (user_memcpy(&frame, (void*)bp, sizeof(frame)) != B_OK) + } else if (!IS_USER_ADDRESS(bp) + || user_memcpy(&frame, (void*)bp, sizeof(frame)) != B_OK) { return B_BAD_ADDRESS; + } *_ip = frame.return_address; *_next = (addr_t)frame.previous;