lkml.org 
[lkml]   [2014]   [Nov]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[ 02/48] x86_32, entry: Store badsys error code in %eax
    2.6.32-longterm review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Sven Wegener <sven.wegener@stealer.net>

    Commit 554086d ("x86_32, entry: Do syscall exit work on badsys
    (CVE-2014-4508)") introduced a regression in the x86_32 syscall entry
    code, resulting in syscall() not returning proper errors for undefined
    syscalls on CPUs supporting the sysenter feature.

    The following code:

    > int result = syscall(666);
    > printf("result=%d errno=%d error=%s\n", result, errno, strerror(errno));

    results in:

    > result=666 errno=0 error=Success

    Obviously, the syscall return value is the called syscall number, but it
    should have been an ENOSYS error. When run under ptrace it behaves
    correctly, which makes it hard to debug in the wild:

    > result=-1 errno=38 error=Function not implemented

    The %eax register is the return value register. For debugging via ptrace
    the syscall entry code stores the complete register context on the
    stack. The badsys handlers only store the ENOSYS error code in the
    ptrace register set and do not set %eax like a regular syscall handler
    would. The old resume_userspace call chain contains code that clobbers
    %eax and it restores %eax from the ptrace registers afterwards. The same
    goes for the ptrace-enabled call chain. When ptrace is not used, the
    syscall return value is the passed-in syscall number from the untouched
    %eax register.

    Use %eax as the return value register in syscall_badsys and
    sysenter_badsys, like a real syscall handler does, and have the caller
    push the value onto the stack for ptrace access.

    Signed-off-by: Sven Wegener <sven.wegener@stealer.net>
    Link: http://lkml.kernel.org/r/alpine.LNX.2.11.1407221022380.31021@titan.int.lan.stealer.net
    Reviewed-and-tested-by: Andy Lutomirski <luto@amacapital.net>
    Cc: <stable@vger.kernel.org>
    Signed-off-by: H. Peter Anvin <hpa@zytor.com>
    (cherry picked from commit 8142b215501f8b291a108a202b3a053a265b03dd)
    Signed-off-by: Willy Tarreau <w@1wt.eu>
    ---
    arch/x86/kernel/entry_32.S | 9 +++++----
    1 file changed, 5 insertions(+), 4 deletions(-)

    diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
    index 40a0d02..3188ca4 100644
    --- a/arch/x86/kernel/entry_32.S
    +++ b/arch/x86/kernel/entry_32.S
    @@ -447,8 +447,8 @@ sysenter_do_call:
    cmpl $(nr_syscalls), %eax
    jae sysenter_badsys
    call *sys_call_table(,%eax,4)
    - movl %eax,PT_EAX(%esp)
    sysenter_after_call:
    + movl %eax,PT_EAX(%esp)
    LOCKDEP_SYS_EXIT
    DISABLE_INTERRUPTS(CLBR_ANY)
    TRACE_IRQS_OFF
    @@ -528,6 +528,7 @@ ENTRY(system_call)
    jae syscall_badsys
    syscall_call:
    call *sys_call_table(,%eax,4)
    +syscall_after_call:
    movl %eax,PT_EAX(%esp) # store the return value
    syscall_exit:
    LOCKDEP_SYS_EXIT
    @@ -702,12 +703,12 @@ syscall_fault:
    END(syscall_fault)

    syscall_badsys:
    - movl $-ENOSYS,PT_EAX(%esp)
    - jmp syscall_exit
    + movl $-ENOSYS,%eax
    + jmp syscall_after_call
    END(syscall_badsys)

    sysenter_badsys:
    - movl $-ENOSYS,PT_EAX(%esp)
    + movl $-ENOSYS,%eax
    jmp sysenter_after_call
    END(syscall_badsys)
    CFI_ENDPROC
    --
    1.7.12.2.21.g234cd45.dirty




    \
     
     \ /
      Last update: 2014-11-16 23:41    [W:4.116 / U:0.020 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site