*: 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 # Test Files
/runprog /runprog
/test /test
.vscode

View File

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

View File

@ -22,7 +22,7 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, prof
beforeFork() beforeFork()
// UnshareFlags (new namespaces) is activated by clone syscall // 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 { if err1 != 0 || r1 != 0 {
// in parent process, immediate return // in parent process, immediate return
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 // Notice: cannot call any GO functions beyond this point
// Close write end of pipe // 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 goto childerror
} }
// Set pg id // Set pg id
_, _, err1 = rawSyscall(funcPC(libc_setpgid_trampoline), 0, 0, 0) _, _, err1 = rawSyscall(libc_setpgid_trampoline_addr, 0, 0, 0)
if err1 != 0 { if err1 != 0 {
goto childerror 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 & pass 2 assigns fds for child process
// Pass 1: fd[i] < i => nextfd // Pass 1: fd[i] < i => nextfd
if pipe < 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 { if err1 != 0 {
goto childerror 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 pipe = nextfd
nextfd++ nextfd++
} }
@ -60,11 +60,11 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, prof
if nextfd == pipe { if nextfd == pipe {
nextfd++ 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 { if err1 != 0 {
goto childerror 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 // Set up close on exec
fd[i] = nextfd fd[i] = nextfd
nextfd++ nextfd++
@ -73,18 +73,18 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, prof
// Pass 2: fd[i] => i // Pass 2: fd[i] => i
for i := 0; i < len(fd); i++ { for i := 0; i < len(fd); i++ {
if fd[i] == -1 { if fd[i] == -1 {
rawSyscall(funcPC(libc_close_trampoline), uintptr(i), 0, 0) rawSyscall(libc_close_trampoline_addr, uintptr(i), 0, 0)
continue continue
} }
if fd[i] == int(i) { if fd[i] == int(i) {
// dup2(i, i) will not clear close on exec flag, need to reset the flag // 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 { if err1 != 0 {
goto childerror goto childerror
} }
continue 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 { if err1 != 0 {
goto childerror goto childerror
} }
@ -92,7 +92,7 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, prof
// chdir for child // chdir for child
if workdir != nil { 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 { if err1 != 0 {
goto childerror goto childerror
} }
@ -100,15 +100,18 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, prof
// Set limit // Set limit
for _, rlim := range r.RLimits { 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 != 0 {
if err1 == syscall.EINVAL && (rlim.Res == syscall.RLIMIT_DATA || rlim.Res == syscall.RLIMIT_AS) {
continue
}
goto childerror goto childerror
} }
} }
// Load sandbox profile // Load sandbox profile
if profile != nil { 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 { if err1 != 0 {
goto childerror goto childerror
} }
@ -116,31 +119,31 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, prof
err1 = 253 err1 = 253
goto childerror 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 // Sync before exec
err2 = 0 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 { if r1 == 0 || err1 != 0 {
goto childerror 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 { if r1 == 0 || err1 != 0 {
goto childerror goto childerror
} }
// Time to exec. // Time to exec.
_, _, err1 = rawSyscall(funcPC(libc_execve_trampoline), _, _, err1 = rawSyscall(libc_execve_trampoline_addr,
uintptr(unsafe.Pointer(argv0)), uintptr(unsafe.Pointer(argv0)),
uintptr(unsafe.Pointer(&argv[0])), uintptr(unsafe.Pointer(&argv[0])),
uintptr(unsafe.Pointer(&env[0]))) uintptr(unsafe.Pointer(&env[0])))
childerror: childerror:
// send error code on pipe // 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 { 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 package forkexec
import ( import (
"log"
"syscall" "syscall"
"unsafe" "unsafe"
@ -84,7 +83,7 @@ func syncWithChild(r *Runner, p [2]int, pid int, err1 syscall.Errno) (int, error
unix.Close(p[0]) unix.Close(p[0])
return 0, syscall.Errno(err1) 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 // child returned error code
if r1 != unsafe.Sizeof(err2) || err2 != 0 || err1 != 0 { if r1 != unsafe.Sizeof(err2) || err2 != 0 || err1 != 0 {
err = handlePipeError(r1, err2) 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) // 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 { if err1 != 0 {
goto fail goto fail
} }
// if read anything mean child failed after sync (close_on_exec so it should not block) // 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]) unix.Close(p[0])
if r1 != 0 || err1 != 0 { if r1 != 0 || err1 != 0 {
err = handlePipeError(r1, err2) err = handlePipeError(r1, err2)
@ -122,7 +121,6 @@ failAfterClose:
// check pipe error // check pipe error
func handlePipeError(r1 uintptr, errno syscall.Errno) error { func handlePipeError(r1 uintptr, errno syscall.Errno) error {
log.Println(r1, errno, int(errno))
if r1 == unsafe.Sizeof(errno) { if r1 == unsafe.Sizeof(errno) {
return syscall.Errno(errno) return syscall.Errno(errno)
} }

View File

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

View File

@ -8,7 +8,7 @@ import (
// SandboxInit calls sandbox_init // SandboxInit calls sandbox_init
func SandboxInit(profile *byte, flags uint64, errorBuf **byte) (err error) { func SandboxInit(profile *byte, flags uint64, errorBuf **byte) (err error) {
var r1 uintptr 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 { if r1 != 0 {
err = syscall.EINVAL err = syscall.EINVAL
} else { } else {
@ -19,15 +19,13 @@ func SandboxInit(profile *byte, flags uint64, errorBuf **byte) (err error) {
// SandboxFreeError calls sandbox_free_error // SandboxFreeError calls sandbox_free_error
func SandboxFreeError(errorBuf *byte) { 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" //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" //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" #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) 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) 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)