Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 2593

kernel-2.6.18-128.1.10.el5.src.rpm

From: Anton Arapov <aarapov@redhat.com>
Subject: [RHEL5.1 patch] RHBZ#297881: CVE-2007-4573 x86_64 syscall 	vulnerability
Date: Mon, 24 Sep 2007 10:46:10 +0200
Bugzilla: 297881
Message-Id: <h8hclk5u3x.fsf@pepelac.englab.brq.redhat.com>
Changelog: [x86_64] syscall vulnerability


BZ#297881:
  https://bugzilla.redhat.com/show_bug.cgi?id=297881

Description: (by Roland McGrath)
  Any user on every x86_64 kernel around can arrange to run code of
their choice in kernel mode without much trouble.  

  AFAIK exactly the mechanism my exploit/test case uses is the only
way to exploit it.  That is, int $0x80 entry from 64-bit mode
(bogus, but allowed) while PTRACE_SYSCALL'd and then ptrace changing
orig_rax so the low bits are in the a valid syscall number range but
some high bits are set.  Et voila, the system call of your choice is
really the kernel-mode call of your choice. 

Upstream status:
  commit# 176df2457ef6207156ca1a40991c54ca01fef567
  - It actually does a little more than strictly needed -- the other
  registers are already zero extended. Also remove the now unnecessary
  and non functional compat task check in ptrace.

Test status:
  Patch has been tested for compilation, bot and tested by problem
  reproducer written by Roland.

==
diff -urpN linux-2.6.18.noarch.orig/arch/x86_64/ia32/ia32entry.S linux-2.6.18.noarch/arch/x86_64/ia32/ia32entry.S
--- linux-2.6.18.noarch.orig/arch/x86_64/ia32/ia32entry.S	2007-09-24 08:21:05.000000000 +0200
+++ linux-2.6.18.noarch/arch/x86_64/ia32/ia32entry.S	2007-09-24 08:38:50.000000000 +0200
@@ -38,6 +38,18 @@
 	movq	%rax,R8(%rsp)
 	.endm
 
+	.macro LOAD_ARGS32 offset
+	movl \offset(%rsp),%r11d
+	movl \offset+8(%rsp),%r10d
+	movl \offset+16(%rsp),%r9d
+	movl \offset+24(%rsp),%r8d
+	movl \offset+40(%rsp),%ecx
+	movl \offset+48(%rsp),%edx
+	movl \offset+56(%rsp),%esi
+	movl \offset+64(%rsp),%edi
+	movl \offset+72(%rsp),%eax
+	.endm
+	
 	.macro CFI_STARTPROC32 simple
 	CFI_STARTPROC	\simple
 	CFI_UNDEFINED	r8
@@ -151,7 +163,7 @@ sysenter_tracesys:
 	movq	$-ENOSYS,RAX(%rsp)	/* really needed? */
 	movq	%rsp,%rdi        /* &pt_regs -> arg1 */
 	call	syscall_trace_enter
-	LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
+	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
 	RESTORE_REST
 	movl	%ebp, %ebp
 	/* no need to do an access_ok check here because rbp has been
@@ -253,7 +265,7 @@ cstar_tracesys:	
 	movq $-ENOSYS,RAX(%rsp)	/* really needed? */
 	movq %rsp,%rdi        /* &pt_regs -> arg1 */
 	call syscall_trace_enter
-	LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
+	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
 	RESTORE_REST
 	movl RSP-ARGOFFSET(%rsp), %r8d
 	/* no need to do an access_ok check here because r8 has been
@@ -330,7 +342,7 @@ ia32_tracesys:			 
 	movq $-ENOSYS,RAX(%rsp)	/* ptrace can change this for a bad syscall */
 	movq %rsp,%rdi        /* &pt_regs -> arg1 */
 	call syscall_trace_enter
-	LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
+	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
 	RESTORE_REST
 	jmp ia32_do_syscall
 END(ia32_syscall)
diff -urpN linux-2.6.18.noarch.orig/arch/x86_64/ia32/ia32entry-xen.S linux-2.6.18.noarch/arch/x86_64/ia32/ia32entry-xen.S
--- linux-2.6.18.noarch.orig/arch/x86_64/ia32/ia32entry-xen.S	2007-09-24 08:21:05.000000000 +0200
+++ linux-2.6.18.noarch/arch/x86_64/ia32/ia32entry-xen.S	2007-09-24 08:42:35.000000000 +0200
@@ -55,6 +55,18 @@
 #define __sti		sti	
 #endif			
 
+	.macro LOAD_ARGS32 offset
+	movl \offset(%rsp),%r11d
+	movl \offset+8(%rsp),%r10d
+	movl \offset+16(%rsp),%r9d
+	movl \offset+24(%rsp),%r8d
+	movl \offset+40(%rsp),%ecx
+	movl \offset+48(%rsp),%edx
+	movl \offset+56(%rsp),%esi
+	movl \offset+64(%rsp),%edi
+	movl \offset+72(%rsp),%eax
+	.endm
+
 	.macro CFI_STARTPROC32 simple
 	CFI_STARTPROC	\simple
 	CFI_UNDEFINED	r8
@@ -171,7 +183,7 @@ sysenter_tracesys:
 	movq	$-ENOSYS,RAX(%rsp)	/* really needed? */
 	movq	%rsp,%rdi        /* &pt_regs -> arg1 */
 	call	syscall_trace_enter
-	LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
+	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
 	RESTORE_REST
 	movl	%ebp, %ebp
 	/* no need to do an access_ok check here because rbp has been
@@ -275,7 +287,7 @@ cstar_tracesys:	
 	movq $-ENOSYS,RAX(%rsp)	/* really needed? */
 	movq %rsp,%rdi        /* &pt_regs -> arg1 */
 	call syscall_trace_enter
-	LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
+	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
 	RESTORE_REST
 	movl RSP-ARGOFFSET(%rsp), %r8d
 	/* no need to do an access_ok check here because r8 has been
@@ -357,7 +369,7 @@ ia32_tracesys:			 
 	movq $-ENOSYS,RAX(%rsp)	/* really needed? */
 	movq %rsp,%rdi        /* &pt_regs -> arg1 */
 	call syscall_trace_enter
-	LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
+	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
 	RESTORE_REST
 	jmp ia32_do_syscall
 END(ia32_syscall)
diff -urpN linux-2.6.18.noarch.orig/arch/x86_64/kernel/ptrace.c linux-2.6.18.noarch/arch/x86_64/kernel/ptrace.c
--- linux-2.6.18.noarch.orig/arch/x86_64/kernel/ptrace.c	2007-09-24 08:21:05.000000000 +0200
+++ linux-2.6.18.noarch/arch/x86_64/kernel/ptrace.c	2007-09-24 08:38:50.000000000 +0200
@@ -234,10 +234,6 @@ static int putreg(struct task_struct *ch
 {
 	unsigned long tmp; 
 	
-	/* Some code in the 64bit emulation may not be 64bit clean.
-	   Don't take any chances. */
-	if (test_tsk_thread_flag(child, TIF_IA32))
-		value &= 0xffffffff;
 	switch (regno) {
 	case offsetof(struct user_regs_struct,fs):
 		if (value && (value & 3) != 3)

-- 
Anton Arapov, <aarapov@redhat.com>
Kernel Development, Red Hat
GPG Key ID: 0x6FA8C812