diff --git a/go.mod b/go.mod index d2dba89..d8a025e 100644 --- a/go.mod +++ b/go.mod @@ -4,5 +4,5 @@ go 1.14 require ( github.com/seccomp/libseccomp-golang v0.9.1 - golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f + golang.org/x/sys v0.0.0-20200513112337-417ce2331b5c ) diff --git a/go.sum b/go.sum index c491d0b..2ed8af2 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,4 @@ github.com/seccomp/libseccomp-golang v0.9.1 h1:NJjM5DNFOs0s3kYE1WUOr6G8V97sdt46rlXTMfXGWBo= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= -golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f h1:mOhmO9WsBaJCNmaZHPtHs9wOcdqdKCjF6OPJlmDM3KI= -golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200513112337-417ce2331b5c h1:kISX68E8gSkNYAFRFiDU8rl5RIn1sJYKYb/r2vMLDrU= +golang.org/x/sys v0.0.0-20200513112337-417ce2331b5c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/pkg/darwin/sandbox_darwin_test.go b/pkg/darwin/sandbox_darwin_test.go new file mode 100644 index 0000000..5b31772 --- /dev/null +++ b/pkg/darwin/sandbox_darwin_test.go @@ -0,0 +1,36 @@ +package darwin + +import ( + "io/ioutil" + "os" + "testing" +) + +func TestWrite(t *testing.T) { + c, err := ioutil.ReadFile("test.sb") + if err != nil { + t.Error(err) + return + } + + // before load profile, it is ok + f, err := os.OpenFile("/tmp/sandbox_test", os.O_CREATE|os.O_RDWR, 0777) + if err != nil { + t.Error(err) + return + } + f.Close() + + if err = SandboxLoadProfile(string(c)); err != nil { + t.Error(err) + return + } + + // after is not ok + f, err = os.OpenFile("/tmp/sandbox_test", os.O_CREATE|os.O_RDWR, 0777) + if !os.IsPermission(err) { + t.Error(err) + return + } + f.Close() +} diff --git a/pkg/darwin/sandbox_load_darwin.go b/pkg/darwin/sandbox_load_darwin.go new file mode 100644 index 0000000..203e315 --- /dev/null +++ b/pkg/darwin/sandbox_load_darwin.go @@ -0,0 +1,35 @@ +package darwin + +import ( + "errors" + "os" + "syscall" + "unsafe" +) + +func goString(b *byte) string { + l := 0 + sb := (*[1 << 20]byte)(unsafe.Pointer(b)) + for sb[l] > 0 { + l++ + } + return string(sb[: l-1 : l-1]) +} + +// SandboxLoadProfile loads profile by sandbox_init +func SandboxLoadProfile(profile string) (err error) { + var errBuf *byte + p, err := syscall.BytePtrFromString(profile) + if err != nil { + return + } + if err := SandboxInit(p, 0, &errBuf); err != nil { + defer SandboxFreeError(errBuf) + if errBuf != nil { + s := goString(errBuf) + return os.NewSyscallError("sandbox_init", errors.New(s)) + } + return os.NewSyscallError("sandbox_init", err) + } + return +} diff --git a/pkg/darwin/syscall_darwin.go b/pkg/darwin/syscall_darwin.go new file mode 100644 index 0000000..5626caf --- /dev/null +++ b/pkg/darwin/syscall_darwin.go @@ -0,0 +1,39 @@ +package darwin + +import ( + "syscall" + "unsafe" +) + +// 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))) + if r1 != 0 { + err = syscall.EINVAL + } else { + err = nil + } + return +} + +// SandboxFreeError calls sandbox_free_error +func SandboxFreeError(errorBuf *byte) { + syscall3(funcPC(libc_sandbox_free_error_trampoline), uintptr(unsafe.Pointer(errorBuf)), 0, 0) +} + +func libc_sandbox_init_trampoline() + +//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() + +//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:linkname syscall3 syscall.syscall +func syscall3(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) + +//go:linkname funcPC syscall.funcPC +func funcPC(f func()) uintptr diff --git a/pkg/darwin/test.sb b/pkg/darwin/test.sb new file mode 100644 index 0000000..0fa54c3 --- /dev/null +++ b/pkg/darwin/test.sb @@ -0,0 +1,21 @@ +; Test Sandbox Profile +; No network / socket +; No system / sysctl +(version 1) + +(deny default) + +; allow posix ipc +(allow ipc-posix*) + +; allow file access / +(allow file-read* (subpath "/usr/lib")) + +; allow execve +(allow process-exec) + +; allow fork +(allow process-fork) + +; allow signal to self +(allow signal (target self)) diff --git a/pkg/darwin/zsyscall_darwin.s b/pkg/darwin/zsyscall_darwin.s new file mode 100644 index 0000000..6a81d4d --- /dev/null +++ b/pkg/darwin/zsyscall_darwin.s @@ -0,0 +1,6 @@ +#include "textflag.h" +TEXT ·libc_sandbox_init_trampoline(SB),NOSPLIT,$0-0 + JMP libc_sandbox_init(SB) + +TEXT ·libc_sandbox_free_error_trampoline(SB),NOSPLIT,$0-0 + JMP libc_sandbox_free_error(SB)