| From ebbe0d8a449d183fa43b42d84fcb248e25303985 Mon Sep 17 00:00:00 2001 |
| From: Willy Tarreau <w@1wt.eu> |
| Date: Sun, 24 Oct 2021 19:28:15 +0200 |
| Subject: tools/nolibc: i386: fix initial stack alignment |
| |
| From: Willy Tarreau <w@1wt.eu> |
| |
| commit ebbe0d8a449d183fa43b42d84fcb248e25303985 upstream. |
| |
| After re-checking in the spec and comparing stack offsets with glibc, |
| The last pushed argument must be 16-byte aligned (i.e. aligned before the |
| call) so that in the callee esp+4 is multiple of 16, so the principle is |
| the 32-bit equivalent to what Ammar fixed for x86_64. It's possible that |
| 32-bit code using SSE2 or MMX could have been affected. In addition the |
| frame pointer ought to be zero at the deepest level. |
| |
| Link: https://gitlab.com/x86-psABIs/i386-ABI/-/wikis/Intel386-psABI |
| Cc: Ammar Faizi <ammar.faizi@students.amikom.ac.id> |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Willy Tarreau <w@1wt.eu> |
| Signed-off-by: Paul E. McKenney <paulmck@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| tools/include/nolibc/nolibc.h | 10 +++++++++- |
| 1 file changed, 9 insertions(+), 1 deletion(-) |
| |
| --- a/tools/include/nolibc/nolibc.h |
| +++ b/tools/include/nolibc/nolibc.h |
| @@ -583,13 +583,21 @@ struct sys_stat_struct { |
| }) |
| |
| /* startup code */ |
| +/* |
| + * i386 System V ABI mandates: |
| + * 1) last pushed argument must be 16-byte aligned. |
| + * 2) The deepest stack frame should be set to zero |
| + * |
| + */ |
| asm(".section .text\n" |
| ".global _start\n" |
| "_start:\n" |
| "pop %eax\n" // argc (first arg, %eax) |
| "mov %esp, %ebx\n" // argv[] (second arg, %ebx) |
| "lea 4(%ebx,%eax,4),%ecx\n" // then a NULL then envp (third arg, %ecx) |
| - "and $-16, %esp\n" // x86 ABI : esp must be 16-byte aligned when |
| + "xor %ebp, %ebp\n" // zero the stack frame |
| + "and $-16, %esp\n" // x86 ABI : esp must be 16-byte aligned before |
| + "sub $4, %esp\n" // the call instruction (args are aligned) |
| "push %ecx\n" // push all registers on the stack so that we |
| "push %ebx\n" // support both regparm and plain stack modes |
| "push %eax\n" |