*: fix macOS build for go1.18

This commit is contained in:
criyle 2022-04-03 02:45:53 -07:00
parent 8fc50bc5b7
commit ca60fcad98
19 changed files with 121 additions and 58 deletions

2
.gitignore vendored
View File

@ -8,3 +8,5 @@ env*.sh
# Test Files
/runprog
/test
.vscode

View File

@ -74,6 +74,9 @@ func main() {
rt, err := start()
debug(rt, err)
if e, ok := err.(syscall.Errno); ok {
debug("errno", int(e))
}
if rt == nil {
rt = &runner.Result{
@ -194,8 +197,8 @@ func start() (*runner.Result, error) {
case wstatus.Exited():
if status := wstatus.ExitStatus(); status != 0 {
result.Status = runner.StatusNonzeroExitStatus
return &result, nil
}
return &result, nil
case wstatus.Signaled():
sig := wstatus.Signal()

View File

@ -22,7 +22,7 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, prof
beforeFork()
// UnshareFlags (new namespaces) is activated by clone syscall
r1, _, err1 = rawSyscall(funcPC(libc_fork_trampoline), 0, 0, 0)
r1, _, err1 = rawSyscall(libc_fork_trampoline_addr, 0, 0, 0)
if err1 != 0 || r1 != 0 {
// in parent process, immediate return
return
@ -33,12 +33,12 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, prof
// Notice: cannot call any GO functions beyond this point
// Close write end of pipe
if _, _, err1 = rawSyscall(funcPC(libc_close_trampoline), uintptr(p[0]), 0, 0); err1 != 0 {
if _, _, err1 = rawSyscall(libc_close_trampoline_addr, uintptr(p[0]), 0, 0); err1 != 0 {
goto childerror
}
// Set pg id
_, _, err1 = rawSyscall(funcPC(libc_setpgid_trampoline), 0, 0, 0)
_, _, err1 = rawSyscall(libc_setpgid_trampoline_addr, 0, 0, 0)
if err1 != 0 {
goto childerror
}
@ -46,11 +46,11 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, prof
// Pass 1 & pass 2 assigns fds for child process
// Pass 1: fd[i] < i => nextfd
if pipe < nextfd {
_, _, err1 = rawSyscall(funcPC(libc_dup2_trampoline), uintptr(pipe), uintptr(nextfd), 0)
_, _, err1 = rawSyscall(libc_dup2_trampoline_addr, uintptr(pipe), uintptr(nextfd), 0)
if err1 != 0 {
goto childerror
}
rawSyscall(funcPC(libc_fcntl_trampoline), uintptr(nextfd), syscall.F_SETFD, syscall.FD_CLOEXEC)
rawSyscall(libc_fcntl_trampoline_addr, uintptr(nextfd), syscall.F_SETFD, syscall.FD_CLOEXEC)
pipe = nextfd
nextfd++
}
@ -60,11 +60,11 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, prof
if nextfd == pipe {
nextfd++
}
_, _, err1 = rawSyscall(funcPC(libc_dup2_trampoline), uintptr(fd[i]), uintptr(nextfd), 0)
_, _, err1 = rawSyscall(libc_dup2_trampoline_addr, uintptr(fd[i]), uintptr(nextfd), 0)
if err1 != 0 {
goto childerror
}
rawSyscall(funcPC(libc_fcntl_trampoline), uintptr(nextfd), syscall.F_SETFD, syscall.FD_CLOEXEC)
rawSyscall(libc_fcntl_trampoline_addr, uintptr(nextfd), syscall.F_SETFD, syscall.FD_CLOEXEC)
// Set up close on exec
fd[i] = nextfd
nextfd++
@ -73,18 +73,18 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, prof
// Pass 2: fd[i] => i
for i := 0; i < len(fd); i++ {
if fd[i] == -1 {
rawSyscall(funcPC(libc_close_trampoline), uintptr(i), 0, 0)
rawSyscall(libc_close_trampoline_addr, uintptr(i), 0, 0)
continue
}
if fd[i] == int(i) {
// dup2(i, i) will not clear close on exec flag, need to reset the flag
_, _, err1 = rawSyscall(funcPC(libc_fcntl_trampoline), uintptr(fd[i]), syscall.F_SETFD, 0)
_, _, err1 = rawSyscall(libc_fcntl_trampoline_addr, uintptr(fd[i]), syscall.F_SETFD, 0)
if err1 != 0 {
goto childerror
}
continue
}
_, _, err1 = rawSyscall(funcPC(libc_dup2_trampoline), uintptr(fd[i]), uintptr(i), 0)
_, _, err1 = rawSyscall(libc_dup2_trampoline_addr, uintptr(fd[i]), uintptr(i), 0)
if err1 != 0 {
goto childerror
}
@ -92,7 +92,7 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, prof
// chdir for child
if workdir != nil {
_, _, err1 = rawSyscall(funcPC(libc_chdir_trampoline), uintptr(unsafe.Pointer(workdir)), 0, 0)
_, _, err1 = rawSyscall(libc_chdir_trampoline_addr, uintptr(unsafe.Pointer(workdir)), 0, 0)
if err1 != 0 {
goto childerror
}
@ -100,15 +100,18 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, prof
// Set limit
for _, rlim := range r.RLimits {
_, _, err1 = rawSyscall(funcPC(libc_setrlimit_trampoline), uintptr(rlim.Res), uintptr(unsafe.Pointer(&rlim.Rlim)), 0)
_, _, err1 = rawSyscall(libc_setrlimit_trampoline_addr, uintptr(rlim.Res), uintptr(unsafe.Pointer(&rlim.Rlim)), 0)
if err1 != 0 {
if err1 == syscall.EINVAL && (rlim.Res == syscall.RLIMIT_DATA || rlim.Res == syscall.RLIMIT_AS) {
continue
}
goto childerror
}
}
// Load sandbox profile
if profile != nil {
r1, _, err1 = rawSyscall(funcPC(libc_sandbox_init_trampoline), uintptr(unsafe.Pointer(profile)), 0, uintptr(unsafe.Pointer(&errBuf)))
r1, _, err1 = rawSyscall(libc_sandbox_init_trampoline_addr, uintptr(unsafe.Pointer(profile)), 0, uintptr(unsafe.Pointer(&errBuf)))
if err1 != 0 {
goto childerror
}
@ -116,31 +119,31 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, prof
err1 = 253
goto childerror
}
rawSyscall(funcPC(libc_sandbox_free_error_trampoline), uintptr(unsafe.Pointer(errBuf)), 0, 0)
rawSyscall(libc_sandbox_free_error_trampoline_addr, uintptr(unsafe.Pointer(errBuf)), 0, 0)
}
// Sync before exec
err2 = 0
r1, _, err1 = rawSyscall(funcPC(libc_write_trampoline), uintptr(pipe), uintptr(unsafe.Pointer(&err2)), unsafe.Sizeof(err2))
r1, _, err1 = rawSyscall(libc_write_trampoline_addr, uintptr(pipe), uintptr(unsafe.Pointer(&err2)), unsafe.Sizeof(err2))
if r1 == 0 || err1 != 0 {
goto childerror
}
r1, _, err1 = rawSyscall(funcPC(libc_read_trampoline), uintptr(pipe), uintptr(unsafe.Pointer(&err2)), unsafe.Sizeof(err2))
r1, _, err1 = rawSyscall(libc_read_trampoline_addr, uintptr(pipe), uintptr(unsafe.Pointer(&err2)), unsafe.Sizeof(err2))
if r1 == 0 || err1 != 0 {
goto childerror
}
// Time to exec.
_, _, err1 = rawSyscall(funcPC(libc_execve_trampoline),
_, _, err1 = rawSyscall(libc_execve_trampoline_addr,
uintptr(unsafe.Pointer(argv0)),
uintptr(unsafe.Pointer(&argv[0])),
uintptr(unsafe.Pointer(&env[0])))
childerror:
// send error code on pipe
rawSyscall(funcPC(libc_write_trampoline), uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
rawSyscall(libc_write_trampoline_addr, uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
for {
rawSyscall(funcPC(libc_exit_trampoline), uintptr(err1+err2), 0, 0)
rawSyscall(libc_exit_trampoline_addr, uintptr(err1+err2), 0, 0)
}
}

View File

@ -1,7 +1,6 @@
package forkexec
import (
"log"
"syscall"
"unsafe"
@ -84,7 +83,7 @@ func syncWithChild(r *Runner, p [2]int, pid int, err1 syscall.Errno) (int, error
unix.Close(p[0])
return 0, syscall.Errno(err1)
}
r1, _, err1 = syscall3(funcPC(libc_read_trampoline), uintptr(p[0]), uintptr(unsafe.Pointer(&err2)), uintptr(unsafe.Sizeof(err2)))
r1, _, err1 = syscall3(libc_read_trampoline_addr, uintptr(p[0]), uintptr(unsafe.Pointer(&err2)), uintptr(unsafe.Sizeof(err2)))
// child returned error code
if r1 != unsafe.Sizeof(err2) || err2 != 0 || err1 != 0 {
err = handlePipeError(r1, err2)
@ -98,13 +97,13 @@ func syncWithChild(r *Runner, p [2]int, pid int, err1 syscall.Errno) (int, error
}
}
// otherwise, ack child (err1 == 0)
r1, _, err1 = syscall3(funcPC(libc_write_trampoline), uintptr(p[0]), uintptr(unsafe.Pointer(&err1)), uintptr(unsafe.Sizeof(err1)))
r1, _, err1 = syscall3(libc_write_trampoline_addr, uintptr(p[0]), uintptr(unsafe.Pointer(&err1)), uintptr(unsafe.Sizeof(err1)))
if err1 != 0 {
goto fail
}
// if read anything mean child failed after sync (close_on_exec so it should not block)
r1, _, err1 = syscall3(funcPC(libc_read_trampoline), uintptr(p[0]), uintptr(unsafe.Pointer(&err2)), uintptr(unsafe.Sizeof(err2)))
r1, _, err1 = syscall3(libc_read_trampoline_addr, uintptr(p[0]), uintptr(unsafe.Pointer(&err2)), uintptr(unsafe.Sizeof(err2)))
unix.Close(p[0])
if r1 != 0 || err1 != 0 {
err = handlePipeError(r1, err2)
@ -122,7 +121,6 @@ failAfterClose:
// check pipe error
func handlePipeError(r1 uintptr, errno syscall.Errno) error {
log.Println(r1, errno, int(errno))
if r1 == unsafe.Sizeof(errno) {
return syscall.Errno(errno)
}

View File

@ -5,9 +5,6 @@ import (
_ "unsafe" // use go:linkname
)
//go:linkname funcPC syscall.funcPC
func funcPC(f func()) uintptr
//go:linkname syscall3 syscall.syscall
func syscall3(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
@ -17,38 +14,27 @@ func rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
//go:linkname rawSyscall6 syscall.rawSyscall6
func rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
//go:linkname libc_fork_trampoline syscall.libc_fork_trampoline
func libc_fork_trampoline()
var libc_fork_trampoline_addr uintptr
//go:linkname libc_close_trampoline syscall.libc_close_trampoline
func libc_close_trampoline()
var libc_close_trampoline_addr uintptr
//go:linkname libc_read_trampoline syscall.libc_read_trampoline
func libc_read_trampoline()
var libc_read_trampoline_addr uintptr
//go:linkname libc_write_trampoline syscall.libc_write_trampoline
func libc_write_trampoline()
var libc_write_trampoline_addr uintptr
//go:linkname libc_fcntl_trampoline syscall.libc_fcntl_trampoline
func libc_fcntl_trampoline()
var libc_fcntl_trampoline_addr uintptr
//go:linkname libc_dup2_trampoline syscall.libc_dup2_trampoline
func libc_dup2_trampoline()
var libc_dup2_trampoline_addr uintptr
//go:linkname libc_chdir_trampoline syscall.libc_chdir_trampoline
func libc_chdir_trampoline()
var libc_chdir_trampoline_addr uintptr
//go:linkname libc_setrlimit_trampoline syscall.libc_setrlimit_trampoline
func libc_setrlimit_trampoline()
var libc_setrlimit_trampoline_addr uintptr
//go:linkname libc_execve_trampoline syscall.libc_execve_trampoline
func libc_execve_trampoline()
var libc_execve_trampoline_addr uintptr
//go:linkname libc_exit_trampoline syscall.libc_exit_trampoline
func libc_exit_trampoline()
var libc_exit_trampoline_addr uintptr
//go:linkname libc_setpgid_trampoline syscall.libc_setpgid_trampoline
func libc_setpgid_trampoline()
var libc_setpgid_trampoline_addr uintptr
//go:linkname fcntl syscall.fcntl
func fcntl(fd int, cmd int, arg int) (val int, err error)

View File

@ -8,7 +8,7 @@ import (
// SandboxInit calls sandbox_init
func SandboxInit(profile *byte, flags uint64, errorBuf **byte) (err error) {
var r1 uintptr
r1, _, err = syscall3(funcPC(libc_sandbox_init_trampoline), uintptr(unsafe.Pointer(profile)), uintptr(flags), uintptr(unsafe.Pointer(errorBuf)))
r1, _, err = syscall3(libc_sandbox_init_trampoline_addr, uintptr(unsafe.Pointer(profile)), uintptr(flags), uintptr(unsafe.Pointer(errorBuf)))
if r1 != 0 {
err = syscall.EINVAL
} else {
@ -19,15 +19,13 @@ func SandboxInit(profile *byte, flags uint64, errorBuf **byte) (err error) {
// SandboxFreeError calls sandbox_free_error
func SandboxFreeError(errorBuf *byte) {
syscall3(funcPC(libc_sandbox_free_error_trampoline), uintptr(unsafe.Pointer(errorBuf)), 0, 0)
syscall3(libc_sandbox_free_error_trampoline_addr, uintptr(unsafe.Pointer(errorBuf)), 0, 0)
}
func libc_sandbox_init_trampoline()
var libc_sandbox_init_trampoline_addr uintptr
//go:linkname libc_sandbox_init libc_sandbox_init
//go:cgo_import_dynamic libc_sandbox_init sandbox_init "/usr/lib/libSystem.B.dylib"
func libc_sandbox_free_error_trampoline()
var libc_sandbox_free_error_trampoline_addr uintptr
//go:linkname libc_sandbox_free_error libc_sandbox_free_error
//go:cgo_import_dynamic libc_sandbox_free_error sandbox_free_error "/usr/lib/libSystem.B.dylib"

View File

@ -1,6 +1,79 @@
#include "textflag.h"
TEXT ·libc_sandbox_init_trampoline(SB),NOSPLIT,$0-0
TEXT libc_sandbox_init_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_sandbox_init(SB)
TEXT ·libc_sandbox_free_error_trampoline(SB),NOSPLIT,$0-0
GLOBL ·libc_sandbox_init_trampoline_addr(SB), RODATA, $8
DATA ·libc_sandbox_init_trampoline_addr(SB)/8, $libc_sandbox_init_trampoline<>(SB)
TEXT libc_sandbox_free_error_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_sandbox_free_error(SB)
GLOBL ·libc_sandbox_free_error_trampoline_addr(SB), RODATA, $8
DATA ·libc_sandbox_free_error_trampoline_addr(SB)/8, $libc_sandbox_free_error_trampoline<>(SB)
TEXT libc_fork_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_fork(SB)
GLOBL ·libc_fork_trampoline_addr(SB), RODATA, $8
DATA ·libc_fork_trampoline_addr(SB)/8, $libc_fork_trampoline<>(SB)
TEXT libc_close_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_close(SB)
GLOBL ·libc_close_trampoline_addr(SB), RODATA, $8
DATA ·libc_close_trampoline_addr(SB)/8, $libc_close_trampoline<>(SB)
TEXT libc_read_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_read(SB)
GLOBL ·libc_read_trampoline_addr(SB), RODATA, $8
DATA ·libc_read_trampoline_addr(SB)/8, $libc_read_trampoline<>(SB)
TEXT libc_write_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_write(SB)
GLOBL ·libc_write_trampoline_addr(SB), RODATA, $8
DATA ·libc_write_trampoline_addr(SB)/8, $libc_write_trampoline<>(SB)
TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_fcntl(SB)
GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $8
DATA ·libc_fcntl_trampoline_addr(SB)/8, $libc_fcntl_trampoline<>(SB)
TEXT libc_dup2_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_dup2(SB)
GLOBL ·libc_dup2_trampoline_addr(SB), RODATA, $8
DATA ·libc_dup2_trampoline_addr(SB)/8, $libc_dup2_trampoline<>(SB)
TEXT libc_chdir_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_chdir(SB)
GLOBL ·libc_chdir_trampoline_addr(SB), RODATA, $8
DATA ·libc_chdir_trampoline_addr(SB)/8, $libc_chdir_trampoline<>(SB)
TEXT libc_setrlimit_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_setrlimit(SB)
GLOBL ·libc_setrlimit_trampoline_addr(SB), RODATA, $8
DATA ·libc_setrlimit_trampoline_addr(SB)/8, $libc_setrlimit_trampoline<>(SB)
TEXT libc_execve_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_execve(SB)
GLOBL ·libc_execve_trampoline_addr(SB), RODATA, $8
DATA ·libc_execve_trampoline_addr(SB)/8, $libc_execve_trampoline<>(SB)
TEXT libc_exit_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_exit(SB)
GLOBL ·libc_exit_trampoline_addr(SB), RODATA, $8
DATA ·libc_exit_trampoline_addr(SB)/8, $libc_exit_trampoline<>(SB)
TEXT libc_setpgid_trampoline<>(SB),NOSPLIT,$0-0
JMP libc_setpgid(SB)
GLOBL ·libc_setpgid_trampoline_addr(SB), RODATA, $8
DATA ·libc_setpgid_trampoline_addr(SB)/8, $libc_setpgid_trampoline<>(SB)