go-sandbox/secutil/secutil.go

74 lines
1.6 KiB
Go

// Package secutil provides utility functions to manipulate seccomp filters
// provided by libseccomp
package secutil
import (
"io/ioutil"
"os"
"syscall"
"unsafe"
libseccomp "github.com/seccomp/libseccomp-golang"
)
// FilterToBPF convert libseccomp filter to kernel readable BPF style
func FilterToBPF(filter *libseccomp.ScmpFilter) (*syscall.SockFprog, error) {
r, w, err := os.Pipe()
if err != nil {
return nil, err
}
// export to pipe
go func() {
filter.ExportBPF(w)
w.Close()
}()
// get BPF binary
bin, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}
// directly convert pointer
return &syscall.SockFprog{
Len: uint16(len(bin) / 8),
Filter: (*syscall.SockFilter)(unsafe.Pointer(&bin[0])),
}, nil
}
// BuildFilter builds libseccomp filter by defining the default action, trace action
// allow and trace syscall names
func BuildFilter(defaultAct, traceAct libseccomp.ScmpAction, allow, trace []string) (*libseccomp.ScmpFilter, error) {
filter, err := libseccomp.NewFilter(defaultAct)
if err != nil {
return nil, err
}
for _, s := range allow {
err := addFilterAction(filter, s, libseccomp.ActAllow)
if err != nil {
return nil, err
}
}
for _, s := range trace {
err := addFilterAction(filter, s, traceAct)
if err != nil {
return nil, err
}
}
return filter, nil
}
func addFilterAction(filter *libseccomp.ScmpFilter, name string, action libseccomp.ScmpAction) error {
syscallID, err := libseccomp.GetSyscallFromName(name)
if err != nil {
return err
}
err = filter.AddRule(syscallID, action)
if err != nil {
return err
}
return nil
}