tools/nolibc: x86-64: Fix startup code bug
authorAmmar Faizi <ammar.faizi@students.amikom.ac.id>
Sun, 24 Oct 2021 17:28:14 +0000 (19:28 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 27 Jan 2022 09:53:41 +0000 (10:53 +0100)
commit06f7528d641bf685dd9bc55e85afbf7c3843b8de
treeb5a5fe4fa0e9b5226eab6e46e51b2410b2b418e8
parent98259dd54e8e0b22400bfe858569423ee4f031f3
tools/nolibc: x86-64: Fix startup code bug

commit 937ed91c712273131de6d2a02caafd3ee84e0c72 upstream.

Before this patch, the `_start` function looks like this:
```
0000000000001170 <_start>:
    1170: pop    %rdi
    1171: mov    %rsp,%rsi
    1174: lea    0x8(%rsi,%rdi,8),%rdx
    1179: and    $0xfffffffffffffff0,%rsp
    117d: sub    $0x8,%rsp
    1181: call   1000 <main>
    1186: movzbq %al,%rdi
    118a: mov    $0x3c,%rax
    1191: syscall
    1193: hlt
    1194: data16 cs nopw 0x0(%rax,%rax,1)
    119f: nop
```
Note the "and" to %rsp with $-16, it makes the %rsp be 16-byte aligned,
but then there is a "sub" with $0x8 which makes the %rsp no longer
16-byte aligned, then it calls main. That's the bug!

What actually the x86-64 System V ABI mandates is that right before the
"call", the %rsp must be 16-byte aligned, not after the "call". So the
"sub" with $0x8 here breaks the alignment. Remove it.

An example where this rule matters is when the callee needs to align
its stack at 16-byte for aligned move instruction, like `movdqa` and
`movaps`. If the callee can't align its stack properly, it will result
in segmentation fault.

x86-64 System V ABI also mandates the deepest stack frame should be
zero. Just to be safe, let's zero the %rbp on startup as the content
of %rbp may be unspecified when the program starts. Now it looks like
this:
```
0000000000001170 <_start>:
    1170: pop    %rdi
    1171: mov    %rsp,%rsi
    1174: lea    0x8(%rsi,%rdi,8),%rdx
    1179: xor    %ebp,%ebp                # zero the %rbp
    117b: and    $0xfffffffffffffff0,%rsp # align the %rsp
    117f: call   1000 <main>
    1184: movzbq %al,%rdi
    1188: mov    $0x3c,%rax
    118f: syscall
    1191: hlt
    1192: data16 cs nopw 0x0(%rax,%rax,1)
    119d: nopl   (%rax)
```

Cc: Bedirhan KURT <windowz414@gnuweeb.org>
Cc: Louvian Lyndal <louvianlyndal@gmail.com>
Reported-by: Peter Cordes <peter@cordes.ca>
Signed-off-by: Ammar Faizi <ammar.faizi@students.amikom.ac.id>
[wt: I did this on purpose due to a misunderstanding of the spec, other
     archs will thus have to be rechecked, particularly i386]
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