summaryrefslogtreecommitdiff
path: root/vendor/github.com/seccomp/libseccomp-golang
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/seccomp/libseccomp-golang')
-rw-r--r--vendor/github.com/seccomp/libseccomp-golang/CHANGELOG11
-rw-r--r--vendor/github.com/seccomp/libseccomp-golang/seccomp.go117
-rw-r--r--vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go237
3 files changed, 233 insertions, 132 deletions
diff --git a/vendor/github.com/seccomp/libseccomp-golang/CHANGELOG b/vendor/github.com/seccomp/libseccomp-golang/CHANGELOG
index 823aeb7f8..a01d9a722 100644
--- a/vendor/github.com/seccomp/libseccomp-golang/CHANGELOG
+++ b/vendor/github.com/seccomp/libseccomp-golang/CHANGELOG
@@ -2,5 +2,16 @@ libseccomp-golang: Releases
===============================================================================
https://github.com/seccomp/libseccomp-golang
+* Version 0.9.1 - May 21, 2019
+- Minimum supported version of libseccomp bumped to v2.2.0
+- Use Libseccomp's `seccomp_version` API to retrieve library version
+- Unconditionally set TSync attribute for filters, due to Go's heavily threaded nature
+- Fix CVE-2017-18367 - Multiple syscall arguments were incorrectly combined with logical-OR, instead of logical-AND
+- Fix a failure to build on Debian-based distributions due to CGo code
+- Fix unit test failures on 32-bit architectures
+- Improve several errors to be more verbose about their causes
+- Add support for SCMP_ACT_LOG (with libseccomp versions 2.4.x and higher), permitting syscalls but logging their execution
+- Add support for SCMP_FLTATR_CTL_LOG (with libseccomp versions 2.4.x and higher), logging not-allowed actions when they are denied
+
* Version 0.9.0 - January 5, 2017
- Initial tagged release
diff --git a/vendor/github.com/seccomp/libseccomp-golang/seccomp.go b/vendor/github.com/seccomp/libseccomp-golang/seccomp.go
index 53bcb024d..a3cc53822 100644
--- a/vendor/github.com/seccomp/libseccomp-golang/seccomp.go
+++ b/vendor/github.com/seccomp/libseccomp-golang/seccomp.go
@@ -43,7 +43,7 @@ func (e VersionError) Error() string {
if e.minimum != "" {
format += e.minimum + ": "
} else {
- format += "2.1.0: "
+ format += "2.2.0: "
}
format += "detected %d.%d.%d"
return fmt.Sprintf(format, verMajor, verMinor, verMicro)
@@ -76,8 +76,8 @@ type ScmpSyscall int32
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
+ // PowerPC and S390(x) architectures are unavailable below library version
+ // v2.3.0 and will returns errors if used with incompatible libraries
// ArchInvalid is a placeholder to ensure uninitialized ScmpArch
// variables are invalid
@@ -137,6 +137,10 @@ const (
ActTrace ScmpAction = iota
// ActAllow permits the syscall to continue execution
ActAllow ScmpAction = iota
+ // ActLog permits the syscall to continue execution after logging it.
+ // This action is only usable when libseccomp API level 3 or higher is
+ // supported.
+ ActLog ScmpAction = iota
)
const (
@@ -211,7 +215,7 @@ func GetArchFromString(arch string) (ScmpArch, error) {
case "s390x":
return ArchS390X, nil
default:
- return ArchInvalid, fmt.Errorf("cannot convert unrecognized string %s", arch)
+ return ArchInvalid, fmt.Errorf("cannot convert unrecognized string %q", arch)
}
}
@@ -255,7 +259,7 @@ func (a ScmpArch) String() string {
case ArchInvalid:
return "Invalid architecture"
default:
- return "Unknown architecture"
+ return fmt.Sprintf("Unknown architecture %#x", uint(a))
}
}
@@ -279,7 +283,7 @@ func (a ScmpCompareOp) String() string {
case CompareInvalid:
return "Invalid comparison operator"
default:
- return "Unrecognized comparison operator"
+ return fmt.Sprintf("Unrecognized comparison operator %#x", uint(a))
}
}
@@ -295,10 +299,12 @@ func (a ScmpAction) String() string {
case ActTrace:
return fmt.Sprintf("Action: Notify tracing processes with code %d",
(a >> 16))
+ case ActLog:
+ return "Action: Log system call"
case ActAllow:
return "Action: Allow system call"
default:
- return "Unrecognized Action"
+ return fmt.Sprintf("Unrecognized Action %#x", uint(a))
}
}
@@ -324,10 +330,29 @@ func (a ScmpAction) GetReturnCode() int16 {
// 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) {
+func GetLibraryVersion() (major, minor, micro uint) {
return verMajor, verMinor, verMicro
}
+// GetApi returns the API level supported by the system.
+// Returns a positive int containing the API level, or 0 with an error if the
+// API level could not be detected due to the library being older than v2.4.0.
+// See the seccomp_api_get(3) man page for details on available API levels:
+// https://github.com/seccomp/libseccomp/blob/master/doc/man/man3/seccomp_api_get.3
+func GetApi() (uint, error) {
+ return getApi()
+}
+
+// SetApi forcibly sets the API level. General use of this function is strongly
+// discouraged.
+// Returns an error if the API level could not be set. An error is always
+// returned if the library is older than v2.4.0
+// See the seccomp_api_get(3) man page for details on available API levels:
+// https://github.com/seccomp/libseccomp/blob/master/doc/man/man3/seccomp_api_get.3
+func SetApi(api uint) error {
+ return setApi(api)
+}
+
// Syscall functions
// GetName retrieves the name of a syscall from its number.
@@ -350,7 +375,7 @@ func (s ScmpSyscall) GetNameByArch(arch ScmpArch) (string, error) {
cString := C.seccomp_syscall_resolve_num_arch(arch.toNative(), C.int(s))
if cString == nil {
- return "", fmt.Errorf("could not resolve syscall name")
+ return "", fmt.Errorf("could not resolve syscall name for %#x", int32(s))
}
defer C.free(unsafe.Pointer(cString))
@@ -373,7 +398,7 @@ func GetSyscallFromName(name string) (ScmpSyscall, error) {
result := C.seccomp_syscall_resolve_name(cString)
if result == scmpError {
- return 0, fmt.Errorf("could not resolve name to syscall")
+ return 0, fmt.Errorf("could not resolve name to syscall: %q", name)
}
return ScmpSyscall(result), nil
@@ -397,7 +422,7 @@ func GetSyscallFromNameByArch(name string, arch ScmpArch) (ScmpSyscall, error) {
result := C.seccomp_syscall_resolve_name_arch(arch.toNative(), cString)
if result == scmpError {
- return 0, fmt.Errorf("could not resolve name to syscall")
+ return 0, fmt.Errorf("could not resolve name to syscall: %q on %v", name, arch)
}
return ScmpSyscall(result), nil
@@ -426,9 +451,9 @@ func MakeCondition(arg uint, comparison ScmpCompareOp, values ...uint64) (ScmpCo
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")
+ return condStruct, fmt.Errorf("syscalls only have up to 6 arguments (%d given)", arg)
} else if len(values) > 2 {
- return condStruct, fmt.Errorf("conditions can have at most 2 arguments")
+ return condStruct, fmt.Errorf("conditions can have at most 2 arguments (%d given)", len(values))
} else if len(values) == 0 {
return condStruct, fmt.Errorf("must provide at least one value to compare against")
}
@@ -494,6 +519,13 @@ func NewFilter(defaultAction ScmpAction) (*ScmpFilter, error) {
filter.valid = true
runtime.SetFinalizer(filter, filterFinalizer)
+ // Enable TSync so all goroutines will receive the same rules
+ // If the kernel does not support TSYNC, allow us to continue without error
+ if err := filter.setFilterAttr(filterAttrTsync, 0x1); err != nil && err != syscall.ENOTSUP {
+ filter.Release()
+ return nil, fmt.Errorf("could not create filter - error setting tsync bit: %v", err)
+ }
+
return filter, nil
}
@@ -550,7 +582,7 @@ func (f *ScmpFilter) Release() {
// 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)
+// attributes (Default Action, Bad Arch Action, and No New Privs 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
@@ -723,24 +755,24 @@ func (f *ScmpFilter) GetNoNewPrivsBit() (bool, error) {
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)
+// GetLogBit returns the current state the Log bit will be set to on the filter
+// being loaded, or an error if an issue was encountered retrieving the value.
+// The Log bit tells the kernel that all actions taken by the filter, with the
+// exception of ActAllow, should be logged.
+// The Log bit is only usable when libseccomp API level 3 or higher is
+// supported.
+func (f *ScmpFilter) GetLogBit() (bool, error) {
+ log, err := f.getFilterAttr(filterAttrLog)
if err != nil {
+ api, apiErr := getApi()
+ if (apiErr != nil && api == 0) || (apiErr == nil && api < 3) {
+ return false, fmt.Errorf("getting the log bit is only supported in libseccomp 2.4.0 and newer with API level 3 or higher")
+ }
+
return false, err
}
- if tSync == 0 {
+ if log == 0 {
return false, nil
}
@@ -773,25 +805,26 @@ func (f *ScmpFilter) SetNoNewPrivsBit(state bool) error {
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 {
+// SetLogBit sets the state of the Log bit, which will be applied on filter
+// load, or an error if an issue was encountered setting the value.
+// The Log bit is only usable when libseccomp API level 3 or higher is
+// supported.
+func (f *ScmpFilter) SetLogBit(state bool) error {
var toSet C.uint32_t = 0x0
- if enable {
+ if state {
toSet = 0x1
}
- return f.setFilterAttr(filterAttrTsync, toSet)
+ err := f.setFilterAttr(filterAttrLog, toSet)
+ if err != nil {
+ api, apiErr := getApi()
+ if (apiErr != nil && api == 0) || (apiErr == nil && api < 3) {
+ return fmt.Errorf("setting the log bit is only supported in libseccomp 2.4.0 and newer with API level 3 or higher")
+ }
+ }
+
+ return err
}
// SetSyscallPriority sets a syscall's priority.
diff --git a/vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go b/vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go
index b0caac91b..4e36b27ae 100644
--- a/vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go
+++ b/vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go
@@ -16,47 +16,20 @@ import (
// #cgo pkg-config: libseccomp
/*
+#include <errno.h>
#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
+#error Minimum supported version of Libseccomp is v2.2.0
+#elif SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 2
+#error Minimum supported version of Libseccomp is v2.2.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
@@ -95,22 +68,29 @@ 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;
+#ifndef SCMP_ACT_LOG
+#define SCMP_ACT_LOG 0x7ffc0000U
+#endif
+
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_LOG = SCMP_ACT_LOG;
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
+// The libseccomp SCMP_FLTATR_CTL_LOG member of the scmp_filter_attr enum was
+// added in v2.4.0
+#if (SCMP_VER_MAJOR < 2) || \
+ (SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 4)
+#define SCMP_FLTATR_CTL_LOG _SCMP_FLTATR_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 uint32_t C_ATTRIBUTE_LOG = (uint32_t)SCMP_FLTATR_CTL_LOG;
const int C_CMP_NE = (int)SCMP_CMP_NE;
const int C_CMP_LT = (int)SCMP_CMP_LT;
@@ -124,25 +104,80 @@ const int C_VERSION_MAJOR = SCMP_VER_MAJOR;
const int C_VERSION_MINOR = SCMP_VER_MINOR;
const int C_VERSION_MICRO = SCMP_VER_MICRO;
+#if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR >= 3
+unsigned int get_major_version()
+{
+ return seccomp_version()->major;
+}
+
+unsigned int get_minor_version()
+{
+ return seccomp_version()->minor;
+}
+
+unsigned int get_micro_version()
+{
+ return seccomp_version()->micro;
+}
+#else
+unsigned int get_major_version()
+{
+ return (unsigned int)C_VERSION_MAJOR;
+}
+
+unsigned int get_minor_version()
+{
+ return (unsigned int)C_VERSION_MINOR;
+}
+
+unsigned int get_micro_version()
+{
+ return (unsigned int)C_VERSION_MICRO;
+}
+#endif
+
+// The libseccomp API level functions were added in v2.4.0
+#if (SCMP_VER_MAJOR < 2) || \
+ (SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 4)
+const unsigned int seccomp_api_get(void)
+{
+ // libseccomp-golang requires libseccomp v2.2.0, at a minimum, which
+ // supported API level 2. However, the kernel may not support API level
+ // 2 constructs which are the seccomp() system call and the TSYNC
+ // filter flag. Return the "reserved" value of 0 here to indicate that
+ // proper API level support is not available in libseccomp.
+ return 0;
+}
+
+int seccomp_api_set(unsigned int level)
+{
+ return -EOPNOTSUPP;
+}
+#endif
+
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
- )
+void* make_arg_cmp_array(unsigned int length)
{
- struct scmp_arg_cmp *s = malloc(sizeof(struct scmp_arg_cmp));
+ return calloc(length, sizeof(struct scmp_arg_cmp));
+}
- s->arg = arg;
- s->op = compare;
- s->datum_a = a;
- s->datum_b = b;
+// Wrapper to add an scmp_arg_cmp struct to an existing arg_cmp array
+void add_struct_arg_cmp(
+ struct scmp_arg_cmp* arr,
+ unsigned int pos,
+ unsigned int arg,
+ int compare,
+ uint64_t a,
+ uint64_t b
+ )
+{
+ arr[pos].arg = arg;
+ arr[pos].op = compare;
+ arr[pos].datum_a = a;
+ arr[pos].datum_b = b;
- return s;
+ return;
}
*/
import "C"
@@ -157,6 +192,7 @@ const (
filterAttrActBadArch scmpFilterAttr = iota
filterAttrNNP scmpFilterAttr = iota
filterAttrTsync scmpFilterAttr = iota
+ filterAttrLog scmpFilterAttr = iota
)
const (
@@ -167,7 +203,7 @@ const (
archEnd ScmpArch = ArchS390X
// Comparison boundaries to check for action validity
actionStart ScmpAction = ActKill
- actionEnd ScmpAction = ActAllow
+ actionEnd ScmpAction = ActLog
// Comparison boundaries to check for comparison operator validity
compareOpStart ScmpCompareOp = CompareNotEqual
compareOpEnd ScmpCompareOp = CompareMaskedEqual
@@ -177,28 +213,51 @@ 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)
+ verMajor = uint(C.get_major_version())
+ verMinor = uint(C.get_minor_version())
+ verMicro = uint(C.get_micro_version())
)
// Nonexported functions
// Check if library version is greater than or equal to the given one
-func checkVersionAbove(major, minor, micro int) bool {
+func checkVersionAbove(major, minor, micro uint) 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.
+// Ensure that the library is supported, i.e. >= 2.2.0.
func ensureSupportedVersion() error {
- if !checkVersionAbove(2, 1, 0) {
+ if !checkVersionAbove(2, 2, 0) {
return VersionError{}
}
return nil
}
+// Get the API level
+func getApi() (uint, error) {
+ api := C.seccomp_api_get()
+ if api == 0 {
+ return 0, fmt.Errorf("API level operations are not supported")
+ }
+
+ return uint(api), nil
+}
+
+// Set the API level
+func setApi(api uint) error {
+ if retCode := C.seccomp_api_set(C.uint(api)); retCode != 0 {
+ if syscall.Errno(-1*retCode) == syscall.EOPNOTSUPP {
+ return fmt.Errorf("API level operations are not supported")
+ }
+
+ return fmt.Errorf("could not set API level: %v", retCode)
+ }
+
+ return nil
+}
+
// Filter helpers
// Filter finalizer - ensure that kernel context for filters is freed
@@ -215,13 +274,6 @@ func (f *ScmpFilter) getFilterAttr(attr scmpFilterAttr) (C.uint32_t, error) {
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)
@@ -241,13 +293,6 @@ func (f *ScmpFilter) setFilterAttr(attr scmpFilterAttr, value C.uint32_t) error
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)
@@ -259,12 +304,9 @@ func (f *ScmpFilter) setFilterAttr(attr scmpFilterAttr, value C.uint32_t) error
// 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
+func (f *ScmpFilter) addRuleWrapper(call ScmpSyscall, action ScmpAction, exact bool, length C.uint, cond C.scmp_cast_t) error {
+ if length != 0 && cond == nil {
+ return fmt.Errorf("null conditions list, but length is nonzero")
}
var retCode C.int
@@ -275,9 +317,11 @@ func (f *ScmpFilter) addRuleWrapper(call ScmpSyscall, action ScmpAction, exact b
}
if syscall.Errno(-1*retCode) == syscall.EFAULT {
- return fmt.Errorf("unrecognized syscall")
+ return fmt.Errorf("unrecognized syscall %#x", int32(call))
} else if syscall.Errno(-1*retCode) == syscall.EPERM {
return fmt.Errorf("requested action matches default action of filter")
+ } else if syscall.Errno(-1*retCode) == syscall.EINVAL {
+ return fmt.Errorf("two checks on same syscall argument")
} else if retCode != 0 {
return syscall.Errno(-1 * retCode)
}
@@ -295,7 +339,7 @@ func (f *ScmpFilter) addRuleGeneric(call ScmpSyscall, action ScmpAction, exact b
}
if len(conds) == 0 {
- if err := f.addRuleWrapper(call, action, exact, nil); err != nil {
+ if err := f.addRuleWrapper(call, action, exact, 0, nil); err != nil {
return err
}
} else {
@@ -307,13 +351,20 @@ func (f *ScmpFilter) addRuleGeneric(call ScmpSyscall, action ScmpAction, exact b
}
}
- 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)
+ argsArr := C.make_arg_cmp_array(C.uint(len(conds)))
+ if argsArr == nil {
+ return fmt.Errorf("error allocating memory for conditions")
+ }
+ defer C.free(argsArr)
+
+ for i, cond := range conds {
+ C.add_struct_arg_cmp(C.scmp_cast_t(argsArr), C.uint(i),
+ C.uint(cond.Argument), cond.Op.toNative(),
+ C.uint64_t(cond.Operand1), C.uint64_t(cond.Operand2))
+ }
- if err := f.addRuleWrapper(call, action, exact, C.scmp_cast_t(cmpStruct)); err != nil {
- return err
- }
+ if err := f.addRuleWrapper(call, action, exact, C.uint(len(conds)), C.scmp_cast_t(argsArr)); err != nil {
+ return err
}
}
@@ -325,11 +376,11 @@ func (f *ScmpFilter) addRuleGeneric(call ScmpSyscall, action ScmpAction, exact b
// Helper - Sanitize Arch token input
func sanitizeArch(in ScmpArch) error {
if in < archStart || in > archEnd {
- return fmt.Errorf("unrecognized architecture")
+ return fmt.Errorf("unrecognized architecture %#x", uint(in))
}
if in.toNative() == C.C_ARCH_BAD {
- return fmt.Errorf("architecture is not supported on this version of the library")
+ return fmt.Errorf("architecture %v is not supported on this version of the library", in)
}
return nil
@@ -338,7 +389,7 @@ func sanitizeArch(in ScmpArch) error {
func sanitizeAction(in ScmpAction) error {
inTmp := in & 0x0000FFFF
if inTmp < actionStart || inTmp > actionEnd {
- return fmt.Errorf("unrecognized action")
+ return fmt.Errorf("unrecognized action %#x", uint(inTmp))
}
if inTmp != ActTrace && inTmp != ActErrno && (in&0xFFFF0000) != 0 {
@@ -350,7 +401,7 @@ func sanitizeAction(in ScmpAction) error {
func sanitizeCompareOp(in ScmpCompareOp) error {
if in < compareOpStart || in > compareOpEnd {
- return fmt.Errorf("unrecognized comparison operator")
+ return fmt.Errorf("unrecognized comparison operator %#x", uint(in))
}
return nil
@@ -393,7 +444,7 @@ func archFromNative(a C.uint32_t) (ScmpArch, error) {
case C.C_ARCH_S390X:
return ArchS390X, nil
default:
- return 0x0, fmt.Errorf("unrecognized architecture")
+ return 0x0, fmt.Errorf("unrecognized architecture %#x", uint32(a))
}
}
@@ -472,10 +523,12 @@ func actionFromNative(a C.uint32_t) (ScmpAction, error) {
return ActErrno.SetReturnCode(int16(aTmp)), nil
case C.C_ACT_TRACE:
return ActTrace.SetReturnCode(int16(aTmp)), nil
+ case C.C_ACT_LOG:
+ return ActLog, nil
case C.C_ACT_ALLOW:
return ActAllow, nil
default:
- return 0x0, fmt.Errorf("unrecognized action")
+ return 0x0, fmt.Errorf("unrecognized action %#x", uint32(a))
}
}
@@ -490,6 +543,8 @@ func (a ScmpAction) toNative() C.uint32_t {
return C.C_ACT_ERRNO | (C.uint32_t(a) >> 16)
case ActTrace:
return C.C_ACT_TRACE | (C.uint32_t(a) >> 16)
+ case ActLog:
+ return C.C_ACT_LOG
case ActAllow:
return C.C_ACT_ALLOW
default:
@@ -508,6 +563,8 @@ func (a scmpFilterAttr) toNative() uint32 {
return uint32(C.C_ATTRIBUTE_NNP)
case filterAttrTsync:
return uint32(C.C_ATTRIBUTE_TSYNC)
+ case filterAttrLog:
+ return uint32(C.C_ATTRIBUTE_LOG)
default:
return 0x0
}