summaryrefslogtreecommitdiff
path: root/vendor/github.com/seccomp
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/seccomp')
-rw-r--r--vendor/github.com/seccomp/libseccomp-golang/LICENSE22
-rw-r--r--vendor/github.com/seccomp/libseccomp-golang/README51
-rw-r--r--vendor/github.com/seccomp/libseccomp-golang/seccomp.go902
-rw-r--r--vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go514
4 files changed, 1489 insertions, 0 deletions
diff --git a/vendor/github.com/seccomp/libseccomp-golang/LICENSE b/vendor/github.com/seccomp/libseccomp-golang/LICENSE
new file mode 100644
index 000000000..81cf60de2
--- /dev/null
+++ b/vendor/github.com/seccomp/libseccomp-golang/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2015 Matthew Heon <mheon@redhat.com>
+Copyright (c) 2015 Paul Moore <pmoore@redhat.com>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/seccomp/libseccomp-golang/README b/vendor/github.com/seccomp/libseccomp-golang/README
new file mode 100644
index 000000000..66839a466
--- /dev/null
+++ b/vendor/github.com/seccomp/libseccomp-golang/README
@@ -0,0 +1,51 @@
+libseccomp-golang: Go Language Bindings for the libseccomp Project
+===============================================================================
+https://github.com/seccomp/libseccomp-golang
+https://github.com/seccomp/libseccomp
+
+The libseccomp library provides an easy to use, platform independent, interface
+to the Linux Kernel's syscall filtering mechanism. The libseccomp API is
+designed to abstract away the underlying BPF based syscall filter language and
+present a more conventional function-call based filtering interface that should
+be familiar to, and easily adopted by, application developers.
+
+The libseccomp-golang library provides a Go based interface to the libseccomp
+library.
+
+* Online Resources
+
+The library source repository currently lives on GitHub at the following URLs:
+
+ -> https://github.com/seccomp/libseccomp-golang
+ -> https://github.com/seccomp/libseccomp
+
+The project mailing list is currently hosted on Google Groups at the URL below,
+please note that a Google account is not required to subscribe to the mailing
+list.
+
+ -> https://groups.google.com/d/forum/libseccomp
+
+Documentation is also available at:
+
+ -> https://godoc.org/github.com/seccomp/libseccomp-golang
+
+* Installing the package
+
+The libseccomp-golang bindings require at least Go v1.2.1 and GCC v4.8.4;
+earlier versions may yield unpredictable results. If you meet these
+requirements you can install this package using the command below:
+
+ $ go get github.com/seccomp/libseccomp-golang
+
+* Testing the Library
+
+A number of tests and lint related recipes are provided in the Makefile, if
+you want to run the standard regression tests, you can excute the following:
+
+ $ make check
+
+In order to execute the 'make lint' recipe the 'golint' tool is needed, it
+can be found at:
+
+ -> https://github.com/golang/lint
+
diff --git a/vendor/github.com/seccomp/libseccomp-golang/seccomp.go b/vendor/github.com/seccomp/libseccomp-golang/seccomp.go
new file mode 100644
index 000000000..53bcb024d
--- /dev/null
+++ b/vendor/github.com/seccomp/libseccomp-golang/seccomp.go
@@ -0,0 +1,902 @@
+// +build linux
+
+// Public API specification for libseccomp Go bindings
+// Contains public API for the bindings
+
+// Package seccomp provides bindings for libseccomp, a library wrapping the Linux
+// seccomp syscall. Seccomp enables an application to restrict system call use
+// for itself and its children.
+package seccomp
+
+import (
+ "fmt"
+ "os"
+ "runtime"
+ "strings"
+ "sync"
+ "syscall"
+ "unsafe"
+)
+
+// C wrapping code
+
+// #cgo pkg-config: libseccomp
+// #include <stdlib.h>
+// #include <seccomp.h>
+import "C"
+
+// Exported types
+
+// VersionError denotes that the system libseccomp version is incompatible
+// with this package.
+type VersionError struct {
+ message string
+ minimum string
+}
+
+func (e VersionError) Error() string {
+ format := "Libseccomp version too low: "
+ if e.message != "" {
+ format += e.message + ": "
+ }
+ format += "minimum supported is "
+ if e.minimum != "" {
+ format += e.minimum + ": "
+ } else {
+ format += "2.1.0: "
+ }
+ format += "detected %d.%d.%d"
+ return fmt.Sprintf(format, verMajor, verMinor, verMicro)
+}
+
+// ScmpArch represents a CPU architecture. Seccomp can restrict syscalls on a
+// per-architecture basis.
+type ScmpArch uint
+
+// ScmpAction represents an action to be taken on a filter rule match in
+// libseccomp
+type ScmpAction uint
+
+// ScmpCompareOp represents a comparison operator which can be used in a filter
+// rule
+type ScmpCompareOp uint
+
+// ScmpCondition represents a rule in a libseccomp filter context
+type ScmpCondition struct {
+ Argument uint `json:"argument,omitempty"`
+ Op ScmpCompareOp `json:"operator,omitempty"`
+ Operand1 uint64 `json:"operand_one,omitempty"`
+ Operand2 uint64 `json:"operand_two,omitempty"`
+}
+
+// ScmpSyscall represents a Linux System Call
+type ScmpSyscall int32
+
+// Exported Constants
+
+const (
+ // Valid architectures recognized by libseccomp
+ // ARM64 and all MIPS architectures are unsupported by versions of the
+ // library before v2.2 and will return errors if used
+
+ // ArchInvalid is a placeholder to ensure uninitialized ScmpArch
+ // variables are invalid
+ ArchInvalid ScmpArch = iota
+ // ArchNative is the native architecture of the kernel
+ ArchNative ScmpArch = iota
+ // ArchX86 represents 32-bit x86 syscalls
+ ArchX86 ScmpArch = iota
+ // ArchAMD64 represents 64-bit x86-64 syscalls
+ ArchAMD64 ScmpArch = iota
+ // ArchX32 represents 64-bit x86-64 syscalls (32-bit pointers)
+ ArchX32 ScmpArch = iota
+ // ArchARM represents 32-bit ARM syscalls
+ ArchARM ScmpArch = iota
+ // ArchARM64 represents 64-bit ARM syscalls
+ ArchARM64 ScmpArch = iota
+ // ArchMIPS represents 32-bit MIPS syscalls
+ ArchMIPS ScmpArch = iota
+ // ArchMIPS64 represents 64-bit MIPS syscalls
+ ArchMIPS64 ScmpArch = iota
+ // ArchMIPS64N32 represents 64-bit MIPS syscalls (32-bit pointers)
+ ArchMIPS64N32 ScmpArch = iota
+ // ArchMIPSEL represents 32-bit MIPS syscalls (little endian)
+ ArchMIPSEL ScmpArch = iota
+ // ArchMIPSEL64 represents 64-bit MIPS syscalls (little endian)
+ ArchMIPSEL64 ScmpArch = iota
+ // ArchMIPSEL64N32 represents 64-bit MIPS syscalls (little endian,
+ // 32-bit pointers)
+ ArchMIPSEL64N32 ScmpArch = iota
+ // ArchPPC represents 32-bit POWERPC syscalls
+ ArchPPC ScmpArch = iota
+ // ArchPPC64 represents 64-bit POWER syscalls (big endian)
+ ArchPPC64 ScmpArch = iota
+ // ArchPPC64LE represents 64-bit POWER syscalls (little endian)
+ ArchPPC64LE ScmpArch = iota
+ // ArchS390 represents 31-bit System z/390 syscalls
+ ArchS390 ScmpArch = iota
+ // ArchS390X represents 64-bit System z/390 syscalls
+ ArchS390X ScmpArch = iota
+)
+
+const (
+ // Supported actions on filter match
+
+ // ActInvalid is a placeholder to ensure uninitialized ScmpAction
+ // variables are invalid
+ ActInvalid ScmpAction = iota
+ // ActKill kills the process
+ ActKill ScmpAction = iota
+ // ActTrap throws SIGSYS
+ ActTrap ScmpAction = iota
+ // ActErrno causes the syscall to return a negative error code. This
+ // code can be set with the SetReturnCode method
+ ActErrno ScmpAction = iota
+ // ActTrace causes the syscall to notify tracing processes with the
+ // given error code. This code can be set with the SetReturnCode method
+ ActTrace ScmpAction = iota
+ // ActAllow permits the syscall to continue execution
+ ActAllow ScmpAction = iota
+)
+
+const (
+ // These are comparison operators used in conditional seccomp rules
+ // They are used to compare the value of a single argument of a syscall
+ // against a user-defined constant
+
+ // CompareInvalid is a placeholder to ensure uninitialized ScmpCompareOp
+ // variables are invalid
+ CompareInvalid ScmpCompareOp = iota
+ // CompareNotEqual returns true if the argument is not equal to the
+ // given value
+ CompareNotEqual ScmpCompareOp = iota
+ // CompareLess returns true if the argument is less than the given value
+ CompareLess ScmpCompareOp = iota
+ // CompareLessOrEqual returns true if the argument is less than or equal
+ // to the given value
+ CompareLessOrEqual ScmpCompareOp = iota
+ // CompareEqual returns true if the argument is equal to the given value
+ CompareEqual ScmpCompareOp = iota
+ // CompareGreaterEqual returns true if the argument is greater than or
+ // equal to the given value
+ CompareGreaterEqual ScmpCompareOp = iota
+ // CompareGreater returns true if the argument is greater than the given
+ // value
+ CompareGreater ScmpCompareOp = iota
+ // CompareMaskedEqual returns true if the argument is equal to the given
+ // value, when masked (bitwise &) against the second given value
+ CompareMaskedEqual ScmpCompareOp = iota
+)
+
+// Helpers for types
+
+// GetArchFromString returns an ScmpArch constant from a string representing an
+// architecture
+func GetArchFromString(arch string) (ScmpArch, error) {
+ if err := ensureSupportedVersion(); err != nil {
+ return ArchInvalid, err
+ }
+
+ switch strings.ToLower(arch) {
+ case "x86":
+ return ArchX86, nil
+ case "amd64", "x86-64", "x86_64", "x64":
+ return ArchAMD64, nil
+ case "x32":
+ return ArchX32, nil
+ case "arm":
+ return ArchARM, nil
+ case "arm64", "aarch64":
+ return ArchARM64, nil
+ case "mips":
+ return ArchMIPS, nil
+ case "mips64":
+ return ArchMIPS64, nil
+ case "mips64n32":
+ return ArchMIPS64N32, nil
+ case "mipsel":
+ return ArchMIPSEL, nil
+ case "mipsel64":
+ return ArchMIPSEL64, nil
+ case "mipsel64n32":
+ return ArchMIPSEL64N32, nil
+ case "ppc":
+ return ArchPPC, nil
+ case "ppc64":
+ return ArchPPC64, nil
+ case "ppc64le":
+ return ArchPPC64LE, nil
+ case "s390":
+ return ArchS390, nil
+ case "s390x":
+ return ArchS390X, nil
+ default:
+ return ArchInvalid, fmt.Errorf("cannot convert unrecognized string %s", arch)
+ }
+}
+
+// String returns a string representation of an architecture constant
+func (a ScmpArch) String() string {
+ switch a {
+ case ArchX86:
+ return "x86"
+ case ArchAMD64:
+ return "amd64"
+ case ArchX32:
+ return "x32"
+ case ArchARM:
+ return "arm"
+ case ArchARM64:
+ return "arm64"
+ case ArchMIPS:
+ return "mips"
+ case ArchMIPS64:
+ return "mips64"
+ case ArchMIPS64N32:
+ return "mips64n32"
+ case ArchMIPSEL:
+ return "mipsel"
+ case ArchMIPSEL64:
+ return "mipsel64"
+ case ArchMIPSEL64N32:
+ return "mipsel64n32"
+ case ArchPPC:
+ return "ppc"
+ case ArchPPC64:
+ return "ppc64"
+ case ArchPPC64LE:
+ return "ppc64le"
+ case ArchS390:
+ return "s390"
+ case ArchS390X:
+ return "s390x"
+ case ArchNative:
+ return "native"
+ case ArchInvalid:
+ return "Invalid architecture"
+ default:
+ return "Unknown architecture"
+ }
+}
+
+// String returns a string representation of a comparison operator constant
+func (a ScmpCompareOp) String() string {
+ switch a {
+ case CompareNotEqual:
+ return "Not equal"
+ case CompareLess:
+ return "Less than"
+ case CompareLessOrEqual:
+ return "Less than or equal to"
+ case CompareEqual:
+ return "Equal"
+ case CompareGreaterEqual:
+ return "Greater than or equal to"
+ case CompareGreater:
+ return "Greater than"
+ case CompareMaskedEqual:
+ return "Masked equality"
+ case CompareInvalid:
+ return "Invalid comparison operator"
+ default:
+ return "Unrecognized comparison operator"
+ }
+}
+
+// String returns a string representation of a seccomp match action
+func (a ScmpAction) String() string {
+ switch a & 0xFFFF {
+ case ActKill:
+ return "Action: Kill Process"
+ case ActTrap:
+ return "Action: Send SIGSYS"
+ case ActErrno:
+ return fmt.Sprintf("Action: Return error code %d", (a >> 16))
+ case ActTrace:
+ return fmt.Sprintf("Action: Notify tracing processes with code %d",
+ (a >> 16))
+ case ActAllow:
+ return "Action: Allow system call"
+ default:
+ return "Unrecognized Action"
+ }
+}
+
+// SetReturnCode adds a return code to a supporting ScmpAction, clearing any
+// existing code Only valid on ActErrno and ActTrace. Takes no action otherwise.
+// Accepts 16-bit return code as argument.
+// Returns a valid ScmpAction of the original type with the new error code set.
+func (a ScmpAction) SetReturnCode(code int16) ScmpAction {
+ aTmp := a & 0x0000FFFF
+ if aTmp == ActErrno || aTmp == ActTrace {
+ return (aTmp | (ScmpAction(code)&0xFFFF)<<16)
+ }
+ return a
+}
+
+// GetReturnCode returns the return code of an ScmpAction
+func (a ScmpAction) GetReturnCode() int16 {
+ return int16(a >> 16)
+}
+
+// General utility functions
+
+// GetLibraryVersion returns the version of the library the bindings are built
+// against.
+// The version is formatted as follows: Major.Minor.Micro
+func GetLibraryVersion() (major, minor, micro int) {
+ return verMajor, verMinor, verMicro
+}
+
+// Syscall functions
+
+// GetName retrieves the name of a syscall from its number.
+// Acts on any syscall number.
+// Returns either a string containing the name of the syscall, or an error.
+func (s ScmpSyscall) GetName() (string, error) {
+ return s.GetNameByArch(ArchNative)
+}
+
+// GetNameByArch retrieves the name of a syscall from its number for a given
+// architecture.
+// Acts on any syscall number.
+// Accepts a valid architecture constant.
+// Returns either a string containing the name of the syscall, or an error.
+// if the syscall is unrecognized or an issue occurred.
+func (s ScmpSyscall) GetNameByArch(arch ScmpArch) (string, error) {
+ if err := sanitizeArch(arch); err != nil {
+ return "", err
+ }
+
+ cString := C.seccomp_syscall_resolve_num_arch(arch.toNative(), C.int(s))
+ if cString == nil {
+ return "", fmt.Errorf("could not resolve syscall name")
+ }
+ defer C.free(unsafe.Pointer(cString))
+
+ finalStr := C.GoString(cString)
+ return finalStr, nil
+}
+
+// GetSyscallFromName returns the number of a syscall by name on the kernel's
+// native architecture.
+// Accepts a string containing the name of a syscall.
+// Returns the number of the syscall, or an error if no syscall with that name
+// was found.
+func GetSyscallFromName(name string) (ScmpSyscall, error) {
+ if err := ensureSupportedVersion(); err != nil {
+ return 0, err
+ }
+
+ cString := C.CString(name)
+ defer C.free(unsafe.Pointer(cString))
+
+ result := C.seccomp_syscall_resolve_name(cString)
+ if result == scmpError {
+ return 0, fmt.Errorf("could not resolve name to syscall")
+ }
+
+ return ScmpSyscall(result), nil
+}
+
+// GetSyscallFromNameByArch returns the number of a syscall by name for a given
+// architecture's ABI.
+// Accepts the name of a syscall and an architecture constant.
+// Returns the number of the syscall, or an error if an invalid architecture is
+// passed or a syscall with that name was not found.
+func GetSyscallFromNameByArch(name string, arch ScmpArch) (ScmpSyscall, error) {
+ if err := ensureSupportedVersion(); err != nil {
+ return 0, err
+ }
+ if err := sanitizeArch(arch); err != nil {
+ return 0, err
+ }
+
+ cString := C.CString(name)
+ defer C.free(unsafe.Pointer(cString))
+
+ result := C.seccomp_syscall_resolve_name_arch(arch.toNative(), cString)
+ if result == scmpError {
+ return 0, fmt.Errorf("could not resolve name to syscall")
+ }
+
+ return ScmpSyscall(result), nil
+}
+
+// MakeCondition creates and returns a new condition to attach to a filter rule.
+// Associated rules will only match if this condition is true.
+// Accepts the number the argument we are checking, and a comparison operator
+// and value to compare to.
+// The rule will match if argument $arg (zero-indexed) of the syscall is
+// $COMPARE_OP the provided comparison value.
+// Some comparison operators accept two values. Masked equals, for example,
+// will mask $arg of the syscall with the second value provided (via bitwise
+// AND) and then compare against the first value provided.
+// For example, in the less than or equal case, if the syscall argument was
+// 0 and the value provided was 1, the condition would match, as 0 is less
+// than or equal to 1.
+// Return either an error on bad argument or a valid ScmpCondition struct.
+func MakeCondition(arg uint, comparison ScmpCompareOp, values ...uint64) (ScmpCondition, error) {
+ var condStruct ScmpCondition
+
+ if err := ensureSupportedVersion(); err != nil {
+ return condStruct, err
+ }
+
+ if comparison == CompareInvalid {
+ return condStruct, fmt.Errorf("invalid comparison operator")
+ } else if arg > 5 {
+ return condStruct, fmt.Errorf("syscalls only have up to 6 arguments")
+ } else if len(values) > 2 {
+ return condStruct, fmt.Errorf("conditions can have at most 2 arguments")
+ } else if len(values) == 0 {
+ return condStruct, fmt.Errorf("must provide at least one value to compare against")
+ }
+
+ condStruct.Argument = arg
+ condStruct.Op = comparison
+ condStruct.Operand1 = values[0]
+ if len(values) == 2 {
+ condStruct.Operand2 = values[1]
+ } else {
+ condStruct.Operand2 = 0 // Unused
+ }
+
+ return condStruct, nil
+}
+
+// Utility Functions
+
+// GetNativeArch returns architecture token representing the native kernel
+// architecture
+func GetNativeArch() (ScmpArch, error) {
+ if err := ensureSupportedVersion(); err != nil {
+ return ArchInvalid, err
+ }
+
+ arch := C.seccomp_arch_native()
+
+ return archFromNative(arch)
+}
+
+// Public Filter API
+
+// ScmpFilter represents a filter context in libseccomp.
+// A filter context is initially empty. Rules can be added to it, and it can
+// then be loaded into the kernel.
+type ScmpFilter struct {
+ filterCtx C.scmp_filter_ctx
+ valid bool
+ lock sync.Mutex
+}
+
+// NewFilter creates and returns a new filter context.
+// Accepts a default action to be taken for syscalls which match no rules in
+// the filter.
+// Returns a reference to a valid filter context, or nil and an error if the
+// filter context could not be created or an invalid default action was given.
+func NewFilter(defaultAction ScmpAction) (*ScmpFilter, error) {
+ if err := ensureSupportedVersion(); err != nil {
+ return nil, err
+ }
+
+ if err := sanitizeAction(defaultAction); err != nil {
+ return nil, err
+ }
+
+ fPtr := C.seccomp_init(defaultAction.toNative())
+ if fPtr == nil {
+ return nil, fmt.Errorf("could not create filter")
+ }
+
+ filter := new(ScmpFilter)
+ filter.filterCtx = fPtr
+ filter.valid = true
+ runtime.SetFinalizer(filter, filterFinalizer)
+
+ return filter, nil
+}
+
+// IsValid determines whether a filter context is valid to use.
+// Some operations (Release and Merge) render filter contexts invalid and
+// consequently prevent further use.
+func (f *ScmpFilter) IsValid() bool {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+
+ return f.valid
+}
+
+// Reset resets a filter context, removing all its existing state.
+// Accepts a new default action to be taken for syscalls which do not match.
+// Returns an error if the filter or action provided are invalid.
+func (f *ScmpFilter) Reset(defaultAction ScmpAction) error {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+
+ if err := sanitizeAction(defaultAction); err != nil {
+ return err
+ } else if !f.valid {
+ return errBadFilter
+ }
+
+ retCode := C.seccomp_reset(f.filterCtx, defaultAction.toNative())
+ if retCode != 0 {
+ return syscall.Errno(-1 * retCode)
+ }
+
+ return nil
+}
+
+// Release releases a filter context, freeing its memory. Should be called after
+// loading into the kernel, when the filter is no longer needed.
+// After calling this function, the given filter is no longer valid and cannot
+// be used.
+// Release() will be invoked automatically when a filter context is garbage
+// collected, but can also be called manually to free memory.
+func (f *ScmpFilter) Release() {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+
+ if !f.valid {
+ return
+ }
+
+ f.valid = false
+ C.seccomp_release(f.filterCtx)
+}
+
+// Merge merges two filter contexts.
+// The source filter src will be released as part of the process, and will no
+// longer be usable or valid after this call.
+// To be merged, filters must NOT share any architectures, and all their
+// attributes (Default Action, Bad Arch Action, No New Privs and TSync bools)
+// must match.
+// The filter src will be merged into the filter this is called on.
+// The architectures of the src filter not present in the destination, and all
+// associated rules, will be added to the destination.
+// Returns an error if merging the filters failed.
+func (f *ScmpFilter) Merge(src *ScmpFilter) error {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+
+ src.lock.Lock()
+ defer src.lock.Unlock()
+
+ if !src.valid || !f.valid {
+ return fmt.Errorf("one or more of the filter contexts is invalid or uninitialized")
+ }
+
+ // Merge the filters
+ retCode := C.seccomp_merge(f.filterCtx, src.filterCtx)
+ if syscall.Errno(-1*retCode) == syscall.EINVAL {
+ return fmt.Errorf("filters could not be merged due to a mismatch in attributes or invalid filter")
+ } else if retCode != 0 {
+ return syscall.Errno(-1 * retCode)
+ }
+
+ src.valid = false
+
+ return nil
+}
+
+// IsArchPresent checks if an architecture is present in a filter.
+// If a filter contains an architecture, it uses its default action for
+// syscalls which do not match rules in it, and its rules can match syscalls
+// for that ABI.
+// If a filter does not contain an architecture, all syscalls made to that
+// kernel ABI will fail with the filter's default Bad Architecture Action
+// (by default, killing the process).
+// Accepts an architecture constant.
+// Returns true if the architecture is present in the filter, false otherwise,
+// and an error on an invalid filter context, architecture constant, or an
+// issue with the call to libseccomp.
+func (f *ScmpFilter) IsArchPresent(arch ScmpArch) (bool, error) {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+
+ if err := sanitizeArch(arch); err != nil {
+ return false, err
+ } else if !f.valid {
+ return false, errBadFilter
+ }
+
+ retCode := C.seccomp_arch_exist(f.filterCtx, arch.toNative())
+ if syscall.Errno(-1*retCode) == syscall.EEXIST {
+ // -EEXIST is "arch not present"
+ return false, nil
+ } else if retCode != 0 {
+ return false, syscall.Errno(-1 * retCode)
+ }
+
+ return true, nil
+}
+
+// AddArch adds an architecture to the filter.
+// Accepts an architecture constant.
+// Returns an error on invalid filter context or architecture token, or an
+// issue with the call to libseccomp.
+func (f *ScmpFilter) AddArch(arch ScmpArch) error {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+
+ if err := sanitizeArch(arch); err != nil {
+ return err
+ } else if !f.valid {
+ return errBadFilter
+ }
+
+ // Libseccomp returns -EEXIST if the specified architecture is already
+ // present. Succeed silently in this case, as it's not fatal, and the
+ // architecture is present already.
+ retCode := C.seccomp_arch_add(f.filterCtx, arch.toNative())
+ if retCode != 0 && syscall.Errno(-1*retCode) != syscall.EEXIST {
+ return syscall.Errno(-1 * retCode)
+ }
+
+ return nil
+}
+
+// RemoveArch removes an architecture from the filter.
+// Accepts an architecture constant.
+// Returns an error on invalid filter context or architecture token, or an
+// issue with the call to libseccomp.
+func (f *ScmpFilter) RemoveArch(arch ScmpArch) error {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+
+ if err := sanitizeArch(arch); err != nil {
+ return err
+ } else if !f.valid {
+ return errBadFilter
+ }
+
+ // Similar to AddArch, -EEXIST is returned if the arch is not present
+ // Succeed silently in that case, this is not fatal and the architecture
+ // is not present in the filter after RemoveArch
+ retCode := C.seccomp_arch_remove(f.filterCtx, arch.toNative())
+ if retCode != 0 && syscall.Errno(-1*retCode) != syscall.EEXIST {
+ return syscall.Errno(-1 * retCode)
+ }
+
+ return nil
+}
+
+// Load loads a filter context into the kernel.
+// Returns an error if the filter context is invalid or the syscall failed.
+func (f *ScmpFilter) Load() error {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+
+ if !f.valid {
+ return errBadFilter
+ }
+
+ if retCode := C.seccomp_load(f.filterCtx); retCode != 0 {
+ return syscall.Errno(-1 * retCode)
+ }
+
+ return nil
+}
+
+// GetDefaultAction returns the default action taken on a syscall which does not
+// match a rule in the filter, or an error if an issue was encountered
+// retrieving the value.
+func (f *ScmpFilter) GetDefaultAction() (ScmpAction, error) {
+ action, err := f.getFilterAttr(filterAttrActDefault)
+ if err != nil {
+ return 0x0, err
+ }
+
+ return actionFromNative(action)
+}
+
+// GetBadArchAction returns the default action taken on a syscall for an
+// architecture not in the filter, or an error if an issue was encountered
+// retrieving the value.
+func (f *ScmpFilter) GetBadArchAction() (ScmpAction, error) {
+ action, err := f.getFilterAttr(filterAttrActBadArch)
+ if err != nil {
+ return 0x0, err
+ }
+
+ return actionFromNative(action)
+}
+
+// GetNoNewPrivsBit returns the current state the No New Privileges bit will be set
+// to on the filter being loaded, or an error if an issue was encountered
+// retrieving the value.
+// The No New Privileges bit tells the kernel that new processes run with exec()
+// cannot gain more privileges than the process that ran exec().
+// For example, a process with No New Privileges set would be unable to exec
+// setuid/setgid executables.
+func (f *ScmpFilter) GetNoNewPrivsBit() (bool, error) {
+ noNewPrivs, err := f.getFilterAttr(filterAttrNNP)
+ if err != nil {
+ return false, err
+ }
+
+ if noNewPrivs == 0 {
+ return false, nil
+ }
+
+ return true, nil
+}
+
+// GetTsyncBit returns whether Thread Synchronization will be enabled on the
+// filter being loaded, or an error if an issue was encountered retrieving the
+// value.
+// Thread Sync ensures that all members of the thread group of the calling
+// process will share the same Seccomp filter set.
+// Tsync is a fairly recent addition to the Linux kernel and older kernels
+// lack support. If the running kernel does not support Tsync and it is
+// requested in a filter, Libseccomp will not enable TSync support and will
+// proceed as normal.
+// This function is unavailable before v2.2 of libseccomp and will return an
+// error.
+func (f *ScmpFilter) GetTsyncBit() (bool, error) {
+ tSync, err := f.getFilterAttr(filterAttrTsync)
+ if err != nil {
+ return false, err
+ }
+
+ if tSync == 0 {
+ return false, nil
+ }
+
+ return true, nil
+}
+
+// SetBadArchAction sets the default action taken on a syscall for an
+// architecture not in the filter, or an error if an issue was encountered
+// setting the value.
+func (f *ScmpFilter) SetBadArchAction(action ScmpAction) error {
+ if err := sanitizeAction(action); err != nil {
+ return err
+ }
+
+ return f.setFilterAttr(filterAttrActBadArch, action.toNative())
+}
+
+// SetNoNewPrivsBit sets the state of the No New Privileges bit, which will be
+// applied on filter load, or an error if an issue was encountered setting the
+// value.
+// Filters with No New Privileges set to 0 can only be loaded if the process
+// has the CAP_SYS_ADMIN capability.
+func (f *ScmpFilter) SetNoNewPrivsBit(state bool) error {
+ var toSet C.uint32_t = 0x0
+
+ if state {
+ toSet = 0x1
+ }
+
+ return f.setFilterAttr(filterAttrNNP, toSet)
+}
+
+// SetTsync sets whether Thread Synchronization will be enabled on the filter
+// being loaded. Returns an error if setting Tsync failed, or the filter is
+// invalid.
+// Thread Sync ensures that all members of the thread group of the calling
+// process will share the same Seccomp filter set.
+// Tsync is a fairly recent addition to the Linux kernel and older kernels
+// lack support. If the running kernel does not support Tsync and it is
+// requested in a filter, Libseccomp will not enable TSync support and will
+// proceed as normal.
+// This function is unavailable before v2.2 of libseccomp and will return an
+// error.
+func (f *ScmpFilter) SetTsync(enable bool) error {
+ var toSet C.uint32_t = 0x0
+
+ if enable {
+ toSet = 0x1
+ }
+
+ return f.setFilterAttr(filterAttrTsync, toSet)
+}
+
+// SetSyscallPriority sets a syscall's priority.
+// This provides a hint to the filter generator in libseccomp about the
+// importance of this syscall. High-priority syscalls are placed
+// first in the filter code, and incur less overhead (at the expense of
+// lower-priority syscalls).
+func (f *ScmpFilter) SetSyscallPriority(call ScmpSyscall, priority uint8) error {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+
+ if !f.valid {
+ return errBadFilter
+ }
+
+ if retCode := C.seccomp_syscall_priority(f.filterCtx, C.int(call),
+ C.uint8_t(priority)); retCode != 0 {
+ return syscall.Errno(-1 * retCode)
+ }
+
+ return nil
+}
+
+// AddRule adds a single rule for an unconditional action on a syscall.
+// Accepts the number of the syscall and the action to be taken on the call
+// being made.
+// Returns an error if an issue was encountered adding the rule.
+func (f *ScmpFilter) AddRule(call ScmpSyscall, action ScmpAction) error {
+ return f.addRuleGeneric(call, action, false, nil)
+}
+
+// AddRuleExact adds a single rule for an unconditional action on a syscall.
+// Accepts the number of the syscall and the action to be taken on the call
+// being made.
+// No modifications will be made to the rule, and it will fail to add if it
+// cannot be applied to the current architecture without modification.
+// The rule will function exactly as described, but it may not function identically
+// (or be able to be applied to) all architectures.
+// Returns an error if an issue was encountered adding the rule.
+func (f *ScmpFilter) AddRuleExact(call ScmpSyscall, action ScmpAction) error {
+ return f.addRuleGeneric(call, action, true, nil)
+}
+
+// AddRuleConditional adds a single rule for a conditional action on a syscall.
+// Returns an error if an issue was encountered adding the rule.
+// All conditions must match for the rule to match.
+// There is a bug in library versions below v2.2.1 which can, in some cases,
+// cause conditions to be lost when more than one are used. Consequently,
+// AddRuleConditional is disabled on library versions lower than v2.2.1
+func (f *ScmpFilter) AddRuleConditional(call ScmpSyscall, action ScmpAction, conds []ScmpCondition) error {
+ return f.addRuleGeneric(call, action, false, conds)
+}
+
+// AddRuleConditionalExact adds a single rule for a conditional action on a
+// syscall.
+// No modifications will be made to the rule, and it will fail to add if it
+// cannot be applied to the current architecture without modification.
+// The rule will function exactly as described, but it may not function identically
+// (or be able to be applied to) all architectures.
+// Returns an error if an issue was encountered adding the rule.
+// There is a bug in library versions below v2.2.1 which can, in some cases,
+// cause conditions to be lost when more than one are used. Consequently,
+// AddRuleConditionalExact is disabled on library versions lower than v2.2.1
+func (f *ScmpFilter) AddRuleConditionalExact(call ScmpSyscall, action ScmpAction, conds []ScmpCondition) error {
+ return f.addRuleGeneric(call, action, true, conds)
+}
+
+// ExportPFC output PFC-formatted, human-readable dump of a filter context's
+// rules to a file.
+// Accepts file to write to (must be open for writing).
+// Returns an error if writing to the file fails.
+func (f *ScmpFilter) ExportPFC(file *os.File) error {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+
+ fd := file.Fd()
+
+ if !f.valid {
+ return errBadFilter
+ }
+
+ if retCode := C.seccomp_export_pfc(f.filterCtx, C.int(fd)); retCode != 0 {
+ return syscall.Errno(-1 * retCode)
+ }
+
+ return nil
+}
+
+// ExportBPF outputs Berkeley Packet Filter-formatted, kernel-readable dump of a
+// filter context's rules to a file.
+// Accepts file to write to (must be open for writing).
+// Returns an error if writing to the file fails.
+func (f *ScmpFilter) ExportBPF(file *os.File) error {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+
+ fd := file.Fd()
+
+ if !f.valid {
+ return errBadFilter
+ }
+
+ if retCode := C.seccomp_export_bpf(f.filterCtx, C.int(fd)); retCode != 0 {
+ return syscall.Errno(-1 * retCode)
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go b/vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go
new file mode 100644
index 000000000..b0caac91b
--- /dev/null
+++ b/vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go
@@ -0,0 +1,514 @@
+// +build linux
+
+// Internal functions for libseccomp Go bindings
+// No exported functions
+
+package seccomp
+
+import (
+ "fmt"
+ "syscall"
+)
+
+// Unexported C wrapping code - provides the C-Golang interface
+// Get the seccomp header in scope
+// Need stdlib.h for free() on cstrings
+
+// #cgo pkg-config: libseccomp
+/*
+#include <stdlib.h>
+#include <seccomp.h>
+
+#if SCMP_VER_MAJOR < 2
+#error Minimum supported version of Libseccomp is v2.1.0
+#elif SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 1
+#error Minimum supported version of Libseccomp is v2.1.0
+#endif
+
+#define ARCH_BAD ~0
+
+const uint32_t C_ARCH_BAD = ARCH_BAD;
+
+#ifndef SCMP_ARCH_AARCH64
+#define SCMP_ARCH_AARCH64 ARCH_BAD
+#endif
+
+#ifndef SCMP_ARCH_MIPS
+#define SCMP_ARCH_MIPS ARCH_BAD
+#endif
+
+#ifndef SCMP_ARCH_MIPS64
+#define SCMP_ARCH_MIPS64 ARCH_BAD
+#endif
+
+#ifndef SCMP_ARCH_MIPS64N32
+#define SCMP_ARCH_MIPS64N32 ARCH_BAD
+#endif
+
+#ifndef SCMP_ARCH_MIPSEL
+#define SCMP_ARCH_MIPSEL ARCH_BAD
+#endif
+
+#ifndef SCMP_ARCH_MIPSEL64
+#define SCMP_ARCH_MIPSEL64 ARCH_BAD
+#endif
+
+#ifndef SCMP_ARCH_MIPSEL64N32
+#define SCMP_ARCH_MIPSEL64N32 ARCH_BAD
+#endif
+
+#ifndef SCMP_ARCH_PPC
+#define SCMP_ARCH_PPC ARCH_BAD
+#endif
+
+#ifndef SCMP_ARCH_PPC64
+#define SCMP_ARCH_PPC64 ARCH_BAD
+#endif
+
+#ifndef SCMP_ARCH_PPC64LE
+#define SCMP_ARCH_PPC64LE ARCH_BAD
+#endif
+
+#ifndef SCMP_ARCH_S390
+#define SCMP_ARCH_S390 ARCH_BAD
+#endif
+
+#ifndef SCMP_ARCH_S390X
+#define SCMP_ARCH_S390X ARCH_BAD
+#endif
+
+const uint32_t C_ARCH_NATIVE = SCMP_ARCH_NATIVE;
+const uint32_t C_ARCH_X86 = SCMP_ARCH_X86;
+const uint32_t C_ARCH_X86_64 = SCMP_ARCH_X86_64;
+const uint32_t C_ARCH_X32 = SCMP_ARCH_X32;
+const uint32_t C_ARCH_ARM = SCMP_ARCH_ARM;
+const uint32_t C_ARCH_AARCH64 = SCMP_ARCH_AARCH64;
+const uint32_t C_ARCH_MIPS = SCMP_ARCH_MIPS;
+const uint32_t C_ARCH_MIPS64 = SCMP_ARCH_MIPS64;
+const uint32_t C_ARCH_MIPS64N32 = SCMP_ARCH_MIPS64N32;
+const uint32_t C_ARCH_MIPSEL = SCMP_ARCH_MIPSEL;
+const uint32_t C_ARCH_MIPSEL64 = SCMP_ARCH_MIPSEL64;
+const uint32_t C_ARCH_MIPSEL64N32 = SCMP_ARCH_MIPSEL64N32;
+const uint32_t C_ARCH_PPC = SCMP_ARCH_PPC;
+const uint32_t C_ARCH_PPC64 = SCMP_ARCH_PPC64;
+const uint32_t C_ARCH_PPC64LE = SCMP_ARCH_PPC64LE;
+const uint32_t C_ARCH_S390 = SCMP_ARCH_S390;
+const uint32_t C_ARCH_S390X = SCMP_ARCH_S390X;
+
+const uint32_t C_ACT_KILL = SCMP_ACT_KILL;
+const uint32_t C_ACT_TRAP = SCMP_ACT_TRAP;
+const uint32_t C_ACT_ERRNO = SCMP_ACT_ERRNO(0);
+const uint32_t C_ACT_TRACE = SCMP_ACT_TRACE(0);
+const uint32_t C_ACT_ALLOW = SCMP_ACT_ALLOW;
+
+// If TSync is not supported, make sure it doesn't map to a supported filter attribute
+// Don't worry about major version < 2, the minimum version checks should catch that case
+#if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 2
+#define SCMP_FLTATR_CTL_TSYNC _SCMP_CMP_MIN
+#endif
+
+const uint32_t C_ATTRIBUTE_DEFAULT = (uint32_t)SCMP_FLTATR_ACT_DEFAULT;
+const uint32_t C_ATTRIBUTE_BADARCH = (uint32_t)SCMP_FLTATR_ACT_BADARCH;
+const uint32_t C_ATTRIBUTE_NNP = (uint32_t)SCMP_FLTATR_CTL_NNP;
+const uint32_t C_ATTRIBUTE_TSYNC = (uint32_t)SCMP_FLTATR_CTL_TSYNC;
+
+const int C_CMP_NE = (int)SCMP_CMP_NE;
+const int C_CMP_LT = (int)SCMP_CMP_LT;
+const int C_CMP_LE = (int)SCMP_CMP_LE;
+const int C_CMP_EQ = (int)SCMP_CMP_EQ;
+const int C_CMP_GE = (int)SCMP_CMP_GE;
+const int C_CMP_GT = (int)SCMP_CMP_GT;
+const int C_CMP_MASKED_EQ = (int)SCMP_CMP_MASKED_EQ;
+
+const int C_VERSION_MAJOR = SCMP_VER_MAJOR;
+const int C_VERSION_MINOR = SCMP_VER_MINOR;
+const int C_VERSION_MICRO = SCMP_VER_MICRO;
+
+typedef struct scmp_arg_cmp* scmp_cast_t;
+
+// Wrapper to create an scmp_arg_cmp struct
+void*
+make_struct_arg_cmp(
+ unsigned int arg,
+ int compare,
+ uint64_t a,
+ uint64_t b
+ )
+{
+ struct scmp_arg_cmp *s = malloc(sizeof(struct scmp_arg_cmp));
+
+ s->arg = arg;
+ s->op = compare;
+ s->datum_a = a;
+ s->datum_b = b;
+
+ return s;
+}
+*/
+import "C"
+
+// Nonexported types
+type scmpFilterAttr uint32
+
+// Nonexported constants
+
+const (
+ filterAttrActDefault scmpFilterAttr = iota
+ filterAttrActBadArch scmpFilterAttr = iota
+ filterAttrNNP scmpFilterAttr = iota
+ filterAttrTsync scmpFilterAttr = iota
+)
+
+const (
+ // An error return from certain libseccomp functions
+ scmpError C.int = -1
+ // Comparison boundaries to check for architecture validity
+ archStart ScmpArch = ArchNative
+ archEnd ScmpArch = ArchS390X
+ // Comparison boundaries to check for action validity
+ actionStart ScmpAction = ActKill
+ actionEnd ScmpAction = ActAllow
+ // Comparison boundaries to check for comparison operator validity
+ compareOpStart ScmpCompareOp = CompareNotEqual
+ compareOpEnd ScmpCompareOp = CompareMaskedEqual
+)
+
+var (
+ // Error thrown on bad filter context
+ errBadFilter = fmt.Errorf("filter is invalid or uninitialized")
+ // Constants representing library major, minor, and micro versions
+ verMajor = int(C.C_VERSION_MAJOR)
+ verMinor = int(C.C_VERSION_MINOR)
+ verMicro = int(C.C_VERSION_MICRO)
+)
+
+// Nonexported functions
+
+// Check if library version is greater than or equal to the given one
+func checkVersionAbove(major, minor, micro int) bool {
+ return (verMajor > major) ||
+ (verMajor == major && verMinor > minor) ||
+ (verMajor == major && verMinor == minor && verMicro >= micro)
+}
+
+// Ensure that the library is supported, i.e. >= 2.1.0.
+func ensureSupportedVersion() error {
+ if !checkVersionAbove(2, 1, 0) {
+ return VersionError{}
+ }
+ return nil
+}
+
+// Filter helpers
+
+// Filter finalizer - ensure that kernel context for filters is freed
+func filterFinalizer(f *ScmpFilter) {
+ f.Release()
+}
+
+// Get a raw filter attribute
+func (f *ScmpFilter) getFilterAttr(attr scmpFilterAttr) (C.uint32_t, error) {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+
+ if !f.valid {
+ return 0x0, errBadFilter
+ }
+
+ if !checkVersionAbove(2, 2, 0) && attr == filterAttrTsync {
+ return 0x0, VersionError{
+ message: "thread synchronization attribute is not supported",
+ minimum: "2.2.0",
+ }
+ }
+
+ var attribute C.uint32_t
+
+ retCode := C.seccomp_attr_get(f.filterCtx, attr.toNative(), &attribute)
+ if retCode != 0 {
+ return 0x0, syscall.Errno(-1 * retCode)
+ }
+
+ return attribute, nil
+}
+
+// Set a raw filter attribute
+func (f *ScmpFilter) setFilterAttr(attr scmpFilterAttr, value C.uint32_t) error {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+
+ if !f.valid {
+ return errBadFilter
+ }
+
+ if !checkVersionAbove(2, 2, 0) && attr == filterAttrTsync {
+ return VersionError{
+ message: "thread synchronization attribute is not supported",
+ minimum: "2.2.0",
+ }
+ }
+
+ retCode := C.seccomp_attr_set(f.filterCtx, attr.toNative(), value)
+ if retCode != 0 {
+ return syscall.Errno(-1 * retCode)
+ }
+
+ return nil
+}
+
+// DOES NOT LOCK OR CHECK VALIDITY
+// Assumes caller has already done this
+// Wrapper for seccomp_rule_add_... functions
+func (f *ScmpFilter) addRuleWrapper(call ScmpSyscall, action ScmpAction, exact bool, cond C.scmp_cast_t) error {
+ var length C.uint
+ if cond != nil {
+ length = 1
+ } else {
+ length = 0
+ }
+
+ var retCode C.int
+ if exact {
+ retCode = C.seccomp_rule_add_exact_array(f.filterCtx, action.toNative(), C.int(call), length, cond)
+ } else {
+ retCode = C.seccomp_rule_add_array(f.filterCtx, action.toNative(), C.int(call), length, cond)
+ }
+
+ if syscall.Errno(-1*retCode) == syscall.EFAULT {
+ return fmt.Errorf("unrecognized syscall")
+ } else if syscall.Errno(-1*retCode) == syscall.EPERM {
+ return fmt.Errorf("requested action matches default action of filter")
+ } else if retCode != 0 {
+ return syscall.Errno(-1 * retCode)
+ }
+
+ return nil
+}
+
+// Generic add function for filter rules
+func (f *ScmpFilter) addRuleGeneric(call ScmpSyscall, action ScmpAction, exact bool, conds []ScmpCondition) error {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+
+ if !f.valid {
+ return errBadFilter
+ }
+
+ if len(conds) == 0 {
+ if err := f.addRuleWrapper(call, action, exact, nil); err != nil {
+ return err
+ }
+ } else {
+ // We don't support conditional filtering in library version v2.1
+ if !checkVersionAbove(2, 2, 1) {
+ return VersionError{
+ message: "conditional filtering is not supported",
+ minimum: "2.2.1",
+ }
+ }
+
+ for _, cond := range conds {
+ cmpStruct := C.make_struct_arg_cmp(C.uint(cond.Argument), cond.Op.toNative(), C.uint64_t(cond.Operand1), C.uint64_t(cond.Operand2))
+ defer C.free(cmpStruct)
+
+ if err := f.addRuleWrapper(call, action, exact, C.scmp_cast_t(cmpStruct)); err != nil {
+ return err
+ }
+ }
+ }
+
+ return nil
+}
+
+// Generic Helpers
+
+// Helper - Sanitize Arch token input
+func sanitizeArch(in ScmpArch) error {
+ if in < archStart || in > archEnd {
+ return fmt.Errorf("unrecognized architecture")
+ }
+
+ if in.toNative() == C.C_ARCH_BAD {
+ return fmt.Errorf("architecture is not supported on this version of the library")
+ }
+
+ return nil
+}
+
+func sanitizeAction(in ScmpAction) error {
+ inTmp := in & 0x0000FFFF
+ if inTmp < actionStart || inTmp > actionEnd {
+ return fmt.Errorf("unrecognized action")
+ }
+
+ if inTmp != ActTrace && inTmp != ActErrno && (in&0xFFFF0000) != 0 {
+ return fmt.Errorf("highest 16 bits must be zeroed except for Trace and Errno")
+ }
+
+ return nil
+}
+
+func sanitizeCompareOp(in ScmpCompareOp) error {
+ if in < compareOpStart || in > compareOpEnd {
+ return fmt.Errorf("unrecognized comparison operator")
+ }
+
+ return nil
+}
+
+func archFromNative(a C.uint32_t) (ScmpArch, error) {
+ switch a {
+ case C.C_ARCH_X86:
+ return ArchX86, nil
+ case C.C_ARCH_X86_64:
+ return ArchAMD64, nil
+ case C.C_ARCH_X32:
+ return ArchX32, nil
+ case C.C_ARCH_ARM:
+ return ArchARM, nil
+ case C.C_ARCH_NATIVE:
+ return ArchNative, nil
+ case C.C_ARCH_AARCH64:
+ return ArchARM64, nil
+ case C.C_ARCH_MIPS:
+ return ArchMIPS, nil
+ case C.C_ARCH_MIPS64:
+ return ArchMIPS64, nil
+ case C.C_ARCH_MIPS64N32:
+ return ArchMIPS64N32, nil
+ case C.C_ARCH_MIPSEL:
+ return ArchMIPSEL, nil
+ case C.C_ARCH_MIPSEL64:
+ return ArchMIPSEL64, nil
+ case C.C_ARCH_MIPSEL64N32:
+ return ArchMIPSEL64N32, nil
+ case C.C_ARCH_PPC:
+ return ArchPPC, nil
+ case C.C_ARCH_PPC64:
+ return ArchPPC64, nil
+ case C.C_ARCH_PPC64LE:
+ return ArchPPC64LE, nil
+ case C.C_ARCH_S390:
+ return ArchS390, nil
+ case C.C_ARCH_S390X:
+ return ArchS390X, nil
+ default:
+ return 0x0, fmt.Errorf("unrecognized architecture")
+ }
+}
+
+// Only use with sanitized arches, no error handling
+func (a ScmpArch) toNative() C.uint32_t {
+ switch a {
+ case ArchX86:
+ return C.C_ARCH_X86
+ case ArchAMD64:
+ return C.C_ARCH_X86_64
+ case ArchX32:
+ return C.C_ARCH_X32
+ case ArchARM:
+ return C.C_ARCH_ARM
+ case ArchARM64:
+ return C.C_ARCH_AARCH64
+ case ArchMIPS:
+ return C.C_ARCH_MIPS
+ case ArchMIPS64:
+ return C.C_ARCH_MIPS64
+ case ArchMIPS64N32:
+ return C.C_ARCH_MIPS64N32
+ case ArchMIPSEL:
+ return C.C_ARCH_MIPSEL
+ case ArchMIPSEL64:
+ return C.C_ARCH_MIPSEL64
+ case ArchMIPSEL64N32:
+ return C.C_ARCH_MIPSEL64N32
+ case ArchPPC:
+ return C.C_ARCH_PPC
+ case ArchPPC64:
+ return C.C_ARCH_PPC64
+ case ArchPPC64LE:
+ return C.C_ARCH_PPC64LE
+ case ArchS390:
+ return C.C_ARCH_S390
+ case ArchS390X:
+ return C.C_ARCH_S390X
+ case ArchNative:
+ return C.C_ARCH_NATIVE
+ default:
+ return 0x0
+ }
+}
+
+// Only use with sanitized ops, no error handling
+func (a ScmpCompareOp) toNative() C.int {
+ switch a {
+ case CompareNotEqual:
+ return C.C_CMP_NE
+ case CompareLess:
+ return C.C_CMP_LT
+ case CompareLessOrEqual:
+ return C.C_CMP_LE
+ case CompareEqual:
+ return C.C_CMP_EQ
+ case CompareGreaterEqual:
+ return C.C_CMP_GE
+ case CompareGreater:
+ return C.C_CMP_GT
+ case CompareMaskedEqual:
+ return C.C_CMP_MASKED_EQ
+ default:
+ return 0x0
+ }
+}
+
+func actionFromNative(a C.uint32_t) (ScmpAction, error) {
+ aTmp := a & 0xFFFF
+ switch a & 0xFFFF0000 {
+ case C.C_ACT_KILL:
+ return ActKill, nil
+ case C.C_ACT_TRAP:
+ return ActTrap, nil
+ case C.C_ACT_ERRNO:
+ return ActErrno.SetReturnCode(int16(aTmp)), nil
+ case C.C_ACT_TRACE:
+ return ActTrace.SetReturnCode(int16(aTmp)), nil
+ case C.C_ACT_ALLOW:
+ return ActAllow, nil
+ default:
+ return 0x0, fmt.Errorf("unrecognized action")
+ }
+}
+
+// Only use with sanitized actions, no error handling
+func (a ScmpAction) toNative() C.uint32_t {
+ switch a & 0xFFFF {
+ case ActKill:
+ return C.C_ACT_KILL
+ case ActTrap:
+ return C.C_ACT_TRAP
+ case ActErrno:
+ return C.C_ACT_ERRNO | (C.uint32_t(a) >> 16)
+ case ActTrace:
+ return C.C_ACT_TRACE | (C.uint32_t(a) >> 16)
+ case ActAllow:
+ return C.C_ACT_ALLOW
+ default:
+ return 0x0
+ }
+}
+
+// Internal only, assumes safe attribute
+func (a scmpFilterAttr) toNative() uint32 {
+ switch a {
+ case filterAttrActDefault:
+ return uint32(C.C_ATTRIBUTE_DEFAULT)
+ case filterAttrActBadArch:
+ return uint32(C.C_ATTRIBUTE_BADARCH)
+ case filterAttrNNP:
+ return uint32(C.C_ATTRIBUTE_NNP)
+ case filterAttrTsync:
+ return uint32(C.C_ATTRIBUTE_TSYNC)
+ default:
+ return 0x0
+ }
+}