Skip to content
/ zig Public
forked from ziglang/zig

Commit

Permalink
std.os.linux: Add unwinding protection in clone() implementations.
Browse files Browse the repository at this point in the history
Whatever was in the frame pointer register prior to clone() will no longer be
valid in the child process, so zero it to protect FP-based unwinders. Similarly,
mark the link register as undefined to protect DWARF-based unwinders.

This is only zeroing the frame pointer(s) on Arm/Thumb because of an LLVM
assembler bug: llvm/llvm-project#115891
  • Loading branch information
alexrp committed Nov 20, 2024
1 parent dd835d6 commit 84718aa
Show file tree
Hide file tree
Showing 14 changed files with 79 additions and 21 deletions.
7 changes: 6 additions & 1 deletion lib/std/os/linux/aarch64.zig
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,13 @@ pub fn clone() callconv(.Naked) usize {
\\ cbz x0,1f
\\ // parent
\\ ret
\\
\\ // child
\\1: ldp x1,x0,[sp],#16
\\1: .cfi_undefined lr
\\ mov fp, 0
\\ mov lr, 0
\\
\\ ldp x1,x0,[sp],#16
\\ blr x1
\\ mov x8,#93 // SYS_exit
\\ svc #0
Expand Down
11 changes: 8 additions & 3 deletions lib/std/os/linux/arm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,16 @@ pub fn clone() callconv(.Naked) usize {
\\ ldmfd sp!,{r4,r5,r6,r7}
\\ bx lr
\\
\\1: mov r0,r6
\\ // https://github.com/llvm/llvm-project/issues/115891
\\1: mov r7, #0
\\ mov r11, #0
\\ mov lr, #0
\\
\\ mov r0,r6
\\ bl 3f
\\2: mov r7,#1 // SYS_exit
\\ mov r7,#1 // SYS_exit
\\ svc 0
\\ b 2b
\\
\\3: bx r5
);
}
Expand Down
4 changes: 4 additions & 0 deletions lib/std/os/linux/hexagon.zig
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ pub fn clone() callconv(.Naked) usize {
\\ p0 = cmp.eq(r0, #0)
\\ if (!p0) dealloc_return
\\
\\ .cfi_undefined r31
\\ r30 = #0
\\ r31 = #0
\\
\\ r0 = r10
\\ callr r11
\\
Expand Down
4 changes: 4 additions & 0 deletions lib/std/os/linux/loongarch64.zig
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ pub fn clone() callconv(.Naked) usize {
\\ beqz $a0, 1f # whether child process
\\ jirl $zero, $ra, 0 # parent process return
\\1:
\\ .cfi_undefined 1
\\ move $fp, $zero
\\ move $ra, $zero
\\
\\ ld.d $t8, $sp, 0 # function pointer
\\ ld.d $a0, $sp, 8 # argument pointer
\\ jirl $ra, $t8, 0 # call the user's function
Expand Down
4 changes: 4 additions & 0 deletions lib/std/os/linux/mips.zig
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,10 @@ pub fn clone() callconv(.Naked) usize {
\\ jr $ra
\\ nop
\\1:
\\ .cfi_undefined $ra
\\ move $fp, $zero
\\ move $ra, $zero
\\
\\ lw $25, 0($sp)
\\ lw $4, 4($sp)
\\ jalr $25
Expand Down
4 changes: 4 additions & 0 deletions lib/std/os/linux/mips64.zig
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@ pub fn clone() callconv(.Naked) usize {
\\ jr $ra
\\ nop
\\1:
\\ .cfi_undefined $ra
\\ move $fp, $zero
\\ move $ra, $zero
\\
\\ ld $25, 0($sp)
\\ ld $4, 8($sp)
\\ jalr $25
Expand Down
26 changes: 15 additions & 11 deletions lib/std/os/linux/powerpc.zig
Original file line number Diff line number Diff line change
Expand Up @@ -133,14 +133,14 @@ pub fn clone() callconv(.Naked) usize {
// syscall(SYS_clone, flags, stack, ptid, tls, ctid)
// 0 3, 4, 5, 6, 7
asm volatile (
\\ # store non-volatile regs r30, r31 on stack in order to put our
\\ # store non-volatile regs r29, r30 on stack in order to put our
\\ # start func and its arg there
\\ stwu 30, -16(1)
\\ stw 31, 4(1)
\\ stwu 29, -16(1)
\\ stw 30, 4(1)
\\
\\ # save r3 (func) into r30, and r6(arg) into r31
\\ mr 30, 3
\\ mr 31, 6
\\ # save r3 (func) into r29, and r6(arg) into r30
\\ mr 29, 3
\\ mr 30, 6
\\
\\ # create initial stack frame for new thread
\\ clrrwi 4, 4, 4
Expand Down Expand Up @@ -171,10 +171,14 @@ pub fn clone() callconv(.Naked) usize {
\\ bne cr7, 2f
\\
\\ #else: we're the child
\\ .cfi_undefined lr
\\ li 31, 0
\\ mtlr 0
\\
\\ #call funcptr: move arg (d) into r3
\\ mr 3, 31
\\ #move r30 (funcptr) into CTR reg
\\ mtctr 30
\\ mr 3, 30
\\ #move r29 (funcptr) into CTR reg
\\ mtctr 29
\\ # call CTR reg
\\ bctrl
\\ # mov SYS_exit into r0 (the exit param is already in r3)
Expand All @@ -184,8 +188,8 @@ pub fn clone() callconv(.Naked) usize {
\\ 2:
\\
\\ # restore stack
\\ lwz 30, 0(1)
\\ lwz 31, 4(1)
\\ lwz 29, 0(1)
\\ lwz 30, 4(1)
\\ addi 1, 1, 16
\\
\\ blr
Expand Down
7 changes: 6 additions & 1 deletion lib/std/os/linux/powerpc64.zig
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,12 @@ pub fn clone() callconv(.Naked) usize {
\\ cmpwi cr7, 3, 0
\\ bnelr cr7
\\
\\ # we're the child. call fn(arg)
\\ # we're the child
\\ .cfi_undefined lr
\\ li 31, 0
\\ mtlr 0
\\
\\ # call fn(arg)
\\ ld 3, 16(1)
\\ ld 12, 8(1)
\\ mtctr 12
Expand Down
6 changes: 5 additions & 1 deletion lib/std/os/linux/riscv32.zig
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,11 @@ pub fn clone() callconv(.Naked) usize {
\\ ret
\\
\\ # Child
\\1: lw a1, 0(sp)
\\1: .cfi_undefined ra
\\ mv fp, zero
\\ mv ra, zero
\\
\\ lw a1, 0(sp)
\\ lw a0, 4(sp)
\\ jalr a1
\\
Expand Down
6 changes: 5 additions & 1 deletion lib/std/os/linux/riscv64.zig
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,11 @@ pub fn clone() callconv(.Naked) usize {
\\ ret
\\
\\ # Child
\\1: ld a1, 0(sp)
\\1: .cfi_undefined ra
\\ mv fp, zero
\\ mv ra, zero
\\
\\ ld a1, 0(sp)
\\ ld a0, 8(sp)
\\ jalr a1
\\
Expand Down
7 changes: 6 additions & 1 deletion lib/std/os/linux/s390x.zig
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,12 @@ pub fn clone() callconv(.Naked) usize {
\\ltgr %%r2, %%r2
\\bnzr %%r14
\\
\\# we're the child. call fn(arg)
\\# we're the child
\\.cfi_undefined %%r14
\\lghi %%r11, 0
\\lghi %%r14, 0
\\
\\# call fn(arg)
\\lg %%r1, 8(%%r15)
\\lg %%r2, 16(%%r15)
\\basr %%r14, %%r1
Expand Down
7 changes: 6 additions & 1 deletion lib/std/os/linux/sparc64.zig
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,12 @@ pub fn clone() callconv(.Naked) usize {
\\ ret
\\ restore
\\1:
\\ # Child process, call func(arg)
\\ # Child process
\\ .cfi_undefined %%i7
\\ mov %%g0, %%fp
\\ mov %%g0, %%i7
\\
\\ # call func(arg)
\\ mov %%g0, %%fp
\\ call %%g2
\\ mov %%g3, %%o0
Expand Down
5 changes: 4 additions & 1 deletion lib/std/os/linux/x86.zig
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,11 @@ pub fn clone() callconv(.Naked) usize {
\\ int $128
\\ testl %%eax,%%eax
\\ jnz 1f
\\ popl %%eax
\\
\\ .cfi_undefined %%eip
\\ xorl %%ebp,%%ebp
\\
\\ popl %%eax
\\ calll *%%eax
\\ movl %%eax,%%ebx
\\ movl $1,%%eax // SYS_exit
Expand Down
2 changes: 2 additions & 0 deletions lib/std/os/linux/x86_64.zig
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,10 @@ pub fn clone() callconv(.Naked) usize {
\\ testq %%rax,%%rax
\\ jz 1f
\\ retq
\\
\\1: .cfi_undefined %%rip
\\ xorl %%ebp,%%ebp
\\
\\ popq %%rdi
\\ callq *%%r9
\\ movl %%eax,%%edi
Expand Down

0 comments on commit 84718aa

Please sign in to comment.