From c33d4568aca9028a22857f94f5e0850012b6444b Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sun, 12 Mar 2006 23:52:59 +0100 Subject: [PATCH] x86-64: Fix up handling of non canonical user RIPs EM64T CPUs have somewhat weird error reporting for non canonical RIPs in SYSRET. We can't handle any exceptions there because the exception handler would end up running on the user stack which is unsafe. To avoid problems any code that might end up with a user touched pt_regs should return using int_ret_from_syscall. int_ret_from_syscall ends up using IRET, which allows safe exceptions. Cc: Ernie Petrides Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/entry.S | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S index 7c10e9009d6111..22cb6ee074b919 100644 --- a/arch/x86_64/kernel/entry.S +++ b/arch/x86_64/kernel/entry.S @@ -178,6 +178,12 @@ rff_trace: * Interrupts are off on entry. * Only called from user space. * + * EM64T CPUs have somewhat weird error reporting for non canonical RIPs in SYSRET. + * We can't handle any exceptions there because the exception handler would + * end up running on the user stack which is unsafe. To avoid problems + * any code that might end up with a user touched pt_regs should return + * using int_ret_from_syscall. + * * XXX if we had a free scratch register we could save the RSP into the stack frame * and report it properly in ps. Unfortunately we haven't. */ @@ -254,7 +260,9 @@ sysret_signal: xorl %esi,%esi # oldset -> arg2 call ptregscall_common 1: movl $_TIF_NEED_RESCHED,%edi - jmp sysret_check + /* Stack frame might have been changed. The IRET path does + some additional checks to handle this */ + jmp int_with_check badsys: movq $-ENOSYS,RAX-ARGOFFSET(%rsp) @@ -280,7 +288,8 @@ tracesys: call syscall_trace_leave RESTORE_TOP_OF_STACK %rbx RESTORE_REST - jmp ret_from_sys_call + /* Stack frame might have been changed. Use the more careful IRET path */ + jmp int_ret_from_sys_call CFI_ENDPROC /* @@ -408,25 +417,9 @@ ENTRY(stub_execve) CFI_ADJUST_CFA_OFFSET -8 CFI_REGISTER rip, r11 SAVE_REST - movq %r11, %r15 - CFI_REGISTER rip, r15 FIXUP_TOP_OF_STACK %r11 call sys_execve - GET_THREAD_INFO(%rcx) - bt $TIF_IA32,threadinfo_flags(%rcx) - CFI_REMEMBER_STATE - jc exec_32bit RESTORE_TOP_OF_STACK %r11 - movq %r15, %r11 - CFI_REGISTER rip, r11 - RESTORE_REST - pushq %r11 - CFI_ADJUST_CFA_OFFSET 8 - CFI_REL_OFFSET rip, 0 - ret - -exec_32bit: - CFI_RESTORE_STATE movq %rax,RAX(%rsp) RESTORE_REST jmp int_ret_from_sys_call -- cgit 1.2.3-korg