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 {...@@ -272,6 +272,12 @@ fn _start() callconv(.Naked) noreturn {
272 : [tos] "={rax}" (-> *std.os.plan9.Tos),272 : [tos] "={rax}" (-> *std.os.plan9.Tos),
273 );273 );
274 }274 }
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.
275 asm volatile (switch (native_arch) {281 asm volatile (switch (native_arch) {
276 .x86_64 =>282 .x86_64 =>
277 \\ xorl %%ebp, %%ebp283 \\ xorl %%ebp, %%ebp
...@@ -291,6 +297,7 @@ fn _start() callconv(.Naked) noreturn {...@@ -291,6 +297,7 @@ fn _start() callconv(.Naked) noreturn {
291 \\ mov fp, #0297 \\ mov fp, #0
292 \\ mov lr, #0298 \\ mov lr, #0
293 \\ mov x0, sp299 \\ mov x0, sp
300 \\ and sp, x0, #-16
294 \\ b %[posixCallMainAndExit]301 \\ b %[posixCallMainAndExit]
295 ,302 ,
296 .arm, .armeb, .thumb, .thumbeb =>303 .arm, .armeb, .thumb, .thumbeb =>
...@@ -322,30 +329,23 @@ fn _start() callconv(.Naked) noreturn {...@@ -322,30 +329,23 @@ fn _start() callconv(.Naked) noreturn {
322 \\ jsr (%%pc, %%a0)329 \\ jsr (%%pc, %%a0)
323 ,330 ,
324 .mips, .mipsel =>331 .mips, .mipsel =>
325 // The lr is already zeroed on entry, as specified by the ABI.332 \\ move $fp, $0
326 \\ addiu $fp, $zero, 0333 \\ move $ra, $0
327 \\ move $a0, $sp334 \\ move $a0, $sp
328 \\ .set push335 \\ and $sp, -8
329 \\ .set noat
330 \\ addiu $1, $zero, -16
331 \\ and $sp, $sp, $1
332 \\ .set pop
333 \\ j %[posixCallMainAndExit]336 \\ j %[posixCallMainAndExit]
334 ,337 ,
335 .mips64, .mips64el =>338 .mips64, .mips64el =>
336 // The lr is already zeroed on entry, as specified by the ABI.339 \\ move $fp, $0
337 \\ addiu $fp, $zero, 0340 \\ move $ra, $0
338 \\ move $a0, $sp341 \\ move $a0, $sp
339 \\ .set push342 \\ and $sp, -16
340 \\ .set noat
341 \\ daddiu $1, $zero, -16
342 \\ and $sp, $sp, $1
343 \\ .set pop
344 \\ j %[posixCallMainAndExit]343 \\ j %[posixCallMainAndExit]
345 ,344 ,
346 .powerpc, .powerpcle =>345 .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.
348 \\ mr 3, 1347 \\ mr 3, 1
348 \\ clrrwi 1, 1, 4
349 \\ li 0, 0349 \\ li 0, 0
350 \\ stwu 1, -16(1)350 \\ stwu 1, -16(1)
351 \\ stw 0, 0(1)351 \\ stw 0, 0(1)
...@@ -353,7 +353,7 @@ fn _start() callconv(.Naked) noreturn {...@@ -353,7 +353,7 @@ fn _start() callconv(.Naked) noreturn {
353 \\ b %[posixCallMainAndExit]353 \\ b %[posixCallMainAndExit]
354 ,354 ,
355 .powerpc64, .powerpc64le =>355 .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.
357 \\ addis 2, 12, .TOC. - %[_start]@ha357 \\ addis 2, 12, .TOC. - %[_start]@ha
358 \\ addi 2, 2, .TOC. - %[_start]@l358 \\ addi 2, 2, .TOC. - %[_start]@l
359 \\ mr 3, 1359 \\ mr 3, 1
...@@ -365,18 +365,22 @@ fn _start() callconv(.Naked) noreturn {...@@ -365,18 +365,22 @@ fn _start() callconv(.Naked) noreturn {
365 ,365 ,
366 .s390x =>366 .s390x =>
367 // Set up the stack frame (register save area and cleared back-chain slot).367 // 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.368 \\ lgr %%r2, %%r15
369 \\ lgr %r2, %r15369 \\ lghi %%r0, -16
370 \\ aghi %r15, -160370 \\ ngr %%r15, %%r0
371 \\ lghi %r0, 0371 \\ aghi %%r15, -160
372 \\ stg %r0, 0(%r15)372 \\ lghi %%r0, 0
373 \\ stg %%r0, 0(%%r15)
373 \\ jg %[posixCallMainAndExit]374 \\ jg %[posixCallMainAndExit]
374 ,375 ,
375 .sparc64 =>376 .sparc64 =>
376 // argc is stored after a register window (16 registers) plus stack bias377 // argc is stored after a register window (16 registers * 8 bytes) plus the stack bias
377 \\ mov %%g0, %%i6378 // (2047 bytes).
378 \\ add %%o6, 2175, %%l0379 \\ mov %%g0, %%fp
379 \\ mov %%l0, %%o0380 \\ add %%sp, 2175, %%o0
381 \\ add %%sp, 2047, %%sp
382 \\ and %%sp, -16, %%sp
383 \\ sub %%sp, 2047, %%sp
380 \\ ba,a %[posixCallMainAndExit]384 \\ ba,a %[posixCallMainAndExit]
381 ,385 ,
382 else => @compileError("unsupported arch"),386 else => @compileError("unsupported arch"),