lkml.org 
[lkml]   [2020]   [Jun]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.7 441/477] s390: fix syscall_get_error for compat processes
    Date
    From: Dmitry V. Levin <ldv@altlinux.org>

    commit b3583fca5fb654af2cfc1c08259abb9728272538 upstream.

    If both the tracer and the tracee are compat processes, and gprs[2]
    is assigned a value by __poke_user_compat, then the higher 32 bits
    of gprs[2] are cleared, IS_ERR_VALUE() always returns false, and
    syscall_get_error() always returns 0.

    Fix the implementation by sign-extending the value for compat processes
    the same way as x86 implementation does.

    The bug was exposed to user space by commit 201766a20e30f ("ptrace: add
    PTRACE_GET_SYSCALL_INFO request") and detected by strace test suite.

    This change fixes strace syscall tampering on s390.

    Link: https://lkml.kernel.org/r/20200602180051.GA2427@altlinux.org
    Fixes: 753c4dd6a2fa2 ("[S390] ptrace changes")
    Cc: Elvira Khabirova <lineprinter@altlinux.org>
    Cc: stable@vger.kernel.org # v2.6.28+
    Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
    Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
    Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h
    index f073292e9fdb..d9d5de0f67ff 100644
    --- a/arch/s390/include/asm/syscall.h
    +++ b/arch/s390/include/asm/syscall.h
    @@ -33,7 +33,17 @@ static inline void syscall_rollback(struct task_struct *task,
    static inline long syscall_get_error(struct task_struct *task,
    struct pt_regs *regs)
    {
    - return IS_ERR_VALUE(regs->gprs[2]) ? regs->gprs[2] : 0;
    + unsigned long error = regs->gprs[2];
    +#ifdef CONFIG_COMPAT
    + if (test_tsk_thread_flag(task, TIF_31BIT)) {
    + /*
    + * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
    + * and will match correctly in comparisons.
    + */
    + error = (long)(int)error;
    + }
    +#endif
    + return IS_ERR_VALUE(error) ? error : 0;
    }

    static inline long syscall_get_return_value(struct task_struct *task,

    \
     
     \ /
      Last update: 2020-06-23 23:24    [W:2.436 / U:1.084 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site