Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2006-04-12 08:19:29 +0200
committerGreg Kroah-Hartman <gregkh@suse.de>2006-04-12 13:06:54 -0700
commit6b12095a4a0e1f21bbf83f95f13299ca99d758fe (patch)
tree5d2a3d96f7b99a3a225c0f7a110c6631848524b0
parent59b2832a31ae2f3279bb5b16ae9b1c4e38e40dea (diff)
[PATCH] x86_64: When user could have changed RIP always force IRET (CVE-2006-0744)
Intel EM64T CPUs handle uncanonical return addresses differently from AMD CPUs. The exception is reported in the SYSRET, not the next instruction. Thgis leads to the kernel exception handler running on the user stack with the wrong GS because the kernel didn't expect exceptions on this instruction. This version of the patch has the teething problems that plagued an earlier version fixed. This is CVE-2006-0744 Thanks to Ernie Petrides and Asit B. Mallick for analysis and initial patches. Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--arch/x86_64/kernel/entry.S12
1 files changed, 10 insertions, 2 deletions
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index 25dcb775559c..ab6e44dcd1e9 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -180,6 +180,10 @@ rff_trace:
*
* 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.
+ *
+ * When user can change the frames always force IRET. That is because
+ * it deals with uncanonical addresses better. SYSRET has trouble
+ * with them due to bugs in both AMD and Intel CPUs.
*/
ENTRY(system_call)
@@ -254,7 +258,10 @@ sysret_signal:
xorl %esi,%esi # oldset -> arg2
call ptregscall_common
1: movl $_TIF_NEED_RESCHED,%edi
- jmp sysret_check
+ /* Use IRET because user could have changed frame. This
+ works because ptregscall_common has called FIXUP_TOP_OF_STACK. */
+ cli
+ jmp int_with_check
badsys:
movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
@@ -280,7 +287,8 @@ tracesys:
call syscall_trace_leave
RESTORE_TOP_OF_STACK %rbx
RESTORE_REST
- jmp ret_from_sys_call
+ /* Use IRET because user could have changed frame */
+ jmp int_ret_from_sys_call
CFI_ENDPROC
/*