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.
This commit is contained in:
Augustin Cavalier
2019-09-02 22:06:22 -04:00
parent a785ea4b3a
commit 3a3d6c4ae2
+4 -2
View File
@@ -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;