Эх сурвалжийг харах

[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 <petrides@redhat.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Andi Kleen 19 жил өмнө
parent
commit
c33d4568ac

+ 11 - 18
arch/x86_64/kernel/entry.S

@@ -178,6 +178,12 @@ rff_trace:
  * Interrupts are off on entry.
  * Interrupts are off on entry.
  * Only called from user space.
  * 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
  * 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.
  *      and report it properly in ps. Unfortunately we haven't.
  */ 			 		
  */ 			 		
@@ -254,7 +260,9 @@ sysret_signal:
 	xorl %esi,%esi # oldset -> arg2
 	xorl %esi,%esi # oldset -> arg2
 	call ptregscall_common
 	call ptregscall_common
 1:	movl $_TIF_NEED_RESCHED,%edi
 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:
 badsys:
 	movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
 	movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
@@ -280,7 +288,8 @@ tracesys:
 	call syscall_trace_leave
 	call syscall_trace_leave
 	RESTORE_TOP_OF_STACK %rbx
 	RESTORE_TOP_OF_STACK %rbx
 	RESTORE_REST
 	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
 	CFI_ENDPROC
 		
 		
 /* 
 /* 
@@ -408,25 +417,9 @@ ENTRY(stub_execve)
 	CFI_ADJUST_CFA_OFFSET -8
 	CFI_ADJUST_CFA_OFFSET -8
 	CFI_REGISTER rip, r11
 	CFI_REGISTER rip, r11
 	SAVE_REST
 	SAVE_REST
-	movq %r11, %r15
-	CFI_REGISTER rip, r15
 	FIXUP_TOP_OF_STACK %r11
 	FIXUP_TOP_OF_STACK %r11
 	call sys_execve
 	call sys_execve
-	GET_THREAD_INFO(%rcx)
-	bt $TIF_IA32,threadinfo_flags(%rcx)
-	CFI_REMEMBER_STATE
-	jc exec_32bit
 	RESTORE_TOP_OF_STACK %r11
 	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)
 	movq %rax,RAX(%rsp)
 	RESTORE_REST
 	RESTORE_REST
 	jmp int_ret_from_sys_call
 	jmp int_ret_from_sys_call