507 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			507 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// +build linux
 | 
						|
 | 
						|
// Internal functions for libseccomp Go bindings
 | 
						|
// No exported functions
 | 
						|
 | 
						|
package seccomp
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"os"
 | 
						|
	"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)
 | 
						|
}
 | 
						|
 | 
						|
// Init function: Verify library version is appropriate
 | 
						|
func init() {
 | 
						|
	if !checkVersionAbove(2, 1, 0) {
 | 
						|
		fmt.Fprintf(os.Stderr, "Libseccomp version too low: minimum supported is 2.1.0, detected %d.%d.%d", C.C_VERSION_MAJOR, C.C_VERSION_MINOR, C.C_VERSION_MICRO)
 | 
						|
		os.Exit(-1)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// 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, fmt.Errorf("the thread synchronization attribute is not supported in this version of the library")
 | 
						|
	}
 | 
						|
 | 
						|
	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 fmt.Errorf("the thread synchronization attribute is not supported in this version of the library")
 | 
						|
	}
 | 
						|
 | 
						|
	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 fmt.Errorf("conditional filtering requires libseccomp version >= 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
 | 
						|
	}
 | 
						|
}
 |