x86_64: Zero extend all registers after ptrace in 32bit entry path.
authorAndi Kleen <ak@suse.de>
Fri, 21 Sep 2007 14:16:18 +0000 (16:16 +0200)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Fri, 21 Sep 2007 16:52:07 +0000 (09:52 -0700)
Strictly it's only needed for eax.

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.

This is CVE-2007-4573

Found by Wojciech Purczynski

Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/x86_64/ia32/ia32entry.S
arch/x86_64/kernel/ptrace.c

index 9382786..18b2318 100644 (file)
        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
@@ -152,7 +164,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
@@ -255,7 +267,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
@@ -334,7 +346,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)
index e83cc67..eea3702 100644 (file)
@@ -232,10 +232,6 @@ static int putreg(struct task_struct *child,
 {
        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)