diff --git a/vendor.conf b/vendor.conf index 4149c557..b0bfb1ef 100644 --- a/vendor.conf +++ b/vendor.conf @@ -6,7 +6,7 @@ github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4 github.com/checkpoint-restore/go-criu v3.11 github.com/mrunalp/fileutils ed869b029674c0e9ce4c0dfa781405c2d9946d08 github.com/opencontainers/selinux v1.2.2 -github.com/seccomp/libseccomp-golang 84e90a91acea0f4e51e62bc1a75de18b1fc0790f +github.com/seccomp/libseccomp-golang v0.9.1 github.com/sirupsen/logrus 8bdbc7bcc01dcbb8ec23dc8a28e332258d25251f github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16 github.com/vishvananda/netlink 1e2e08e8a2dcdacaae3f14ac44c5cfa31361f270 diff --git a/vendor/github.com/seccomp/libseccomp-golang/seccomp.go b/vendor/github.com/seccomp/libseccomp-golang/seccomp.go index d3d9e6bf..a3cc5382 100644 --- a/vendor/github.com/seccomp/libseccomp-golang/seccomp.go +++ b/vendor/github.com/seccomp/libseccomp-golang/seccomp.go @@ -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)) } } @@ -328,6 +334,25 @@ 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") } @@ -730,6 +755,30 @@ func (f *ScmpFilter) GetNoNewPrivsBit() (bool, error) { return true, nil } +// 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 log == 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. @@ -756,6 +805,28 @@ func (f *ScmpFilter) SetNoNewPrivsBit(state bool) error { return f.setFilterAttr(filterAttrNNP, toSet) } +// 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 state { + toSet = 0x1 + } + + 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. // This provides a hint to the filter generator in libseccomp about the // importance of this syscall. High-priority syscalls are placed diff --git a/vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go b/vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go index 5b6a79ad..4e36b27a 100644 --- a/vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go +++ b/vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go @@ -16,6 +16,7 @@ import ( // #cgo pkg-config: libseccomp /* +#include #include #include @@ -67,16 +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; +// 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; @@ -122,6 +136,25 @@ unsigned int get_micro_version() } #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; void* make_arg_cmp_array(unsigned int length) @@ -159,6 +192,7 @@ const ( filterAttrActBadArch scmpFilterAttr = iota filterAttrNNP scmpFilterAttr = iota filterAttrTsync scmpFilterAttr = iota + filterAttrLog scmpFilterAttr = iota ) const ( @@ -169,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 @@ -201,6 +235,29 @@ func ensureSupportedVersion() error { 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 @@ -260,7 +317,7 @@ 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 { @@ -319,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 @@ -332,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 { @@ -344,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 @@ -387,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)) } } @@ -466,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)) } } @@ -484,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: @@ -502,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 } diff --git a/vendor/github.com/sirupsen/logrus/go.mod b/vendor/github.com/sirupsen/logrus/go.mod new file mode 100644 index 00000000..8261a2b3 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/go.mod @@ -0,0 +1,10 @@ +module github.com/sirupsen/logrus + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/konsorten/go-windows-terminal-sequences v1.0.1 + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/objx v0.1.1 // indirect + github.com/stretchr/testify v1.2.2 + golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 +)