lkml.org 
[lkml]   [2021]   [Jun]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.12 070/110] s390/stack: fix possible register corruption with stack switch helper
    Date
    From: Heiko Carstens <hca@linux.ibm.com>

    commit 67147e96a332b56c7206238162771d82467f86c0 upstream.

    The CALL_ON_STACK macro is used to call a C function from inline
    assembly, and therefore must consider the C ABI, which says that only
    registers 6-13, and 15 are non-volatile (restored by the called
    function).

    The inline assembly incorrectly marks all registers used to pass
    parameters to the called function as read-only input operands, instead
    of operands that are read and written to. This might result in
    register corruption depending on usage, compiler, and compile options.

    Fix this by marking all operands used to pass parameters as read/write
    operands. To keep the code simple even register 6, if used, is marked
    as read-write operand.

    Fixes: ff340d2472ec ("s390: add stack switch helper")
    Cc: <stable@kernel.org> # 4.20
    Reviewed-by: Vasily Gorbik <gor@linux.ibm.com>
    Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
    Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    arch/s390/include/asm/stacktrace.h | 18 +++++++++++-------
    1 file changed, 11 insertions(+), 7 deletions(-)

    diff --git a/arch/s390/include/asm/stacktrace.h b/arch/s390/include/asm/stacktrace.h
    index 2b543163d90a..76c6034428be 100644
    --- a/arch/s390/include/asm/stacktrace.h
    +++ b/arch/s390/include/asm/stacktrace.h
    @@ -91,12 +91,16 @@ struct stack_frame {
    CALL_ARGS_4(arg1, arg2, arg3, arg4); \
    register unsigned long r4 asm("6") = (unsigned long)(arg5)

    -#define CALL_FMT_0 "=&d" (r2) :
    -#define CALL_FMT_1 "+&d" (r2) :
    -#define CALL_FMT_2 CALL_FMT_1 "d" (r3),
    -#define CALL_FMT_3 CALL_FMT_2 "d" (r4),
    -#define CALL_FMT_4 CALL_FMT_3 "d" (r5),
    -#define CALL_FMT_5 CALL_FMT_4 "d" (r6),
    +/*
    + * To keep this simple mark register 2-6 as being changed (volatile)
    + * by the called function, even though register 6 is saved/nonvolatile.
    + */
    +#define CALL_FMT_0 "=&d" (r2)
    +#define CALL_FMT_1 "+&d" (r2)
    +#define CALL_FMT_2 CALL_FMT_1, "+&d" (r3)
    +#define CALL_FMT_3 CALL_FMT_2, "+&d" (r4)
    +#define CALL_FMT_4 CALL_FMT_3, "+&d" (r5)
    +#define CALL_FMT_5 CALL_FMT_4, "+&d" (r6)

    #define CALL_CLOBBER_5 "0", "1", "14", "cc", "memory"
    #define CALL_CLOBBER_4 CALL_CLOBBER_5
    @@ -118,7 +122,7 @@ struct stack_frame {
    " brasl 14,%[_fn]\n" \
    " la 15,0(%[_prev])\n" \
    : [_prev] "=&a" (prev), CALL_FMT_##nr \
    - [_stack] "R" (stack), \
    + : [_stack] "R" (stack), \
    [_bc] "i" (offsetof(struct stack_frame, back_chain)), \
    [_frame] "d" (frame), \
    [_fn] "X" (fn) : CALL_CLOBBER_##nr); \
    --
    2.30.2
    \
     
     \ /
      Last update: 2021-06-28 16:24    [W:4.122 / U:0.032 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site