Merge pull request #20777 from alexrp/start-abi-hardening

`start`: Harden against program interpreters that don't adhere fully to the ABI
This commit is contained in:
Andrew Kelley 2024-07-25 16:29:08 -07:00 committed by GitHub
commit ed847b85c2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -272,6 +272,12 @@ fn _start() callconv(.Naked) noreturn {
: [tos] "={rax}" (-> *std.os.plan9.Tos),
);
}
// Note that we maintain a very low level of trust with regards to ABI guarantees at this point.
// We will redundantly align the stack, clear the link register, etc. While e.g. the Linux
// kernel is usually good about upholding the ABI guarantees, the same cannot be said of dynamic
// linkers; musl's ldso, for example, opts to not align the stack when invoking the dynamic
// linker explicitly.
asm volatile (switch (native_arch) {
.x86_64 =>
\\ xorl %%ebp, %%ebp
@ -291,6 +297,7 @@ fn _start() callconv(.Naked) noreturn {
\\ mov fp, #0
\\ mov lr, #0
\\ mov x0, sp
\\ and sp, x0, #-16
\\ b %[posixCallMainAndExit]
,
.arm, .armeb, .thumb, .thumbeb =>
@ -322,30 +329,23 @@ fn _start() callconv(.Naked) noreturn {
\\ jsr (%%pc, %%a0)
,
.mips, .mipsel =>
// The lr is already zeroed on entry, as specified by the ABI.
\\ addiu $fp, $zero, 0
\\ move $fp, $0
\\ move $ra, $0
\\ move $a0, $sp
\\ .set push
\\ .set noat
\\ addiu $1, $zero, -16
\\ and $sp, $sp, $1
\\ .set pop
\\ and $sp, -8
\\ j %[posixCallMainAndExit]
,
.mips64, .mips64el =>
// The lr is already zeroed on entry, as specified by the ABI.
\\ addiu $fp, $zero, 0
\\ move $fp, $0
\\ move $ra, $0
\\ move $a0, $sp
\\ .set push
\\ .set noat
\\ daddiu $1, $zero, -16
\\ and $sp, $sp, $1
\\ .set pop
\\ and $sp, -16
\\ j %[posixCallMainAndExit]
,
.powerpc, .powerpcle =>
// Setup the initial stack frame and clear the back chain pointer.
// Set up the initial stack frame, and clear the back chain pointer.
\\ mr 3, 1
\\ clrrwi 1, 1, 4
\\ li 0, 0
\\ stwu 1, -16(1)
\\ stw 0, 0(1)
@ -353,7 +353,7 @@ fn _start() callconv(.Naked) noreturn {
\\ b %[posixCallMainAndExit]
,
.powerpc64, .powerpc64le =>
// Setup the initial stack frame and clear the back chain pointer.
// Set up the ToC and initial stack frame, and clear the back chain pointer.
\\ addis 2, 12, .TOC. - %[_start]@ha
\\ addi 2, 2, .TOC. - %[_start]@l
\\ mr 3, 1
@ -365,18 +365,22 @@ fn _start() callconv(.Naked) noreturn {
,
.s390x =>
// Set up the stack frame (register save area and cleared back-chain slot).
// Note: Stack pointer is guaranteed by ABI to be 8-byte aligned as required.
\\ lgr %r2, %r15
\\ aghi %r15, -160
\\ lghi %r0, 0
\\ stg %r0, 0(%r15)
\\ lgr %%r2, %%r15
\\ lghi %%r0, -16
\\ ngr %%r15, %%r0
\\ aghi %%r15, -160
\\ lghi %%r0, 0
\\ stg %%r0, 0(%%r15)
\\ jg %[posixCallMainAndExit]
,
.sparc64 =>
// argc is stored after a register window (16 registers) plus stack bias
\\ mov %%g0, %%i6
\\ add %%o6, 2175, %%l0
\\ mov %%l0, %%o0
// argc is stored after a register window (16 registers * 8 bytes) plus the stack bias
// (2047 bytes).
\\ mov %%g0, %%fp
\\ add %%sp, 2175, %%o0
\\ add %%sp, 2047, %%sp
\\ and %%sp, -16, %%sp
\\ sub %%sp, 2047, %%sp
\\ ba,a %[posixCallMainAndExit]
,
else => @compileError("unsupported arch"),