diff --git a/pkg/forkexec/fork_child_linux.go b/pkg/forkexec/fork_child_linux.go index d045068..a15fdf3 100644 --- a/pkg/forkexec/fork_child_linux.go +++ b/pkg/forkexec/fork_child_linux.go @@ -5,6 +5,7 @@ import ( "syscall" "unsafe" + "github.com/criyle/go-sandbox/pkg/forkexec/vfork" "github.com/criyle/go-sandbox/pkg/rlimit" "golang.org/x/sys/unix" ) @@ -30,7 +31,7 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, host flag := r.CloneFlags & UnshareFlags if r.SyncFunc == nil && !(r.StopBeforeSeccomp || (r.Seccomp != nil && r.Ptrace)) && flag&syscall.CLONE_NEWUSER != syscall.CLONE_NEWUSER { - // flag |= syscall.CLONE_VM | syscall.CLONE_VFORK + flag |= syscall.CLONE_VM | syscall.CLONE_VFORK } // use clone3 if cgroupFd specified @@ -54,13 +55,13 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, host // UnshareFlags (new namespaces) is activated by clone syscall if clone3 != nil { - r1, _, err1 = syscall.RawSyscall6(unix.SYS_CLONE3, uintptr(unsafe.Pointer(clone3)), unsafe.Sizeof(*clone3), 0, 0, 0, 0) + r1, err1 = vfork.RawVforkSyscall(unix.SYS_CLONE3, uintptr(unsafe.Pointer(clone3)), unsafe.Sizeof(*clone3), 0) } else { if runtime.GOARCH == "s390x" { // On Linux/s390, the first two arguments of clone(2) are swapped. - r1, _, err1 = syscall.RawSyscall6(syscall.SYS_CLONE, 0, flag, 0, 0, 0, 0) + r1, err1 = vfork.RawVforkSyscall(syscall.SYS_CLONE, 0, flag, 0) } else { - r1, _, err1 = syscall.RawSyscall6(syscall.SYS_CLONE, flag, 0, 0, 0, 0, 0) + r1, err1 = vfork.RawVforkSyscall(syscall.SYS_CLONE, flag, 0, 0) } } if err1 != 0 || r1 != 0 { diff --git a/pkg/forkexec/vfork/asm_linux_386.s b/pkg/forkexec/vfork/asm_linux_386.s new file mode 100644 index 0000000..925ee06 --- /dev/null +++ b/pkg/forkexec/vfork/asm_linux_386.s @@ -0,0 +1,25 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// func RawVforkSyscall(trap, a1, a2, a3 uintptr) (r1, err uintptr) +TEXT ·RawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-24 + MOVL trap+0(FP), AX // syscall entry + MOVL a1+4(FP), BX + MOVL a2+8(FP), CX + MOVL a3+12(FP), DX + POPL SI // preserve return address + INVOKE_SYSCALL + PUSHL SI + CMPL AX, $0xfffff001 + JLS ok + MOVL $-1, r1+16(FP) + NEGL AX + MOVL AX, err+20(FP) + RET +ok: + MOVL AX, r1+16(FP) + MOVL $0, err+20(FP) + RET \ No newline at end of file diff --git a/pkg/forkexec/vfork/asm_linux_amd64.s b/pkg/forkexec/vfork/asm_linux_amd64.s new file mode 100644 index 0000000..b4832ef --- /dev/null +++ b/pkg/forkexec/vfork/asm_linux_amd64.s @@ -0,0 +1,28 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// func RawVforkSyscall(trap, a1, a2, a3 uintptr) (r1, err uintptr) +TEXT ·RawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-48 + MOVQ a1+8(FP), DI + MOVQ a2+16(FP), SI + MOVQ a3+24(FP), DX + MOVQ $0, R10 + MOVQ $0, R8 + MOVQ $0, R9 + MOVQ trap+0(FP), AX // syscall entry + POPQ R12 // preserve return address + SYSCALL + PUSHQ R12 + CMPQ AX, $0xfffffffffffff001 + JLS ok2 + MOVQ $-1, r1+32(FP) + NEGQ AX + MOVQ AX, err+40(FP) + RET +ok2: + MOVQ AX, r1+32(FP) + MOVQ $0, err+40(FP) + RET \ No newline at end of file diff --git a/pkg/forkexec/vfork/asm_linux_arm.s b/pkg/forkexec/vfork/asm_linux_arm.s new file mode 100644 index 0000000..b1b7c65 --- /dev/null +++ b/pkg/forkexec/vfork/asm_linux_arm.s @@ -0,0 +1,26 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// func RawVforkSyscall(trap, a1, a2, a3 uintptr) (r1, err uintptr) +TEXT ·RawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-24 + MOVW trap+0(FP), R7 // syscall entry + MOVW a1+4(FP), R0 + MOVW a2+8(FP), R1 + MOVW a3+12(FP), R2 + SWI $0 + MOVW $0xfffff001, R1 + CMP R1, R0 + BLS ok + MOVW $-1, R1 + MOVW R1, r1+16(FP) + RSB $0, R0, R0 + MOVW R0, err+20(FP) + RET +ok: + MOVW R0, r1+16(FP) + MOVW $0, R0 + MOVW R0, err+20(FP) + RET \ No newline at end of file diff --git a/pkg/forkexec/vfork/asm_linux_arm64.s b/pkg/forkexec/vfork/asm_linux_arm64.s new file mode 100644 index 0000000..502257f --- /dev/null +++ b/pkg/forkexec/vfork/asm_linux_arm64.s @@ -0,0 +1,27 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// func RawVforkSyscall(trap, a1, a2, a3 uintptr) (r1, err uintptr) +TEXT ·RawVforkSyscall(SB),NOSPLIT,$0-48 + MOVD a1+8(FP), R0 + MOVD a2+16(FP), R1 + MOVD a3+24(FP), R2 + MOVD $0, R3 + MOVD $0, R4 + MOVD $0, R5 + MOVD trap+0(FP), R8 // syscall entry + SVC + CMN $4095, R0 + BCC ok + MOVD $-1, R4 + MOVD R4, r1+32(FP) // r1 + NEG R0, R0 + MOVD R0, err+40(FP) // errno + RET +ok: + MOVD R0, r1+32(FP) // r1 + MOVD ZR, err+40(FP) // errno + RET diff --git a/pkg/forkexec/vfork/asm_linux_loong64.s b/pkg/forkexec/vfork/asm_linux_loong64.s new file mode 100644 index 0000000..7b31437 --- /dev/null +++ b/pkg/forkexec/vfork/asm_linux_loong64.s @@ -0,0 +1,27 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// func RawVforkSyscall(trap, a1, a2, a3 uintptr) (r1, err uintptr) +TEXT ·RawVforkSyscall(SB),NOSPLIT,$0-48 + MOVV a1+8(FP), R4 + MOVV a2+16(FP), R5 + MOVV a3+24(FP), R6 + MOVV $0, R7 + MOVV $0, R8 + MOVV $0, R9 + MOVV trap+0(FP), R11 // syscall entry + SYSCALL + MOVW $-4096, R12 + BGEU R12, R4, ok + MOVV $-1, R12 + MOVV R12, r1+32(FP) // r1 + SUBVU R4, R0, R4 + MOVV R4, err+40(FP) // errno + RET +ok: + MOVV R4, r1+32(FP) // r1 + MOVV R0, err+40(FP) // errno + RET diff --git a/pkg/forkexec/vfork/asm_linux_mips64x.s b/pkg/forkexec/vfork/asm_linux_mips64x.s new file mode 100644 index 0000000..687f155 --- /dev/null +++ b/pkg/forkexec/vfork/asm_linux_mips64x.s @@ -0,0 +1,27 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux && (mips64 || mips64le) + +#include "textflag.h" + +// func RawVforkSyscall(trap, a1, a2, a3 uintptr) (r1, err uintptr) +TEXT ·RawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-48 + MOVV a1+8(FP), R4 + MOVV a2+16(FP), R5 + MOVV a3+24(FP), R6 + MOVV R0, R7 + MOVV R0, R8 + MOVV R0, R9 + MOVV trap+0(FP), R2 // syscall entry + SYSCALL + BEQ R7, ok + MOVV $-1, R1 + MOVV R1, r1+32(FP) // r1 + MOVV R2, err+40(FP) // errno + RET +ok: + MOVV R2, r1+32(FP) // r1 + MOVV R0, err+40(FP) // errno + RET diff --git a/pkg/forkexec/vfork/asm_linux_mipsx.s b/pkg/forkexec/vfork/asm_linux_mipsx.s new file mode 100644 index 0000000..0b8595c --- /dev/null +++ b/pkg/forkexec/vfork/asm_linux_mipsx.s @@ -0,0 +1,24 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux && (mips || mipsle) + +#include "textflag.h" + +// func RawVforkSyscall(trap, a1, a2, a3 uintptr) (r1, err uintptr) +TEXT ·RawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-24 + MOVW a1+4(FP), R4 + MOVW a2+8(FP), R5 + MOVW a3+12(FP), R6 + MOVW trap+0(FP), R2 // syscall entry + SYSCALL + BEQ R7, ok + MOVW $-1, R1 + MOVW R1, r1+16(FP) // r1 + MOVW R2, err+20(FP) // errno + RET +ok: + MOVW R2, r1+16(FP) // r1 + MOVW R0, err+20(FP) // errno + RET diff --git a/pkg/forkexec/vfork/asm_linux_ppc64x.s b/pkg/forkexec/vfork/asm_linux_ppc64x.s new file mode 100644 index 0000000..8eaa656 --- /dev/null +++ b/pkg/forkexec/vfork/asm_linux_ppc64x.s @@ -0,0 +1,27 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux && (ppc64 || ppc64le) + +#include "textflag.h" + +// func RawVforkSyscall(trap, a1, a2, a3 uintptr) (r1, err uintptr) +TEXT ·RawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-48 + MOVD a1+8(FP), R3 + MOVD a2+16(FP), R4 + MOVD a3+24(FP), R5 + MOVD R0, R6 + MOVD R0, R7 + MOVD R0, R8 + MOVD trap+0(FP), R9 // syscall entry + SYSCALL R9 + BVC ok + MOVD $-1, R4 + MOVD R4, r1+32(FP) // r1 + MOVD R3, err+40(FP) // errno + RET +ok: + MOVD R3, r1+32(FP) // r1 + MOVD R0, err+40(FP) // errno + RET diff --git a/pkg/forkexec/vfork/asm_linux_riscv64.s b/pkg/forkexec/vfork/asm_linux_riscv64.s new file mode 100644 index 0000000..668bbf3 --- /dev/null +++ b/pkg/forkexec/vfork/asm_linux_riscv64.s @@ -0,0 +1,27 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// func RawVforkSyscall(trap, a1, a2, a3 uintptr) (r1, err uintptr) +TEXT ·RawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-48 + MOV a1+8(FP), A0 + MOV a2+16(FP), A1 + MOV a3+24(FP), A2 + MOV ZERO, A3 + MOV ZERO, A4 + MOV ZERO, A5 + MOV trap+0(FP), A7 // syscall entry + ECALL + MOV $-4096, T0 + BLTU T0, A0, err + MOV A0, r1+32(FP) // r1 + MOV ZERO, err+40(FP) // errno + RET +err: + MOV $-1, T0 + MOV T0, r1+32(FP) // r1 + SUB A0, ZERO, A0 + MOV A0, err+40(FP) // errno + RET diff --git a/pkg/forkexec/vfork/asm_linux_s390x.s b/pkg/forkexec/vfork/asm_linux_s390x.s new file mode 100644 index 0000000..624d34a --- /dev/null +++ b/pkg/forkexec/vfork/asm_linux_s390x.s @@ -0,0 +1,26 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// func RawVforkSyscall(trap, a1, a2, a3 uintptr) (r1, err uintptr) +TEXT ·RawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-48 + MOVD a1+8(FP), R2 + MOVD a2+16(FP), R3 + MOVD a3+24(FP), R4 + MOVD $0, R5 + MOVD $0, R6 + MOVD $0, R7 + MOVD trap+0(FP), R1 // syscall entry + SYSCALL + MOVD $0xfffffffffffff001, R8 + CMPUBLT R2, R8, ok2 + MOVD $-1, r1+32(FP) + NEG R2, R2 + MOVD R2, err+40(FP) // errno + RET +ok2: + MOVD R2, r1+32(FP) + MOVD $0, err+40(FP) // errno + RET diff --git a/pkg/forkexec/vfork/syscall.go b/pkg/forkexec/vfork/syscall.go new file mode 100644 index 0000000..1e14da0 --- /dev/null +++ b/pkg/forkexec/vfork/syscall.go @@ -0,0 +1,12 @@ +// Package vfork provides the mirror of the un-exported syscall.rawVforkSyscall. +// The assembly code is copied from go1.24 syscall package +package vfork + +import "syscall" + +// RawVforkSyscall provided the mirrored version from un-exported syscall.rawVforkSyscall +// The go:linkname does not work for assembly function and it was suggested by the go team +// to copy over the assembly functions +// +// See go.dev/issue/71892 +func RawVforkSyscall(trap, a1, a2, a3 uintptr) (r1 uintptr, err syscall.Errno)