| From: Andreas Schwab <schwab@linux-m68k.org> |
| Date: Wed, 23 Sep 2015 23:12:09 +0200 |
| Subject: m68k: Define asmlinkage_protect |
| |
| commit 8474ba74193d302e8340dddd1e16c85cc4b98caf upstream. |
| |
| Make sure the compiler does not modify arguments of syscall functions. |
| This can happen if the compiler generates a tailcall to another |
| function. For example, without asmlinkage_protect sys_openat is compiled |
| into this function: |
| |
| sys_openat: |
| clr.l %d0 |
| move.w 18(%sp),%d0 |
| move.l %d0,16(%sp) |
| jbra do_sys_open |
| |
| Note how the fourth argument is modified in place, modifying the register |
| %d4 that gets restored from this stack slot when the function returns to |
| user-space. The caller may expect the register to be unmodified across |
| system calls. |
| |
| Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> |
| Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| arch/m68k/include/asm/linkage.h | 30 ++++++++++++++++++++++++++++++ |
| 1 file changed, 30 insertions(+) |
| |
| --- a/arch/m68k/include/asm/linkage.h |
| +++ b/arch/m68k/include/asm/linkage.h |
| @@ -4,4 +4,34 @@ |
| #define __ALIGN .align 4 |
| #define __ALIGN_STR ".align 4" |
| |
| +/* |
| + * Make sure the compiler doesn't do anything stupid with the |
| + * arguments on the stack - they are owned by the *caller*, not |
| + * the callee. This just fools gcc into not spilling into them, |
| + * and keeps it from doing tailcall recursion and/or using the |
| + * stack slots for temporaries, since they are live and "used" |
| + * all the way to the end of the function. |
| + */ |
| +#define asmlinkage_protect(n, ret, args...) \ |
| + __asmlinkage_protect##n(ret, ##args) |
| +#define __asmlinkage_protect_n(ret, args...) \ |
| + __asm__ __volatile__ ("" : "=r" (ret) : "0" (ret), ##args) |
| +#define __asmlinkage_protect0(ret) \ |
| + __asmlinkage_protect_n(ret) |
| +#define __asmlinkage_protect1(ret, arg1) \ |
| + __asmlinkage_protect_n(ret, "m" (arg1)) |
| +#define __asmlinkage_protect2(ret, arg1, arg2) \ |
| + __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2)) |
| +#define __asmlinkage_protect3(ret, arg1, arg2, arg3) \ |
| + __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3)) |
| +#define __asmlinkage_protect4(ret, arg1, arg2, arg3, arg4) \ |
| + __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3), \ |
| + "m" (arg4)) |
| +#define __asmlinkage_protect5(ret, arg1, arg2, arg3, arg4, arg5) \ |
| + __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3), \ |
| + "m" (arg4), "m" (arg5)) |
| +#define __asmlinkage_protect6(ret, arg1, arg2, arg3, arg4, arg5, arg6) \ |
| + __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3), \ |
| + "m" (arg4), "m" (arg5), "m" (arg6)) |
| + |
| #endif |