authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-07-25 16:29:08-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-07-25 16:29:08-07:00
loged847b85c284783c20efd4c4a565138b79d33e2c
tree115655c29ff2f77ba4093092de23db8a33a402ae
parent3344ed8b8f9142fa547f3d8b598acdb561055a52
parentfff5ce053fcfaf0cf3fea815b4c50c000036ff5b
signaturebadge-check Signed by PGP key B5690EEEBB952194

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

`start`: Harden against program interpreters that don't adhere fully to the ABI

1 files changed, 29 insertions(+), 25 deletions(-)

lib/std/start.zig+29-25
......@@ -272,6 +272,12 @@ fn _start() callconv(.Naked) noreturn {
272272 : [tos] "={rax}" (-> *std.os.plan9.Tos),
273273 );
274274 }
275
276 // Note that we maintain a very low level of trust with regards to ABI guarantees at this point.
277 // We will redundantly align the stack, clear the link register, etc. While e.g. the Linux
278 // kernel is usually good about upholding the ABI guarantees, the same cannot be said of dynamic
279 // linkers; musl's ldso, for example, opts to not align the stack when invoking the dynamic
280 // linker explicitly.
275281 asm volatile (switch (native_arch) {
276282 .x86_64 =>
277283 \\ xorl %%ebp, %%ebp
......@@ -291,6 +297,7 @@ fn _start() callconv(.Naked) noreturn {
291297 \\ mov fp, #0
292298 \\ mov lr, #0
293299 \\ mov x0, sp
300 \\ and sp, x0, #-16
294301 \\ b %[posixCallMainAndExit]
295302 ,
296303 .arm, .armeb, .thumb, .thumbeb =>
......@@ -322,30 +329,23 @@ fn _start() callconv(.Naked) noreturn {
322329 \\ jsr (%%pc, %%a0)
323330 ,
324331 .mips, .mipsel =>
325 // The lr is already zeroed on entry, as specified by the ABI.
326 \\ addiu $fp, $zero, 0
332 \\ move $fp, $0
333 \\ move $ra, $0
327334 \\ move $a0, $sp
328 \\ .set push
329 \\ .set noat
330 \\ addiu $1, $zero, -16
331 \\ and $sp, $sp, $1
332 \\ .set pop
335 \\ and $sp, -8
333336 \\ j %[posixCallMainAndExit]
334337 ,
335338 .mips64, .mips64el =>
336 // The lr is already zeroed on entry, as specified by the ABI.
337 \\ addiu $fp, $zero, 0
339 \\ move $fp, $0
340 \\ move $ra, $0
338341 \\ move $a0, $sp
339 \\ .set push
340 \\ .set noat
341 \\ daddiu $1, $zero, -16
342 \\ and $sp, $sp, $1
343 \\ .set pop
342 \\ and $sp, -16
344343 \\ j %[posixCallMainAndExit]
345344 ,
346345 .powerpc, .powerpcle =>
347 // Setup the initial stack frame and clear the back chain pointer.
346 // Set up the initial stack frame, and clear the back chain pointer.
348347 \\ mr 3, 1
348 \\ clrrwi 1, 1, 4
349349 \\ li 0, 0
350350 \\ stwu 1, -16(1)
351351 \\ stw 0, 0(1)
......@@ -353,7 +353,7 @@ fn _start() callconv(.Naked) noreturn {
353353 \\ b %[posixCallMainAndExit]
354354 ,
355355 .powerpc64, .powerpc64le =>
356 // Setup the initial stack frame and clear the back chain pointer.
356 // Set up the ToC and initial stack frame, and clear the back chain pointer.
357357 \\ addis 2, 12, .TOC. - %[_start]@ha
358358 \\ addi 2, 2, .TOC. - %[_start]@l
359359 \\ mr 3, 1
......@@ -365,18 +365,22 @@ fn _start() callconv(.Naked) noreturn {
365365 ,
366366 .s390x =>
367367 // Set up the stack frame (register save area and cleared back-chain slot).
368 // Note: Stack pointer is guaranteed by ABI to be 8-byte aligned as required.
369 \\ lgr %r2, %r15
370 \\ aghi %r15, -160
371 \\ lghi %r0, 0
372 \\ stg %r0, 0(%r15)
368 \\ lgr %%r2, %%r15
369 \\ lghi %%r0, -16
370 \\ ngr %%r15, %%r0
371 \\ aghi %%r15, -160
372 \\ lghi %%r0, 0
373 \\ stg %%r0, 0(%%r15)
373374 \\ jg %[posixCallMainAndExit]
374375 ,
375376 .sparc64 =>
376 // argc is stored after a register window (16 registers) plus stack bias
377 \\ mov %%g0, %%i6
378 \\ add %%o6, 2175, %%l0
379 \\ mov %%l0, %%o0
377 // argc is stored after a register window (16 registers * 8 bytes) plus the stack bias
378 // (2047 bytes).
379 \\ mov %%g0, %%fp
380 \\ add %%sp, 2175, %%o0
381 \\ add %%sp, 2047, %%sp
382 \\ and %%sp, -16, %%sp
383 \\ sub %%sp, 2047, %%sp
380384 \\ ba,a %[posixCallMainAndExit]
381385 ,
382386 else => @compileError("unsupported arch"),