Skip to content

Instantly share code, notes, and snippets.

@andrewkroh
Created September 20, 2017 20:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrewkroh/1c8db5a2321ba37a728c4a453f156b48 to your computer and use it in GitHub Desktop.
Save andrewkroh/1c8db5a2321ba37a728c4a453f156b48 to your computer and use it in GitHub Desktop.
Go seccomp-bpf example using Google Kafel to generate BPF filter
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