diff options
Diffstat (limited to 'sandbox/seccomp/seccomp.go')
| -rw-r--r-- | sandbox/seccomp/seccomp.go | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/sandbox/seccomp/seccomp.go b/sandbox/seccomp/seccomp.go new file mode 100644 index 00000000..2e730479 --- /dev/null +++ b/sandbox/seccomp/seccomp.go @@ -0,0 +1,114 @@ +package seccomp + +/* +#cgo linux pkg-config: --static libseccomp + +#include "seccomp-build.h" +*/ +import "C" +import ( + "errors" + "fmt" + "runtime" + "syscall" +) + +// LibraryError represents a libseccomp error. +type LibraryError struct { + Prefix string + Seccomp syscall.Errno + Errno error +} + +func (e *LibraryError) Error() string { + if e.Seccomp == 0 { + if e.Errno == nil { + panic("invalid libseccomp error") + } + return fmt.Sprintf("%s: %s", e.Prefix, e.Errno) + } + if e.Errno == nil { + return fmt.Sprintf("%s: %s", e.Prefix, e.Seccomp) + } + return fmt.Sprintf("%s: %s (%s)", e.Prefix, e.Seccomp, e.Errno) +} + +func (e *LibraryError) Is(err error) bool { + if e == nil { + return err == nil + } + if ef, ok := err.(*LibraryError); ok { + return *e == *ef + } + return (e.Seccomp != 0 && errors.Is(err, e.Seccomp)) || + (e.Errno != nil && errors.Is(err, e.Errno)) +} + +var resPrefix = [...]string{ + 0: "", + 1: "seccomp_init failed", + 2: "seccomp_arch_add failed", + 3: "seccomp_arch_add failed (multiarch)", + 4: "internal libseccomp failure", + 5: "seccomp_rule_add failed", + 6: "seccomp_export_bpf failed", + 7: "seccomp_load failed", +} + +type SyscallOpts = C.f_syscall_opts + +const ( + flagVerbose SyscallOpts = C.F_VERBOSE + // FlagExt are project-specific extensions. + FlagExt SyscallOpts = C.F_EXT + // FlagDenyNS denies namespace setup syscalls. + FlagDenyNS SyscallOpts = C.F_DENY_NS + // FlagDenyTTY denies faking input. + FlagDenyTTY SyscallOpts = C.F_DENY_TTY + // FlagDenyDevel denies development-related syscalls. + FlagDenyDevel SyscallOpts = C.F_DENY_DEVEL + // FlagMultiarch allows multiarch/emulation. + FlagMultiarch SyscallOpts = C.F_MULTIARCH + // FlagLinux32 sets PER_LINUX32. + FlagLinux32 SyscallOpts = C.F_LINUX32 + // FlagCan allows AF_CAN. + FlagCan SyscallOpts = C.F_CAN + // FlagBluetooth allows AF_BLUETOOTH. + FlagBluetooth SyscallOpts = C.F_BLUETOOTH +) + +func buildFilter(fd int, opts SyscallOpts) error { + var ( + arch C.uint32_t = 0 + multiarch C.uint32_t = 0 + ) + switch runtime.GOARCH { + case "386": + arch = C.SCMP_ARCH_X86 + case "amd64": + arch = C.SCMP_ARCH_X86_64 + multiarch = C.SCMP_ARCH_X86 + case "arm": + arch = C.SCMP_ARCH_ARM + case "arm64": + arch = C.SCMP_ARCH_AARCH64 + multiarch = C.SCMP_ARCH_ARM + } + + // this removes repeated transitions between C and Go execution + // when producing log output via F_println and CPrintln is nil + if fp := printlnP.Load(); fp != nil { + opts |= flagVerbose + } + + var ret C.int + res, err := C.f_build_filter(&ret, C.int(fd), arch, multiarch, opts) + if prefix := resPrefix[res]; prefix != "" { + return &LibraryError{ + prefix, + -syscall.Errno(ret), + err, + } + } + return err +} |
