From: Jiri Olsa <jolsa@redhat.com> Date: Tue, 12 May 2009 16:00:56 +0200 Subject: [x86_64] 32-bit ptrace emulation mishandles 6th arg Message-id: 20090512140056.GA3453@jolsa.englab.brq.redhat.com O-Subject: [PATCH RHEL5.4] BZ495125 x86_64 - 32-bit ptrace emulation mishandles 6th arg Bugzilla: 495125 RH-Acked-by: Vitaly Mayatskikh <vmayatsk@redhat.com> RH-Acked-by: Chris Lalancette <clalance@redhat.com> Bugzilla: ========= https://bugzilla.redhat.com/show_bug.cgi?id=495125 Description: ============ On x86_64, strace is reporting invalid values of the 6th syscall argument when run on 32-bit executables. Upstream status: ================ x86 - 32-bit ptrace emulation mishandles 6th arg http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=ecd744eec3aa8bbc949ec04ed3fbf7ecb2958a0e x86-64: slightly stream-line 32-bit syscall entry code http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=295286a89107c353b9677bc604361c537fd6a1c0 Test status of the patch: ========================= tested with attached reproducer on AMD and INTEL CPUs wbr, jirka diff --git a/arch/x86_64/ia32/ia32entry-xen.S b/arch/x86_64/ia32/ia32entry-xen.S index 8aa41fb..b0838f8 100644 --- a/arch/x86_64/ia32/ia32entry-xen.S +++ b/arch/x86_64/ia32/ia32entry-xen.S @@ -32,11 +32,11 @@ .endm /* clobbers %eax */ - .macro CLEAR_RREGS + .macro CLEAR_RREGS _r9=rax xorl %eax,%eax movq %rax,R11(%rsp) movq %rax,R10(%rsp) - movq %rax,R9(%rsp) + movq %\_r9,R9(%rsp) movq %rax,R8(%rsp) .endm @@ -55,11 +55,10 @@ #define __sti sti #endif - .macro LOAD_ARGS32 offset - movl \offset(%rsp),%r11d - movl \offset+8(%rsp),%r10d + .macro LOAD_ARGS32 offset, _r9=0 + .if \_r9 movl \offset+16(%rsp),%r9d - movl \offset+24(%rsp),%r8d + .endif movl \offset+40(%rsp),%ecx movl \offset+48(%rsp),%edx movl \offset+56(%rsp),%esi @@ -136,7 +135,7 @@ ENTRY(ia32_sysenter_target) SAVE_ARGS 0,0,0 /* no need to do an access_ok check here because rbp has been 32bit zero extended */ -1: movl (%rbp),%r9d +1: movl (%rbp),%ebp .section __ex_table,"a" .quad 1b,ia32_badarg .previous @@ -148,7 +147,7 @@ ENTRY(ia32_sysenter_target) sysenter_do_call: cmpl $(IA32_NR_syscalls-1),%eax ja ia32_badsys - IA32_ARG_FIXUP 1 + IA32_ARG_FIXUP call *ia32_sys_call_table(,%rax,8) movq %rax,RAX-ARGOFFSET(%rsp) GET_THREAD_INFO(%r10) @@ -185,13 +184,6 @@ sysenter_tracesys: call syscall_trace_enter 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 - 32bit zero extended */ -1: movl (%rbp),%r9d - .section __ex_table,"a" - .quad 1b,ia32_badarg - .previous jmp sysenter_do_call CFI_ENDPROC ENDPROC(ia32_sysenter_target) @@ -282,20 +274,15 @@ cstar_do_call: cstar_tracesys: CFI_RESTORE_STATE + xchgl %r9d,%ebp SAVE_REST - CLEAR_RREGS + CLEAR_RREGS r9 movq $-ENOSYS,RAX(%rsp) /* really needed? */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter - LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ + LOAD_ARGS32 ARGOFFSET 1 /* 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 - 32bit zero extended */ -1: movl (%r8),%r9d - .section __ex_table,"a" - .quad 1b,ia32_badarg - .previous + xchgl %ebp,%r9d jmp cstar_do_call END(ia32_cstar_target) diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S index 50ca6d6..b365454 100644 --- a/arch/x86_64/ia32/ia32entry.S +++ b/arch/x86_64/ia32/ia32entry.S @@ -30,19 +30,18 @@ .endm /* clobbers %eax */ - .macro CLEAR_RREGS + .macro CLEAR_RREGS _r9=rax xorl %eax,%eax movq %rax,R11(%rsp) movq %rax,R10(%rsp) - movq %rax,R9(%rsp) + movq %\_r9,R9(%rsp) movq %rax,R8(%rsp) .endm - .macro LOAD_ARGS32 offset - movl \offset(%rsp),%r11d - movl \offset+8(%rsp),%r10d + .macro LOAD_ARGS32 offset, _r9=0 + .if \_r9 movl \offset+16(%rsp),%r9d - movl \offset+24(%rsp),%r8d + .endif movl \offset+40(%rsp),%ecx movl \offset+48(%rsp),%edx movl \offset+56(%rsp),%esi @@ -118,7 +117,7 @@ ENTRY(ia32_sysenter_target) SAVE_ARGS 0,0,0 /* no need to do an access_ok check here because rbp has been 32bit zero extended */ -1: movl (%rbp),%r9d +1: movl (%rbp),%ebp .section __ex_table,"a" .quad 1b,ia32_badarg .previous @@ -130,7 +129,7 @@ ENTRY(ia32_sysenter_target) sysenter_do_call: cmpl $(IA32_NR_syscalls-1),%eax ja ia32_badsys - IA32_ARG_FIXUP 1 + IA32_ARG_FIXUP call *ia32_sys_call_table(,%rax,8) movq %rax,RAX-ARGOFFSET(%rsp) GET_THREAD_INFO(%r10) @@ -165,13 +164,6 @@ sysenter_tracesys: call syscall_trace_enter 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 - 32bit zero extended */ -1: movl (%rbp),%r9d - .section __ex_table,"a" - .quad 1b,ia32_badarg - .previous jmp sysenter_do_call CFI_ENDPROC ENDPROC(ia32_sysenter_target) @@ -260,20 +252,15 @@ cstar_do_call: cstar_tracesys: CFI_RESTORE_STATE + xchgl %r9d,%ebp SAVE_REST - CLEAR_RREGS + CLEAR_RREGS r9 movq $-ENOSYS,RAX(%rsp) /* really needed? */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter - LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ + LOAD_ARGS32 ARGOFFSET 1 /* 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 - 32bit zero extended */ -1: movl (%r8),%r9d - .section __ex_table,"a" - .quad 1b,ia32_badarg - .previous + xchgl %ebp,%r9d jmp cstar_do_call END(ia32_cstar_target)