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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user