Add MacOS sandbox support

This commit is contained in:
criyle 2020-05-15 03:02:04 -04:00
parent 3fd00038db
commit bc0b7f92f1
3 changed files with 41 additions and 3 deletions

View File

@ -3,6 +3,8 @@ package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"syscall"
@ -17,6 +19,8 @@ var (
timeLimit, realTimeLimit, memoryLimit, outputLimit, stackLimit uint64
inputFileName, outputFileName, errorFileName, workPath string
profilePath string
args []string
)
@ -31,6 +35,7 @@ func main() {
flag.StringVar(&outputFileName, "out", "", "Set output file name")
flag.StringVar(&errorFileName, "err", "", "Set error file name")
flag.StringVar(&workPath, "work-path", "", "Set the work path of the program")
flag.StringVar(&profilePath, "p", "", "sandbox profile")
flag.Parse()
args = flag.Args()
@ -61,6 +66,15 @@ func start() (*runner.Result, error) {
}
defer closeFiles(files)
var profile string
if profilePath != "" {
c, err := ioutil.ReadFile(profilePath)
if err != nil {
return nil, fmt.Errorf("profile: %v", err)
}
profile = string(c)
}
// if not defined, then use the original value
fds := make([]uintptr, len(files))
for i, f := range files {
@ -89,7 +103,7 @@ func start() (*runner.Result, error) {
RLimits: rlims.PrepareRLimit(),
Files: fds,
WorkDir: workPath,
SandboxProfile: "",
SandboxProfile: profile,
SyncFunc: func(pid int) error {
mTime = time.Now()
return nil

View File

@ -9,7 +9,8 @@ import (
//go:norace
func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, profile *byte, p [2]int) (r1 uintptr, err1 syscall.Errno) {
var (
err2 syscall.Errno
err2 syscall.Errno
errBuf *byte
)
// similar to exec_linux, avoid side effect by shuffling around
@ -93,12 +94,25 @@ 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(funcPC(libc_setrlimit_trampoline), uintptr(rlim.Res), uintptr(unsafe.Pointer(&rlim.Rlim)), 0)
if err1 != 0 {
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)))
if err1 != 0 {
goto childerror
}
if r1 != 0 {
err1 = 253
goto childerror
}
rawSyscall(funcPC(libc_sandbox_free_error_trampoline), 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))

View File

@ -3,8 +3,12 @@ package forkexec
import (
"syscall"
_ "unsafe" // use go:linkname
"github.com/criyle/go-sandbox/pkg/darwin" // use sandbox_init
)
var _ = darwin.SandboxInit
//go:linkname funcPC syscall.funcPC
func funcPC(f func()) uintptr
@ -47,5 +51,11 @@ func libc_execve_trampoline()
//go:linkname libc_exit_trampoline syscall.libc_exit_trampoline
func libc_exit_trampoline()
//go:linkname libc_sandbox_init_trampoline github.com/criyle/go-sandbox/pkg/darwin.libc_sandbox_init_trampoline
func libc_sandbox_init_trampoline()
//go:linkname libc_sandbox_free_error_trampoline github.com/criyle/go-sandbox/pkg/darwin.libc_sandbox_free_error_trampoline
func libc_sandbox_free_error_trampoline()
//go:linkname fcntl syscall.fcntl
func fcntl(fd int, cmd int, arg int) (val int, err error)