Merge pull request #5436 from opencontainers/dependabot/go_modules/github.com/seccomp/libseccomp-golang-0.12.0

build(deps): bump github.com/seccomp/libseccomp-golang from 0.11.1 to 0.12.0
This commit is contained in:
Akihiro Suda authored and GitHub committed 2026-09-01 17:40:09 +09:00
commit 982e5f5938
9 files changed
+540 -251

No files matched your search

+1 -1
View File
@@ -19,7 +19,7 @@ require (
github.com/opencontainers/cgroups v0.1.0
github.com/opencontainers/runtime-spec v1.3.0
github.com/opencontainers/selinux v1.15.1
github.com/seccomp/libseccomp-golang v0.11.1
github.com/seccomp/libseccomp-golang v0.12.0
github.com/sirupsen/logrus v1.10.2
github.com/urfave/cli/v3 v3.11.0
github.com/vishvananda/netlink v1.3.1
+2 -2
View File
@@ -44,8 +44,8 @@ github.com/opencontainers/selinux v1.15.1 h1:ERxeh5caJvCzNAKdI8WQbJmB1LDTn4BuaAg
github.com/opencontainers/selinux v1.15.1/go.mod h1:LenyElirjUHszfxrjuFqC85HIeXZKumHcKMQtnaDlQQ=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/seccomp/libseccomp-golang v0.11.1 h1:wuk4ZjSx6kyQII4rj6G6fvVzRHQaSiPvccJazDagu4g=
github.com/seccomp/libseccomp-golang v0.11.1/go.mod h1:5m1Lk8E9OwgZTTVz4bBOer7JuazaBa+xTkM895tDiWc=
github.com/seccomp/libseccomp-golang v0.12.0 h1:IYaotOCgdBokfN0ry0COtn2Q6Co+tYd/rnrUx0NalZQ=
github.com/seccomp/libseccomp-golang v0.12.0/go.mod h1:5m1Lk8E9OwgZTTVz4bBOer7JuazaBa+xTkM895tDiWc=
github.com/sirupsen/logrus v1.10.2 h1:G2SED73/qrAu6YwbdxOD6peLkCBI3z7L+ykJFTXJBBo=
github.com/sirupsen/logrus v1.10.2/go.mod h1:SLEg8TqYulVKKfIGHldVp2K2aYz2DKSVBq4g/H5bR7Q=
github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE=
@@ -673,7 +673,7 @@ func filterFlags(config *configs.Seccomp, filter *libseccomp.ScmpFilter) (flags
}
}
if apiLevel >= 7 {
if waitKill, err := filter.GetWaitKill(); err != nil && !errors.Is(err, unix.EINVAL) {
if waitKill, err := filter.GetWaitKill(); err != nil {
return 0, false, fmt.Errorf("unable to fetch SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV bit: %w", err)
} else if waitKill {
flags |= uint(C.C_FILTER_FLAG_WAIT_KILLABLE_RECV)
+76 -21
View File
@@ -1,22 +1,8 @@
# libseccomp-golang
.PHONY: all
all: check
.PHONY: all check check-build check-syntax fix-syntax vet test lint
all: check-build
check: lint test
check-build:
go build
check-syntax:
gofmt -d .
fix-syntax:
gofmt -w .
vet:
go vet -v ./...
.PHONY: check
check: lint build test check-symbols
# Previous bugs have made the tests freeze until the timeout. Golang default
# timeout for tests is 10 minutes, which is too long, considering current tests
@@ -24,8 +10,77 @@ vet:
# be noticed earlier in the CI.
TEST_TIMEOUT=10s
test:
go test -v -timeout $(TEST_TIMEOUT)
.PHONY: test
test: test-build test-run
.PHONY: test-build
test-build:
go test -c
.PHONY: test-run
test-run:
./libseccomp-golang.test -test.v -test.timeout $(TEST_TIMEOUT)
# All libseccomp functions available in v2.3.1, the minimum version supported
# by this package. Since these are always present, they are the only ones that
# may be referenced strongly; anything added later has to be referenced weakly
# and called via a compat_* wrapper, so that a binary compiled against a newer
# libseccomp can still be loaded and used with an older run-time library. See
# seccomp_compat.h for details.
LIBSECCOMP_V231_SYMBOLS = \
seccomp_arch_add \
seccomp_arch_exist \
seccomp_arch_native \
seccomp_arch_remove \
seccomp_attr_get \
seccomp_attr_set \
seccomp_export_bpf \
seccomp_export_pfc \
seccomp_init \
seccomp_load \
seccomp_merge \
seccomp_release \
seccomp_reset \
seccomp_rule_add_array \
seccomp_rule_add_exact_array \
seccomp_syscall_priority \
seccomp_syscall_resolve_name \
seccomp_syscall_resolve_name_arch \
seccomp_syscall_resolve_num_arch \
seccomp_version
.PHONY: check-symbols
check-symbols: test-build
@# A strong reference to a symbol the run-time library does not have makes
@# the binary fail to load, so anything post-v2.3.1 has to stay weak.
@command -v nm >/dev/null 2>&1 || { echo "nm not found; skipping symbol check"; exit 0; }
@strong=$$(nm -D --undefined-only ./libseccomp-golang.test \
| awk '$$1 == "U" && $$2 ~ /^seccomp_/ { print $$2 }' \
| grep -vx $(patsubst %,-e %,$(LIBSECCOMP_V231_SYMBOLS)) || true); \
if [ -n "$$strong" ]; then \
echo "Error: strong references to libseccomp symbols added after v2.3.1:"; \
echo "$$strong" | sed 's/^/ /'; \
echo "Declare them weak and call them via a compat_* wrapper (see seccomp_compat.h)."; \
exit 1; \
fi
@# A weak reference stays weak no matter who calls it, so the check above
@# can not see a direct call from Go, which would crash on NULL rather
@# than fail to load. Only seccomp_compat.c may call these directly, and
@# only after checking for NULL.
@direct=$$(grep -n -o 'C\.seccomp_[a-z0-9_]*' *.go \
| sed 's/C\.//' \
| grep -v $(patsubst %,-e ':%$$',$(LIBSECCOMP_V231_SYMBOLS)) || true); \
if [ -n "$$direct" ]; then \
echo "Error: direct calls to libseccomp symbols added after v2.3.1:"; \
echo "$$direct" | sed 's/^/ /'; \
echo "Call them via a compat_* wrapper instead (see seccomp_compat.h)."; \
exit 1; \
fi
.PHONY: lint
lint:
golangci-lint run .
golangci-lint run
.PHONY: build
build:
go build
+37 -31
View File
@@ -18,26 +18,7 @@ import (
)
/*
#include <errno.h>
#include <stdlib.h>
#include <seccomp.h>
// The following functions were added in libseccomp v2.6.0.
#if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 6
int seccomp_precompute(scmp_filter_ctx ctx) {
return -EOPNOTSUPP;
}
int seccomp_export_bpf_mem(const scmp_filter_ctx ctx, void *buf, size_t *len) {
return -EOPNOTSUPP;
}
int seccomp_transaction_start(const scmp_filter_ctx ctx) {
return -EOPNOTSUPP;
}
int seccomp_transaction_commit(const scmp_filter_ctx ctx) {
return -EOPNOTSUPP;
}
void seccomp_transaction_reject(const scmp_filter_ctx ctx) {}
#endif
#include "seccomp_compat.h"
*/
import "C"
@@ -45,6 +26,10 @@ import "C"
// VersionError represents an error when either the system libseccomp version
// or the kernel version is too old to perform the operation requested.
//
// The libseccomp version it reports is the effective one, that is the lower of
// the compile-time and the run-time versions (see [GetLibraryVersion]), since
// an operation needs to be available in both.
type VersionError struct {
op string // operation that failed or would fail
major, minor, micro uint // minimally required libseccomp version
@@ -62,11 +47,11 @@ func init() {
func (e VersionError) Error() string {
if e.minAPI != 0 {
return fmt.Sprintf("%s requires libseccomp >= %d.%d.%d and API level >= %d "+
"(current version: %d.%d.%d, API level: %d)",
"(effective version: %d.%d.%d, API level: %d)",
e.op, e.major, e.minor, e.micro, e.minAPI,
verMajor, verMinor, verMicro, e.curAPI)
}
return fmt.Sprintf("%s requires libseccomp >= %d.%d.%d (current version: %d.%d.%d)",
return fmt.Sprintf("%s requires libseccomp >= %d.%d.%d (effective version: %d.%d.%d)",
e.op, e.major, e.minor, e.micro, verMajor, verMinor, verMicro)
}
@@ -469,14 +454,15 @@ func (a ScmpAction) GetReturnCode() int16 {
// General utility functions
// GetLibraryVersion returns the version of the library the bindings are built
// against.
// GetLibraryVersion returns the version of the libseccomp library used,
// which is the lower of the compile-time and run-time versions.
// The version is formatted as follows: Major.Minor.Micro
func GetLibraryVersion() (major, minor, micro uint) {
return verMajor, verMinor, verMicro
}
// GetAPI returns the API level supported by the system.
// GetAPI returns the API level supported by the system, which is the lower of
// the compile-time and run-time supported levels.
// 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:
@@ -851,7 +837,11 @@ func (f *ScmpFilter) Precompute() error {
return errBadFilter
}
if retCode := C.seccomp_precompute(f.filterCtx); retCode != 0 {
if e := checkVersion("Precompute", 2, 6, 0); e != nil {
return e
}
if retCode := C.compat_precompute(f.filterCtx); retCode != 0 {
return errRc(retCode)
}
@@ -1262,14 +1252,18 @@ func (f *ScmpFilter) ExportBPFMem() ([]byte, error) {
return nil, errBadFilter
}
if e := checkVersion("ExportBPFMem", 2, 6, 0); e != nil {
return nil, e
}
var len C.size_t
// Get the size required.
if retCode := C.seccomp_export_bpf_mem(f.filterCtx, unsafe.Pointer(nil), &len); retCode < 0 {
if retCode := C.compat_export_bpf_mem(f.filterCtx, unsafe.Pointer(nil), &len); retCode < 0 {
return nil, errRc(retCode)
}
// Get the data.
buf := make([]byte, int(len))
if retCode := C.seccomp_export_bpf_mem(f.filterCtx, unsafe.Pointer(&buf[0]), &len); retCode < 0 {
if retCode := C.compat_export_bpf_mem(f.filterCtx, unsafe.Pointer(&buf[0]), &len); retCode < 0 {
return nil, errRc(retCode)
}
@@ -1324,7 +1318,11 @@ func (f *ScmpFilter) TransactionStart() error {
return errBadFilter
}
if retCode := C.seccomp_transaction_start(f.filterCtx); retCode < 0 {
if e := checkVersion("TransactionStart", 2, 6, 0); e != nil {
return e
}
if retCode := C.compat_transaction_start(f.filterCtx); retCode < 0 {
return errRc(retCode)
}
@@ -1340,7 +1338,11 @@ func (f *ScmpFilter) TransactionReject() {
return
}
C.seccomp_transaction_reject(f.filterCtx)
if checkVersion("TransactionReject", 2, 6, 0) != nil {
return
}
C.compat_transaction_reject(f.filterCtx)
}
// TransactionCommit commits a transaction started by [TransactionStart].
@@ -1352,7 +1354,11 @@ func (f *ScmpFilter) TransactionCommit() error {
return errBadFilter
}
if retCode := C.seccomp_transaction_commit(f.filterCtx); retCode < 0 {
if e := checkVersion("TransactionCommit", 2, 6, 0); e != nil {
return e
}
if retCode := C.compat_transaction_commit(f.filterCtx); retCode < 0 {
return errRc(retCode)
}
+121
View File
@@ -0,0 +1,121 @@
// Wrappers around libseccomp functionality that may be missing from the
// run-time libseccomp library. The functions wrapped here are declared as weak
// references (see seccomp_compat.h), meaning they resolve to NULL when the
// run-time library is older than the version that added them, so they must not
// be called directly.
#include "seccomp_compat.h"
// The API level operations were added in libseccomp v2.4.0.
unsigned int compat_api_get(void)
{
// Return the "reserved" value of 0 to tell the caller that proper API
// level support is not available in libseccomp.
if (seccomp_api_get == NULL)
return 0;
return seccomp_api_get();
}
int compat_api_set(unsigned int level)
{
if (seccomp_api_set == NULL)
return -EOPNOTSUPP;
return seccomp_api_set(level);
}
// The seccomp notify API was added in libseccomp v2.5.0.
int compat_notify_alloc(struct seccomp_notif **req, struct seccomp_notif_resp **resp)
{
if (seccomp_notify_alloc == NULL)
return -EOPNOTSUPP;
return seccomp_notify_alloc(req, resp);
}
int compat_notify_fd(const scmp_filter_ctx ctx)
{
if (seccomp_notify_fd == NULL)
return -EOPNOTSUPP;
return seccomp_notify_fd(ctx);
}
void compat_notify_free(struct seccomp_notif *req, struct seccomp_notif_resp *resp)
{
if (seccomp_notify_free == NULL)
return;
seccomp_notify_free(req, resp);
}
int compat_notify_id_valid(int fd, uint64_t id)
{
if (seccomp_notify_id_valid == NULL)
return -EOPNOTSUPP;
return seccomp_notify_id_valid(fd, id);
}
int compat_notify_receive(int fd, struct seccomp_notif *req)
{
if (seccomp_notify_receive == NULL)
return -EOPNOTSUPP;
return seccomp_notify_receive(fd, req);
}
int compat_notify_respond(int fd, struct seccomp_notif_resp *resp)
{
if (seccomp_notify_respond == NULL)
return -EOPNOTSUPP;
return seccomp_notify_respond(fd, resp);
}
// The following functions were added in libseccomp v2.6.0.
int compat_precompute(scmp_filter_ctx ctx)
{
if (seccomp_precompute == NULL)
return -EOPNOTSUPP;
return seccomp_precompute(ctx);
}
int compat_export_bpf_mem(const scmp_filter_ctx ctx, void *buf, size_t *len)
{
if (seccomp_export_bpf_mem == NULL)
return -EOPNOTSUPP;
return seccomp_export_bpf_mem(ctx, buf, len);
}
int compat_transaction_start(const scmp_filter_ctx ctx)
{
if (seccomp_transaction_start == NULL)
return -EOPNOTSUPP;
return seccomp_transaction_start(ctx);
}
int compat_transaction_commit(const scmp_filter_ctx ctx)
{
if (seccomp_transaction_commit == NULL)
return -EOPNOTSUPP;
return seccomp_transaction_commit(ctx);
}
void compat_transaction_reject(const scmp_filter_ctx ctx)
{
if (seccomp_transaction_reject == NULL)
return;
seccomp_transaction_reject(ctx);
}
+231
View File
@@ -0,0 +1,231 @@
#ifndef SECCOMP_COMPAT_H
#define SECCOMP_COMPAT_H
#include <errno.h>
#include <stdlib.h>
#include <seccomp.h>
// Minimally required version during compile time.
#if (SCMP_VER_MAJOR < 2) || \
(SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 3) || \
(SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR == 3 && SCMP_VER_MICRO < 1)
#error This package requires libseccomp >= v2.3.1
#endif
// Macros that are missing from older libseccomp headers. Being macros, they
// only need an #ifndef guard, so no version tracking is needed for them.
#define ARCH_BAD ~0
#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
#ifndef SCMP_ARCH_PARISC
#define SCMP_ARCH_PARISC ARCH_BAD
#endif
#ifndef SCMP_ARCH_PARISC64
#define SCMP_ARCH_PARISC64 ARCH_BAD
#endif
#ifndef SCMP_ARCH_RISCV64
#define SCMP_ARCH_RISCV64 ARCH_BAD
#endif
#ifndef SCMP_ARCH_LOONGARCH64
#define SCMP_ARCH_LOONGARCH64 ARCH_BAD
#endif
#ifndef SCMP_ARCH_M68K
#define SCMP_ARCH_M68K ARCH_BAD
#endif
#ifndef SCMP_ARCH_SH
#define SCMP_ARCH_SH ARCH_BAD
#endif
#ifndef SCMP_ARCH_SHEB
#define SCMP_ARCH_SHEB ARCH_BAD
#endif
#ifndef SCMP_ACT_LOG
#define SCMP_ACT_LOG 0x7ffc0000U
#endif
#ifndef SCMP_ACT_KILL_PROCESS
#define SCMP_ACT_KILL_PROCESS 0x80000000U
#endif
#ifndef SCMP_ACT_KILL_THREAD
#define SCMP_ACT_KILL_THREAD 0x00000000U
#endif
#ifndef SCMP_ACT_NOTIFY
#define SCMP_ACT_NOTIFY 0x7fc00000U
#endif
// Definitions that are only available in newer libseccomp headers. Unlike
// functions (see below), these can not be resolved at run time, so they have
// to be provided here when compiling against older headers.
//
// The SCMP_FLTATR_* ones are enum members rather than macros, so, unlike the
// above, the preprocessor can not tell whether they are already defined, and
// an explicit version check is needed instead.
#if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 4
// SCMP_FLTATR_CTL_LOG was added in v2.4.0.
#define SCMP_FLTATR_CTL_LOG 6
#endif // < 2.4.0
#if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 5
// The following SCMP_FLTATR_* were added in libseccomp v2.5.0.
#define SCMP_FLTATR_CTL_SSB 7
#define SCMP_FLTATR_CTL_OPTIMIZE 8
#define SCMP_FLTATR_API_SYSRAWRC 9
// The seccomp notify API structs were added in v2.5.0. Their layout is
// dictated by the kernel UAPI, so it is safe to define them here.
struct seccomp_data {
int nr;
__u32 arch;
__u64 instruction_pointer;
__u64 args[6];
};
struct seccomp_notif {
__u64 id;
__u32 pid;
__u32 flags;
struct seccomp_data data;
};
struct seccomp_notif_resp {
__u64 id;
__s64 val;
__s32 error;
__u32 flags;
};
#endif // < 2.5.0
#if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 6
#define SCMP_FLTATR_CTL_WAITKILL 10
#endif // < 2.6.0
// Functions that were added after v2.3.1 are declared as weak references, so
// that a binary compiled against a newer libseccomp can still be loaded and
// used with an older run-time libseccomp. Without this, the dynamic linker
// fails to resolve the newer symbols, and the program does not even start.
//
// A weak reference to a symbol that is missing at run time resolves to NULL
// rather than being an error, so every such function must only be called via
// its compat_* wrapper below, which checks for availability first.
//
// Declaring these unconditionally serves a second purpose: when compiling
// against headers older than the version that added a function, the weak
// declaration is the only declaration, replacing the dummy implementations
// that used to be needed to make the package compile.
#define SCMP_WEAK __attribute__((weak))
// Forward declarations, so that the notify prototypes below do not depend on
// which of seccomp.h, linux/seccomp.h, or the compat block above ends up
// defining these structs. Only pointers to them are used here.
struct seccomp_notif;
struct seccomp_notif_resp;
// Added in v2.4.0.
SCMP_WEAK unsigned int seccomp_api_get(void);
SCMP_WEAK int seccomp_api_set(unsigned int level);
// Added in v2.5.0.
SCMP_WEAK int seccomp_notify_alloc(struct seccomp_notif **req, struct seccomp_notif_resp **resp);
SCMP_WEAK int seccomp_notify_fd(const scmp_filter_ctx ctx);
SCMP_WEAK void seccomp_notify_free(struct seccomp_notif *req, struct seccomp_notif_resp *resp);
SCMP_WEAK int seccomp_notify_id_valid(int fd, uint64_t id);
SCMP_WEAK int seccomp_notify_receive(int fd, struct seccomp_notif *req);
SCMP_WEAK int seccomp_notify_respond(int fd, struct seccomp_notif_resp *resp);
// Added in v2.6.0.
SCMP_WEAK int seccomp_precompute(scmp_filter_ctx ctx);
SCMP_WEAK int seccomp_export_bpf_mem(const scmp_filter_ctx ctx, void *buf, size_t *len);
SCMP_WEAK int seccomp_transaction_start(const scmp_filter_ctx ctx);
SCMP_WEAK int seccomp_transaction_commit(const scmp_filter_ctx ctx);
SCMP_WEAK void seccomp_transaction_reject(const scmp_filter_ctx ctx);
// Wrappers around the weakly referenced functions above; implemented in
// seccomp_compat.c. These are what the Go code calls. Normally, a missing
// function is already ruled out by the version and API level checks done in
// Go, and these wrappers are merely a safety net making sure a NULL pointer
// is never called.
unsigned int compat_api_get(void);
int compat_api_set(unsigned int level);
int compat_notify_alloc(struct seccomp_notif **req, struct seccomp_notif_resp **resp);
int compat_notify_fd(const scmp_filter_ctx ctx);
void compat_notify_free(struct seccomp_notif *req, struct seccomp_notif_resp *resp);
int compat_notify_id_valid(int fd, uint64_t id);
int compat_notify_receive(int fd, struct seccomp_notif *req);
int compat_notify_respond(int fd, struct seccomp_notif_resp *resp);
int compat_precompute(scmp_filter_ctx ctx);
int compat_export_bpf_mem(const scmp_filter_ctx ctx, void *buf, size_t *len);
int compat_transaction_start(const scmp_filter_ctx ctx);
int compat_transaction_commit(const scmp_filter_ctx ctx);
void compat_transaction_reject(const scmp_filter_ctx ctx);
// The highest API level that can possibly be supported by the compile-time
// libseccomp headers, regardless of what the run-time library reports. This
// mirrors the version gates in the Go code, which use the lower of the
// compile-time and the run-time version: functionality added after the
// compile-time version can never be used, even if a newer library is loaded
// at run time.
//
// The API level to version mapping is documented in the seccomp_api_get(3)
// man page.
#if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 4
#define SCMP_COMPAT_MAX_API_LEVEL 2
#elif SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR == 4
#define SCMP_COMPAT_MAX_API_LEVEL 3
#elif SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR == 5
#define SCMP_COMPAT_MAX_API_LEVEL 6
#else
// TODO: bump this (and add a branch above) whenever a new libseccomp
// version introduces a new API level. Until then, a newer libseccomp is
// capped to the highest level known here, which is the safe direction to
// err in, but does mean its new functionality stays unavailable.
#define SCMP_COMPAT_MAX_API_LEVEL 7
#endif
#endif // SECCOMP_COMPAT_H
+70 -194
View File
@@ -22,68 +22,10 @@ import (
// #cgo pkg-config: libseccomp
/*
#include <errno.h>
#include <stdlib.h>
#include <seccomp.h>
#if (SCMP_VER_MAJOR < 2) || \
(SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 3) || \
(SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR == 3 && SCMP_VER_MICRO < 1)
#error This package requires libseccomp >= v2.3.1
#endif
#define ARCH_BAD ~0
#include "seccomp_compat.h"
const uint32_t C_ARCH_BAD = ARCH_BAD;
#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
#ifndef SCMP_ARCH_PARISC
#define SCMP_ARCH_PARISC ARCH_BAD
#endif
#ifndef SCMP_ARCH_PARISC64
#define SCMP_ARCH_PARISC64 ARCH_BAD
#endif
#ifndef SCMP_ARCH_RISCV64
#define SCMP_ARCH_RISCV64 ARCH_BAD
#endif
#ifndef SCMP_ARCH_LOONGARCH64
#define SCMP_ARCH_LOONGARCH64 ARCH_BAD
#endif
#ifndef SCMP_ARCH_M68K
#define SCMP_ARCH_M68K ARCH_BAD
#endif
#ifndef SCMP_ARCH_SH
#define SCMP_ARCH_SH ARCH_BAD
#endif
#ifndef SCMP_ARCH_SHEB
#define SCMP_ARCH_SHEB 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;
@@ -109,22 +51,6 @@ const uint32_t C_ARCH_M68K = SCMP_ARCH_M68K;
const uint32_t C_ARCH_SH = SCMP_ARCH_SH;
const uint32_t C_ARCH_SHEB = SCMP_ARCH_SHEB;
#ifndef SCMP_ACT_LOG
#define SCMP_ACT_LOG 0x7ffc0000U
#endif
#ifndef SCMP_ACT_KILL_PROCESS
#define SCMP_ACT_KILL_PROCESS 0x80000000U
#endif
#ifndef SCMP_ACT_KILL_THREAD
#define SCMP_ACT_KILL_THREAD 0x00000000U
#endif
#ifndef SCMP_ACT_NOTIFY
#define SCMP_ACT_NOTIFY 0x7fc00000U
#endif
const uint32_t C_ACT_KILL = SCMP_ACT_KILL;
const uint32_t C_ACT_KILL_PROCESS = SCMP_ACT_KILL_PROCESS;
const uint32_t C_ACT_KILL_THREAD = SCMP_ACT_KILL_THREAD;
@@ -135,24 +61,6 @@ const uint32_t C_ACT_LOG = SCMP_ACT_LOG;
const uint32_t C_ACT_ALLOW = SCMP_ACT_ALLOW;
const uint32_t C_ACT_NOTIFY = SCMP_ACT_NOTIFY;
// 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_MINOR < 4
#define SCMP_FLTATR_CTL_LOG _SCMP_FLTATR_MIN
#endif
// The following SCMP_FLTATR_* were added in libseccomp v2.5.0.
#if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 5
#define SCMP_FLTATR_CTL_SSB _SCMP_FLTATR_MIN
#define SCMP_FLTATR_CTL_OPTIMIZE _SCMP_FLTATR_MIN
#define SCMP_FLTATR_API_SYSRAWRC _SCMP_FLTATR_MIN
#endif
// Added in libseccomp v2.6.0.
#if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 6
#define SCMP_FLTATR_CTL_WAITKILL _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;
@@ -171,39 +79,6 @@ 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;
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;
}
// The libseccomp API level functions were added in v2.4.0
#if 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)
@@ -229,49 +104,6 @@ void add_struct_arg_cmp(
return;
}
// The seccomp notify API functions were added in v2.5.0
#if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 5
struct seccomp_data {
int nr;
__u32 arch;
__u64 instruction_pointer;
__u64 args[6];
};
struct seccomp_notif {
__u64 id;
__u32 pid;
__u32 flags;
struct seccomp_data data;
};
struct seccomp_notif_resp {
__u64 id;
__s64 val;
__s32 error;
__u32 flags;
};
int seccomp_notify_alloc(struct seccomp_notif **req, struct seccomp_notif_resp **resp) {
return -EOPNOTSUPP;
}
int seccomp_notify_fd(const scmp_filter_ctx ctx) {
return -EOPNOTSUPP;
}
void seccomp_notify_free(struct seccomp_notif *req, struct seccomp_notif_resp *resp) {
}
int seccomp_notify_id_valid(int fd, uint64_t id) {
return -EOPNOTSUPP;
}
int seccomp_notify_receive(int fd, struct seccomp_notif *req) {
return -EOPNOTSUPP;
}
int seccomp_notify_respond(int fd, struct seccomp_notif_resp *resp) {
return -EOPNOTSUPP;
}
#endif
*/
import "C"
@@ -310,24 +142,45 @@ var (
// errBadFilter is thrown on bad filter context.
errBadFilter = errors.New("filter is invalid or uninitialized")
errDefAction = errors.New("requested action matches default action of filter")
// Constants representing library major, minor, and micro versions
verMajor = uint(C.get_major_version())
verMinor = uint(C.get_minor_version())
verMicro = uint(C.get_micro_version())
// errAPIUnsupported is returned when the libseccomp used lacks the API
// level operations, added in v2.4.0.
errAPIUnsupported = errors.New("API level operations are not supported")
// libseccomp major, minor, and micro version numbers. Used by checkVersion.
verMajor, verMinor, verMicro = getMinVersion()
)
// versionGE reports whether (major1,minor1,micro1) >= (major2,minor2,micro2).
func versionGE(major1, minor1, micro1, major2, minor2, micro2 uint) bool {
return (major1 > major2) ||
(major1 == major2 && minor1 > minor2) ||
(major1 == major2 && minor1 == minor2 && micro1 >= micro2)
}
func getMinVersion() (uint, uint, uint) {
runVer := C.seccomp_version()
cMajor, cMinor, cMicro := uint(C.SCMP_VER_MAJOR), uint(C.SCMP_VER_MINOR), uint(C.SCMP_VER_MICRO)
rMajor, rMinor, rMicro := uint(runVer.major), uint(runVer.minor), uint(runVer.micro)
if versionGE(rMajor, rMinor, rMicro, cMajor, cMinor, cMicro) {
return cMajor, cMinor, cMicro
}
return rMajor, rMinor, rMicro
}
// Nonexported functions
// checkVersion returns an error if the libseccomp version being used
// is less than the one specified by major, minor, and micro arguments.
// checkVersion returns an error if the libseccomp version is less than the one
// specified by major, minor, and micro arguments.
//
// Since this package may be compiled with one version of libseccomp and
// used with another, we use the older one to be on the safe side.
//
// Argument op is an arbitrary non-empty operation description, which
// is used as a part of the error message returned.
//
// Most users should use checkAPI instead.
func checkVersion(op string, major, minor, micro uint) error {
if (verMajor > major) ||
(verMajor == major && verMinor > minor) ||
(verMajor == major && verMinor == minor && verMicro >= micro) {
if versionGE(verMajor, verMinor, verMicro, major, minor, micro) {
return nil
}
return &VersionError{
@@ -342,22 +195,44 @@ func ensureSupportedVersion() error {
return checkVersion("seccomp", 2, 3, 1)
}
// Get the API level
// Get the API level, capped to the compile-time supported maximum (see
// getMinVersion for why this cap is needed).
func getAPI() (uint, error) {
api := C.seccomp_api_get()
if api == 0 {
return 0, errors.New("API level operations are not supported")
// The API level operations were added in libseccomp v2.4.0 and, like
// any other functionality, have to be available at both compile and
// run time. This is the one place that can not use checkAPI, the API
// level being the very thing the latter checks.
//
// Note that while the minimally required libseccomp v2.3.1 does support
// API level 2, the kernel may not support the API level 2 constructs
// (the seccomp() system call and the TSYNC filter flag), so no API
// level is assumed here.
if checkVersion("API level operations", 2, 4, 0) != nil {
return 0, errAPIUnsupported
}
return uint(api), nil
api := uint(C.compat_api_get())
if api == 0 {
return 0, errAPIUnsupported
}
if maxAPI := uint(C.SCMP_COMPAT_MAX_API_LEVEL); api > maxAPI {
api = maxAPI
}
return api, nil
}
// Set the API level
func setAPI(api uint) error {
if retCode := C.seccomp_api_set(C.uint(api)); retCode != 0 {
// See the comment in getAPI.
if checkVersion("API level operations", 2, 4, 0) != nil {
return errAPIUnsupported
}
if retCode := C.compat_api_set(C.uint(api)); retCode != 0 {
e := errRc(retCode)
if e == syscall.EOPNOTSUPP {
return errors.New("API level operations are not supported")
return errAPIUnsupported
}
return fmt.Errorf("could not set API level: %w", e)
@@ -784,7 +659,8 @@ func checkAPI(op string, minLevel uint, major, minor, micro uint) error {
}
// Userspace Notification API
// Calls to C.seccomp_notify* hidden from seccomp.go
// Calls to C.compat_notify* (thin wrappers around the libseccomp
// seccomp_notify* functions) hidden from seccomp.go
func notifSupported() error {
return checkAPI("seccomp notification", 6, 2, 5, 0)
@@ -801,7 +677,7 @@ func (f *ScmpFilter) getNotifFd() (ScmpFd, error) {
return -1, err
}
fd := C.seccomp_notify_fd(f.filterCtx)
fd := C.compat_notify_fd(f.filterCtx)
return ScmpFd(fd), nil
}
@@ -815,13 +691,13 @@ func notifReceive(fd ScmpFd) (*ScmpNotifReq, error) {
}
// we only use the request here; the response is unused
if retCode := C.seccomp_notify_alloc(&req, &resp); retCode != 0 {
if retCode := C.compat_notify_alloc(&req, &resp); retCode != 0 {
return nil, errRc(retCode)
}
defer C.seccomp_notify_free(req, resp)
defer C.compat_notify_free(req, resp)
for {
retCode, errno := C.seccomp_notify_receive(C.int(fd), req)
retCode, errno := C.compat_notify_receive(C.int(fd), req)
if retCode == 0 {
break
}
@@ -849,15 +725,15 @@ func notifRespond(fd ScmpFd, scmpResp *ScmpNotifResp) error {
}
// we only use the response here; the request is discarded
if retCode := C.seccomp_notify_alloc(&req, &resp); retCode != 0 {
if retCode := C.compat_notify_alloc(&req, &resp); retCode != 0 {
return errRc(retCode)
}
defer C.seccomp_notify_free(req, resp)
defer C.compat_notify_free(req, resp)
scmpResp.toNative(resp)
for {
retCode, errno := C.seccomp_notify_respond(C.int(fd), resp)
retCode, errno := C.compat_notify_respond(C.int(fd), resp)
if retCode == 0 {
break
}
@@ -882,7 +758,7 @@ func notifIDValid(fd ScmpFd, id uint64) error {
}
for {
retCode, errno := C.seccomp_notify_id_valid(C.int(fd), C.uint64_t(id))
retCode, errno := C.compat_notify_id_valid(C.int(fd), C.uint64_t(id))
if retCode == 0 {
break
}
+1 -1
View File
@@ -84,7 +84,7 @@ github.com/opencontainers/runtime-spec/specs-go/features
github.com/opencontainers/selinux/go-selinux
github.com/opencontainers/selinux/go-selinux/label
github.com/opencontainers/selinux/pkg/pwalkdir
# github.com/seccomp/libseccomp-golang v0.11.1
# github.com/seccomp/libseccomp-golang v0.12.0
## explicit; go 1.19
github.com/seccomp/libseccomp-golang
# github.com/sirupsen/logrus v1.10.2