Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

s390/stack: fix possible register corruption with stack switch helper

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>

authored by

Heiko Carstens and committed by
Vasily Gorbik
67147e96 9e3d62d5

+11 -7
+11 -7
arch/s390/include/asm/stacktrace.h
··· 91 91 CALL_ARGS_4(arg1, arg2, arg3, arg4); \ 92 92 register unsigned long r4 asm("6") = (unsigned long)(arg5) 93 93 94 - #define CALL_FMT_0 "=&d" (r2) : 95 - #define CALL_FMT_1 "+&d" (r2) : 96 - #define CALL_FMT_2 CALL_FMT_1 "d" (r3), 97 - #define CALL_FMT_3 CALL_FMT_2 "d" (r4), 98 - #define CALL_FMT_4 CALL_FMT_3 "d" (r5), 99 - #define CALL_FMT_5 CALL_FMT_4 "d" (r6), 94 + /* 95 + * To keep this simple mark register 2-6 as being changed (volatile) 96 + * by the called function, even though register 6 is saved/nonvolatile. 97 + */ 98 + #define CALL_FMT_0 "=&d" (r2) 99 + #define CALL_FMT_1 "+&d" (r2) 100 + #define CALL_FMT_2 CALL_FMT_1, "+&d" (r3) 101 + #define CALL_FMT_3 CALL_FMT_2, "+&d" (r4) 102 + #define CALL_FMT_4 CALL_FMT_3, "+&d" (r5) 103 + #define CALL_FMT_5 CALL_FMT_4, "+&d" (r6) 100 104 101 105 #define CALL_CLOBBER_5 "0", "1", "14", "cc", "memory" 102 106 #define CALL_CLOBBER_4 CALL_CLOBBER_5 ··· 122 118 " brasl 14,%[_fn]\n" \ 123 119 " la 15,0(%[_prev])\n" \ 124 120 : [_prev] "=&a" (prev), CALL_FMT_##nr \ 125 - [_stack] "R" (stack), \ 121 + : [_stack] "R" (stack), \ 126 122 [_bc] "i" (offsetof(struct stack_frame, back_chain)), \ 127 123 [_frame] "d" (frame), \ 128 124 [_fn] "X" (fn) : CALL_CLOBBER_##nr); \