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