Created
September 20, 2017 20:09
-
-
Save andrewkroh/1c8db5a2321ba37a728c4a453f156b48 to your computer and use it in GitHub Desktop.
Go seccomp-bpf example using Google Kafel to generate BPF filter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"errors" | |
"log" | |
"os/exec" | |
"syscall" | |
"unsafe" | |
) | |
// Checkout google/kafel in this dir and build libkafel.a. | |
// #cgo CFLAGS: -I${SRCDIR}/kafel/include | |
// #cgo LDFLAGS: -L${SRCDIR}/kafel -lkafel | |
// #include <linux/filter.h> | |
// #include <linux/seccomp.h> | |
// #include <sys/prctl.h> | |
// #include <stdlib.h> | |
// #include <kafel.h> | |
import "C" | |
const killPolicy = `POLICY a { KILL { execve, clone, fork } } USE a DEFAULT ALLOW` | |
const errorPolicy = `POLICY a { ERRNO(1) { execve, clone, fork } } USE a DEFAULT ALLOW` | |
func main() { | |
prog, err := BuildSeccompBPFFilter(errorPolicy) | |
if err != nil { | |
log.Fatal(err) | |
} | |
if err := NoNewPrivs(); err != nil { | |
log.Fatal(err) | |
} | |
if err := InstallSeccomp(prog); err != nil { | |
log.Fatal(err) | |
} | |
log.Println("seccomp filter installed") | |
log.Println("attempting to exec") | |
out, err := exec.Command("ls", "-la").Output() | |
if err != nil { | |
log.Fatal("exec failed", err) | |
} | |
log.Println("cmd output:", string(out)) | |
log.Println("Done") | |
} | |
// Build filter. | |
func BuildSeccompBPFFilter(policy string) (*C.struct_sock_fprog, error) { | |
policyPtr := C.CString(policy) | |
defer C.free(unsafe.Pointer(policyPtr)) | |
prog := C.struct_sock_fprog{} | |
if rc := C.kafel_compile_string(policyPtr, &prog); rc != 0 { | |
return nil, errors.New("policy compilation failed") | |
} | |
return &prog, nil | |
} | |
// NoNewPrivs will use prctl to stop new privileges using native methods | |
func NoNewPrivs() error { | |
return prctl(C.PR_SET_NO_NEW_PRIVS, 1) | |
} | |
// InstallSeccomp will install seccomp using native methods. | |
func InstallSeccomp(prog *C.struct_sock_fprog) error { | |
return seccomp(C.SECCOMP_SET_MODE_FILTER, C.SECCOMP_FILTER_FLAG_TSYNC, unsafe.Pointer(prog)) | |
} | |
// seccomp syscall wrapper. | |
func seccomp(op, flags uintptr, uargs unsafe.Pointer) error { | |
// This is an amd64 specific syscall number. | |
_, _, e := syscall.Syscall(uintptr(317), op, flags, uintptr(uargs)) | |
if e != 0 { | |
return e | |
} | |
return nil | |
} | |
// prctl syscall wrapper. | |
func prctl(option uintptr, args ...uintptr) error { | |
if len(args) > 4 { | |
return syscall.E2BIG | |
} | |
var arg [4]uintptr | |
copy(arg[:], args) | |
_, _, e := syscall.Syscall6(syscall.SYS_PRCTL, option, arg[0], arg[1], arg[2], arg[3], 0) | |
if e != 0 { | |
return e | |
} | |
return nil | |
} | |
// Sample output: | |
// 2017/09/20 20:06:13 seccomp filter installed | |
// 2017/09/20 20:06:13 attempting to exec | |
// 2017/09/20 20:06:13 exec failedfork/exec /bin/ls: operation not permitted |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment