| author | |
| committer | |
| log | da018f972619377e8c044c5c27ebf231be262bb3 |
| tree | 00faa647aca74f648677b74828301ab0f8c14fc0 |
| parent | 7d0087707634028308d3a870883249bfa59d94b8 |
| signature |
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: https://github.com/llvm/llvm-project/issues/11589114 files changed, 98 insertions(+), 44 deletions(-)
lib/std/os/linux/aarch64.zig+6-1| ... | ... | @@ -120,8 +120,13 @@ pub fn clone() callconv(.Naked) usize { |
| 120 | 120 | \\ cbz x0,1f |
| 121 | 121 | \\ // parent |
| 122 | 122 | \\ ret |
| 123 | \\ | |
| 123 | 124 | \\ // child |
| 124 | \\1: ldp x1,x0,[sp],#16 | |
| 125 | \\1: .cfi_undefined lr | |
| 126 | \\ mov fp, 0 | |
| 127 | \\ mov lr, 0 | |
| 128 | \\ | |
| 129 | \\ ldp x1,x0,[sp],#16 | |
| 125 | 130 | \\ blr x1 |
| 126 | 131 | \\ mov x8,#93 // SYS_exit |
| 127 | 132 | \\ svc #0 |
lib/std/os/linux/arm.zig+8-3| ... | ... | @@ -120,11 +120,16 @@ pub fn clone() callconv(.Naked) usize { |
| 120 | 120 | \\ ldmfd sp!,{r4,r5,r6,r7} |
| 121 | 121 | \\ bx lr |
| 122 | 122 | \\ |
| 123 | \\1: mov r0,r6 | |
| 123 | \\ // https://github.com/llvm/llvm-project/issues/115891 | |
| 124 | \\1: mov r7, #0 | |
| 125 | \\ mov r11, #0 | |
| 126 | \\ mov lr, #0 | |
| 127 | \\ | |
| 128 | \\ mov r0,r6 | |
| 124 | 129 | \\ bl 3f |
| 125 | \\2: mov r7,#1 // SYS_exit | |
| 130 | \\ mov r7,#1 // SYS_exit | |
| 126 | 131 | \\ svc 0 |
| 127 | \\ b 2b | |
| 132 | \\ | |
| 128 | 133 | \\3: bx r5 |
| 129 | 134 | ); |
| 130 | 135 | } |
lib/std/os/linux/hexagon.zig+4| ... | ... | @@ -118,6 +118,10 @@ pub fn clone() callconv(.Naked) usize { |
| 118 | 118 | \\ p0 = cmp.eq(r0, #0) |
| 119 | 119 | \\ if (!p0) dealloc_return |
| 120 | 120 | \\ |
| 121 | \\ .cfi_undefined r31 | |
| 122 | \\ r30 = #0 | |
| 123 | \\ r31 = #0 | |
| 124 | \\ | |
| 121 | 125 | \\ r0 = r10 |
| 122 | 126 | \\ callr r11 |
| 123 | 127 | \\ |
lib/std/os/linux/loongarch64.zig+4| ... | ... | @@ -121,6 +121,10 @@ pub fn clone() callconv(.Naked) usize { |
| 121 | 121 | \\ beqz $a0, 1f # whether child process |
| 122 | 122 | \\ jirl $zero, $ra, 0 # parent process return |
| 123 | 123 | \\1: |
| 124 | \\ .cfi_undefined 1 | |
| 125 | \\ move $fp, $zero | |
| 126 | \\ move $ra, $zero | |
| 127 | \\ | |
| 124 | 128 | \\ ld.d $t8, $sp, 0 # function pointer |
| 125 | 129 | \\ ld.d $a0, $sp, 8 # argument pointer |
| 126 | 130 | \\ jirl $ra, $t8, 0 # call the user's function |
lib/std/os/linux/mips.zig+4| ... | ... | @@ -231,6 +231,10 @@ pub fn clone() callconv(.Naked) usize { |
| 231 | 231 | \\ jr $ra |
| 232 | 232 | \\ nop |
| 233 | 233 | \\1: |
| 234 | \\ .cfi_undefined $ra | |
| 235 | \\ move $fp, $zero | |
| 236 | \\ move $ra, $zero | |
| 237 | \\ | |
| 234 | 238 | \\ lw $25, 0($sp) |
| 235 | 239 | \\ lw $4, 4($sp) |
| 236 | 240 | \\ jalr $25 |
lib/std/os/linux/mips64.zig+4| ... | ... | @@ -210,6 +210,10 @@ pub fn clone() callconv(.Naked) usize { |
| 210 | 210 | \\ jr $ra |
| 211 | 211 | \\ nop |
| 212 | 212 | \\1: |
| 213 | \\ .cfi_undefined $ra | |
| 214 | \\ move $fp, $zero | |
| 215 | \\ move $ra, $zero | |
| 216 | \\ | |
| 213 | 217 | \\ ld $25, 0($sp) |
| 214 | 218 | \\ ld $4, 8($sp) |
| 215 | 219 | \\ jalr $25 |
lib/std/os/linux/powerpc.zig+20-20| ... | ... | @@ -133,14 +133,14 @@ pub fn clone() callconv(.Naked) usize { |
| 133 | 133 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) |
| 134 | 134 | // 0 3, 4, 5, 6, 7 |
| 135 | 135 | asm volatile ( |
| 136 | \\ # store non-volatile regs r30, r31 on stack in order to put our | |
| 136 | \\ # store non-volatile regs r29, r30 on stack in order to put our | |
| 137 | 137 | \\ # start func and its arg there |
| 138 | \\ stwu 30, -16(1) | |
| 139 | \\ stw 31, 4(1) | |
| 138 | \\ stwu 29, -16(1) | |
| 139 | \\ stw 30, 4(1) | |
| 140 | 140 | \\ |
| 141 | \\ # save r3 (func) into r30, and r6(arg) into r31 | |
| 142 | \\ mr 30, 3 | |
| 143 | \\ mr 31, 6 | |
| 141 | \\ # save r3 (func) into r29, and r6(arg) into r30 | |
| 142 | \\ mr 29, 3 | |
| 143 | \\ mr 30, 6 | |
| 144 | 144 | \\ |
| 145 | 145 | \\ # create initial stack frame for new thread |
| 146 | 146 | \\ clrrwi 4, 4, 4 |
| ... | ... | @@ -167,28 +167,28 @@ pub fn clone() callconv(.Naked) usize { |
| 167 | 167 | \\ # compare sc result with 0 |
| 168 | 168 | \\ cmpwi cr7, 3, 0 |
| 169 | 169 | \\ |
| 170 | \\ # if not 0, jump to end | |
| 171 | \\ bne cr7, 2f | |
| 170 | \\ # if not 0, restore stack and return | |
| 171 | \\ beq cr7, 2f | |
| 172 | \\ lwz 29, 0(1) | |
| 173 | \\ lwz 30, 4(1) | |
| 174 | \\ addi 1, 1, 16 | |
| 175 | \\ blr | |
| 172 | 176 | \\ |
| 173 | 177 | \\ #else: we're the child |
| 178 | \\ 2: | |
| 179 | \\ .cfi_undefined lr | |
| 180 | \\ li 31, 0 | |
| 181 | \\ mtlr 0 | |
| 182 | \\ | |
| 174 | 183 | \\ #call funcptr: move arg (d) into r3 |
| 175 | \\ mr 3, 31 | |
| 176 | \\ #move r30 (funcptr) into CTR reg | |
| 177 | \\ mtctr 30 | |
| 184 | \\ mr 3, 30 | |
| 185 | \\ #move r29 (funcptr) into CTR reg | |
| 186 | \\ mtctr 29 | |
| 178 | 187 | \\ # call CTR reg |
| 179 | 188 | \\ bctrl |
| 180 | 189 | \\ # mov SYS_exit into r0 (the exit param is already in r3) |
| 181 | 190 | \\ li 0, 1 |
| 182 | 191 | \\ sc |
| 183 | \\ | |
| 184 | \\ 2: | |
| 185 | \\ | |
| 186 | \\ # restore stack | |
| 187 | \\ lwz 30, 0(1) | |
| 188 | \\ lwz 31, 4(1) | |
| 189 | \\ addi 1, 1, 16 | |
| 190 | \\ | |
| 191 | \\ blr | |
| 192 | 192 | ); |
| 193 | 193 | } |
| 194 | 194 |
lib/std/os/linux/powerpc64.zig+6-1| ... | ... | @@ -160,7 +160,12 @@ pub fn clone() callconv(.Naked) usize { |
| 160 | 160 | \\ cmpwi cr7, 3, 0 |
| 161 | 161 | \\ bnelr cr7 |
| 162 | 162 | \\ |
| 163 | \\ # we're the child. call fn(arg) | |
| 163 | \\ # we're the child | |
| 164 | \\ .cfi_undefined lr | |
| 165 | \\ li 31, 0 | |
| 166 | \\ mtlr 0 | |
| 167 | \\ | |
| 168 | \\ # call fn(arg) | |
| 164 | 169 | \\ ld 3, 16(1) |
| 165 | 170 | \\ ld 12, 8(1) |
| 166 | 171 | \\ mtctr 12 |
lib/std/os/linux/riscv32.zig+5-1| ... | ... | @@ -120,7 +120,11 @@ pub fn clone() callconv(.Naked) usize { |
| 120 | 120 | \\ ret |
| 121 | 121 | \\ |
| 122 | 122 | \\ # Child |
| 123 | \\1: lw a1, 0(sp) | |
| 123 | \\1: .cfi_undefined ra | |
| 124 | \\ mv fp, zero | |
| 125 | \\ mv ra, zero | |
| 126 | \\ | |
| 127 | \\ lw a1, 0(sp) | |
| 124 | 128 | \\ lw a0, 4(sp) |
| 125 | 129 | \\ jalr a1 |
| 126 | 130 | \\ |
lib/std/os/linux/riscv64.zig+5-1| ... | ... | @@ -120,7 +120,11 @@ pub fn clone() callconv(.Naked) usize { |
| 120 | 120 | \\ ret |
| 121 | 121 | \\ |
| 122 | 122 | \\ # Child |
| 123 | \\1: ld a1, 0(sp) | |
| 123 | \\1: .cfi_undefined ra | |
| 124 | \\ mv fp, zero | |
| 125 | \\ mv ra, zero | |
| 126 | \\ | |
| 127 | \\ ld a1, 0(sp) | |
| 124 | 128 | \\ ld a0, 8(sp) |
| 125 | 129 | \\ jalr a1 |
| 126 | 130 | \\ |
lib/std/os/linux/s390x.zig+6-1| ... | ... | @@ -133,7 +133,12 @@ pub fn clone() callconv(.Naked) usize { |
| 133 | 133 | \\ltgr %%r2, %%r2 |
| 134 | 134 | \\bnzr %%r14 |
| 135 | 135 | \\ |
| 136 | \\# we're the child. call fn(arg) | |
| 136 | \\# we're the child | |
| 137 | \\.cfi_undefined %%r14 | |
| 138 | \\lghi %%r11, 0 | |
| 139 | \\lghi %%r14, 0 | |
| 140 | \\ | |
| 141 | \\# call fn(arg) | |
| 137 | 142 | \\lg %%r1, 8(%%r15) |
| 138 | 143 | \\lg %%r2, 16(%%r15) |
| 139 | 144 | \\basr %%r14, %%r1 |
lib/std/os/linux/sparc64.zig+13-8| ... | ... | @@ -198,29 +198,34 @@ pub fn clone() callconv(.Naked) usize { |
| 198 | 198 | \\ mov %%i5, %%o3 |
| 199 | 199 | \\ ldx [%%fp + 0x8af], %%o4 |
| 200 | 200 | \\ t 0x6d |
| 201 | \\ bcs,pn %%xcc, 2f | |
| 201 | \\ bcs,pn %%xcc, 1f | |
| 202 | 202 | \\ nop |
| 203 | 203 | \\ # The child pid is returned in o0 while o1 tells if this |
| 204 | 204 | \\ # process is # the child (=1) or the parent (=0). |
| 205 | \\ brnz %%o1, 1f | |
| 205 | \\ brnz %%o1, 2f | |
| 206 | 206 | \\ nop |
| 207 | 207 | \\ # Parent process, return the child pid |
| 208 | 208 | \\ mov %%o0, %%i0 |
| 209 | 209 | \\ ret |
| 210 | 210 | \\ restore |
| 211 | 211 | \\1: |
| 212 | \\ # Child process, call func(arg) | |
| 212 | \\ # The syscall failed | |
| 213 | \\ sub %%g0, %%o0, %%i0 | |
| 214 | \\ ret | |
| 215 | \\ restore | |
| 216 | \\2: | |
| 217 | \\ # Child process | |
| 218 | \\ .cfi_undefined %%i7 | |
| 219 | \\ mov %%g0, %%fp | |
| 220 | \\ mov %%g0, %%i7 | |
| 221 | \\ | |
| 222 | \\ # call func(arg) | |
| 213 | 223 | \\ mov %%g0, %%fp |
| 214 | 224 | \\ call %%g2 |
| 215 | 225 | \\ mov %%g3, %%o0 |
| 216 | 226 | \\ # Exit |
| 217 | 227 | \\ mov 1, %%g1 // SYS_exit |
| 218 | 228 | \\ t 0x6d |
| 219 | \\2: | |
| 220 | \\ # The syscall failed | |
| 221 | \\ sub %%g0, %%o0, %%i0 | |
| 222 | \\ ret | |
| 223 | \\ restore | |
| 224 | 229 | ); |
| 225 | 230 | } |
| 226 | 231 |
lib/std/os/linux/x86.zig+11-8| ... | ... | @@ -148,19 +148,22 @@ pub fn clone() callconv(.Naked) usize { |
| 148 | 148 | \\ movl $120,%%eax // SYS_clone |
| 149 | 149 | \\ int $128 |
| 150 | 150 | \\ testl %%eax,%%eax |
| 151 | \\ jnz 1f | |
| 152 | \\ popl %%eax | |
| 153 | \\ xorl %%ebp,%%ebp | |
| 154 | \\ calll *%%eax | |
| 155 | \\ movl %%eax,%%ebx | |
| 156 | \\ movl $1,%%eax // SYS_exit | |
| 157 | \\ int $128 | |
| 158 | \\1: | |
| 151 | \\ jz 1f | |
| 159 | 152 | \\ popl %%edi |
| 160 | 153 | \\ popl %%esi |
| 161 | 154 | \\ popl %%ebx |
| 162 | 155 | \\ popl %%ebp |
| 163 | 156 | \\ retl |
| 157 | \\ | |
| 158 | \\1: | |
| 159 | \\ .cfi_undefined %%eip | |
| 160 | \\ xorl %%ebp,%%ebp | |
| 161 | \\ | |
| 162 | \\ popl %%eax | |
| 163 | \\ calll *%%eax | |
| 164 | \\ movl %%eax,%%ebx | |
| 165 | \\ movl $1,%%eax // SYS_exit | |
| 166 | \\ int $128 | |
| 164 | 167 | ); |
| 165 | 168 | } |
| 166 | 169 |
lib/std/os/linux/x86_64.zig+2| ... | ... | @@ -116,8 +116,10 @@ pub fn clone() callconv(.Naked) usize { |
| 116 | 116 | \\ testq %%rax,%%rax |
| 117 | 117 | \\ jz 1f |
| 118 | 118 | \\ retq |
| 119 | \\ | |
| 119 | 120 | \\1: .cfi_undefined %%rip |
| 120 | 121 | \\ xorl %%ebp,%%ebp |
| 122 | \\ | |
| 121 | 123 | \\ popq %%rdi |
| 122 | 124 | \\ callq *%%r9 |
| 123 | 125 | \\ movl %%eax,%%edi |