deps: update runc to 1.1.0

This updates vendored runc/libcontainer to 1.1.0,
and google/cadvisor to a version updated to runc 1.1.0
(google/cadvisor#3048).

Changes in vendor are generated by (roughly):

        ./hack/pin-dependency.sh github.com/google/cadvisor v0.44.0
        ./hack/pin-dependency.sh github.com/opencontainers/runc v1.1.0
        ./hack/update-vendor.sh
        ./hack/lint-dependencies.sh # And follow all its recommendations.
        ./hack/update-vendor.sh
        ./hack/update-internal-modules.sh
        ./hack/lint-dependencies.sh # Re-check everything again.

Co-Authored-By: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
Elana Hashman
2022-03-28 11:32:04 -07:00
parent 41830a1f79
commit 07af1bab70
245 changed files with 6520 additions and 5250 deletions

View File

@@ -0,0 +1,57 @@
# Travis CI configuration for libseccomp-golang
# https://docs.travis-ci.com/user/reference/bionic
# https://wiki.ubuntu.com/Releases
dist: bionic
sudo: false
notifications:
email:
on_success: always
on_failure: always
arch:
- amd64
os:
- linux
language: go
jobs:
include:
- name: "last libseccomp 2.5.0"
env:
- SECCOMP_VER=2.5.0
- SECCOMP_SHA256SUM=1ffa7038d2720ad191919816db3479295a4bcca1ec14e02f672539f4983014f3
- name: "compat libseccomp 2.4.4"
env:
- SECCOMP_VER=2.4.4
- SECCOMP_SHA256SUM=4e79738d1ef3c9b7ca9769f1f8b8d84fc17143c2c1c432e53b9c64787e0ff3eb
- name: "compat libseccomp 2.2.1"
env:
- SECCOMP_VER=2.2.1
- SECCOMP_SHA256SUM=0ba1789f54786c644af54cdffc9fd0dd0a8bb2b2ee153933f658855d2851a740
addons:
apt:
packages:
- build-essential
- astyle
- golint
- gperf
install:
- go get -u golang.org/x/lint/golint
# run all of the tests independently, fail if any of the tests error
script:
- wget https://github.com/seccomp/libseccomp/releases/download/v$SECCOMP_VER/libseccomp-$SECCOMP_VER.tar.gz
- echo $SECCOMP_SHA256SUM libseccomp-$SECCOMP_VER.tar.gz | sha256sum -c
- tar xf libseccomp-$SECCOMP_VER.tar.gz
- pushd libseccomp-$SECCOMP_VER && ./configure --prefix=/opt/libseccomp-$SECCOMP_VER && make && sudo make install && popd
- make check-syntax
- make lint
- PKG_CONFIG_PATH=/opt/libseccomp-$SECCOMP_VER/lib/pkgconfig LD_LIBRARY_PATH=/opt/libseccomp-$SECCOMP_VER/lib make vet
- PKG_CONFIG_PATH=/opt/libseccomp-$SECCOMP_VER/lib/pkgconfig LD_LIBRARY_PATH=/opt/libseccomp-$SECCOMP_VER/lib make test

View File

@@ -8,11 +8,11 @@ to the rules described here, but by following the instructions below you
should have a much easier time getting your work merged with the upstream
project.
* Test Your Code
## Test Your Code Using Existing Tests
There are two possible tests you can run to verify your code. The first test
is used to check the formatting and coding style of your changes, you can run
the test with the following command:
There are two possible tests you can run to verify your code. The first
test is used to check the formatting and coding style of your changes, you
can run the test with the following command:
# make check-syntax
@@ -27,30 +27,13 @@ with the following command:
... if there are any faults or errors they will be displayed.
* Generate the Patch(es)
## Add New Tests for New Functionality
Depending on how you decided to work with the libseccomp code base and what
tools you are using there are different ways to generate your patch(es).
However, regardless of what tools you use, you should always generate your
patches using the "unified" diff/patch format and the patches should always
apply to the libseccomp source tree using the following command from the top
directory of the libseccomp sources:
Any submissions which add functionality, or significantly change the existing
code, should include additional tests to verify the proper operation of the
proposed changes.
# patch -p1 < changes.patch
If you are not using git, stacked git (stgit), or some other tool which can
generate patch files for you automatically, you may find the following command
helpful in generating patches, where "libseccomp.orig/" is the unmodified
source code directory and "libseccomp/" is the source code directory with your
changes:
# diff -purN libseccomp-golang.orig/ libseccomp-golang/
When in doubt please generate your patch and try applying it to an unmodified
copy of the libseccomp sources; if it fails for you, it will fail for the rest
of us.
* Explain Your Work
## Explain Your Work
At the top of every patch you should include a description of the problem you
are trying to solve, how you solved it, and why you chose the solution you
@@ -59,7 +42,7 @@ if you can describe/include a reproducer for the problem in the description as
well as instructions on how to test for the bug and verify that it has been
fixed.
* Sign Your Work
## Sign Your Work
The sign-off is a simple line at the end of the patch description, which
certifies that you wrote it or otherwise have the right to pass it on as an
@@ -97,16 +80,49 @@ your real name, saying:
Signed-off-by: Random J Developer <random@developer.example.org>
* Email Your Patch(es)
You can add this to your commit description in `git` with `git commit -s`
## Post Your Patches Upstream
The libseccomp project accepts both GitHub pull requests and patches sent via
the mailing list. GitHub pull requests are preferred. This sections below
explain how to contribute via either method. Please read each step and perform
all steps that apply to your chosen contribution method.
### Submitting via Email
Depending on how you decided to work with the libseccomp code base and what
tools you are using there are different ways to generate your patch(es).
However, regardless of what tools you use, you should always generate your
patches using the "unified" diff/patch format and the patches should always
apply to the libseccomp source tree using the following command from the top
directory of the libseccomp sources:
# patch -p1 < changes.patch
If you are not using git, stacked git (stgit), or some other tool which can
generate patch files for you automatically, you may find the following command
helpful in generating patches, where "libseccomp.orig/" is the unmodified
source code directory and "libseccomp/" is the source code directory with your
changes:
# diff -purN libseccomp.orig/ libseccomp/
When in doubt please generate your patch and try applying it to an unmodified
copy of the libseccomp sources; if it fails for you, it will fail for the rest
of us.
Finally, you will need to email your patches to the mailing list so they can
be reviewed and potentially merged into the main libseccomp-golang repository.
When sending patches to the mailing list it is important to send your email in
text form, no HTML mail please, and ensure that your email client does not
mangle your patches. It should be possible to save your raw email to disk and
apply it directly to the libseccomp source code; if that fails then you likely
have a problem with your email client. When in doubt try a test first by
sending yourself an email with your patch and attempting to apply the emailed
patch to the libseccomp-golang repository; if it fails for you, it will fail
for the rest of us trying to test your patch and include it in the main
libseccomp-golang repository.
be reviewed and potentially merged into the main libseccomp repository. When
sending patches to the mailing list it is important to send your email in text
form, no HTML mail please, and ensure that your email client does not mangle
your patches. It should be possible to save your raw email to disk and apply
it directly to the libseccomp source code; if that fails then you likely have
a problem with your email client. When in doubt try a test first by sending
yourself an email with your patch and attempting to apply the emailed patch to
the libseccomp repository; if it fails for you, it will fail for the rest of
us trying to test your patch and include it in the main libseccomp repository.
### Submitting via GitHub
See [this guide](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request) if you've never done this before.

View File

@@ -18,8 +18,14 @@ fix-syntax:
vet:
go vet -v
# 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
# can be executed in less than 1 second. Reduce the timeout, so problems can
# be noticed earlier in the CI.
TEST_TIMEOUT=10s
test:
go test -v
go test -v -timeout $(TEST_TIMEOUT)
lint:
@$(if $(shell which golint),true,$(error "install golint and include it in your PATH"))

View File

@@ -1,7 +1,8 @@
libseccomp-golang: Go Language Bindings for the libseccomp Project
![libseccomp Golang Bindings](https://github.com/seccomp/libseccomp-artwork/blob/main/logo/libseccomp-color_text.png)
===============================================================================
https://github.com/seccomp/libseccomp-golang
https://github.com/seccomp/libseccomp
[![Build Status](https://img.shields.io/travis/seccomp/libseccomp-golang/main.svg)](https://travis-ci.org/seccomp/libseccomp-golang)
The libseccomp library provides an easy to use, platform independent, interface
to the Linux Kernel's syscall filtering mechanism. The libseccomp API is
@@ -12,40 +13,39 @@ be familiar to, and easily adopted by, application developers.
The libseccomp-golang library provides a Go based interface to the libseccomp
library.
* Online Resources
## 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
* 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
* https://groups.google.com/d/forum/libseccomp
Documentation is also available at:
-> https://godoc.org/github.com/seccomp/libseccomp-golang
* https://godoc.org/github.com/seccomp/libseccomp-golang
* Installing the package
## 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
# go get github.com/seccomp/libseccomp-golang
* Testing the Library
## 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
# 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
* https://github.com/golang/lint

3
vendor/github.com/seccomp/libseccomp-golang/go.mod generated vendored Normal file
View File

@@ -0,0 +1,3 @@
module github.com/seccomp/libseccomp-golang
go 1.14

23
vendor/github.com/seccomp/libseccomp-golang/go.sum generated vendored Normal file
View File

@@ -0,0 +1,23 @@
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7 h1:EBZoQjiKKPaLbPrbpssUfuHtwM6KV/vb4U85g/cigFY=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200313205530-4303120df7d8 h1:gkI/wGGwpcG5W4hLCzZNGxA4wzWBGGDStRI1MrjDl2Q=
golang.org/x/tools v0.0.0-20200313205530-4303120df7d8/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -20,6 +20,13 @@ import (
// C wrapping code
// To compile libseccomp-golang against a specific version of libseccomp:
// cd ../libseccomp && mkdir -p prefix
// ./configure --prefix=$PWD/prefix && make && make install
// cd ../libseccomp-golang
// PKG_CONFIG_PATH=$PWD/../libseccomp/prefix/lib/pkgconfig/ make
// LD_PRELOAD=$PWD/../libseccomp/prefix/lib/libseccomp.so.2.5.0 PKG_CONFIG_PATH=$PWD/../libseccomp/prefix/lib/pkgconfig/ make test
// #cgo pkg-config: libseccomp
// #include <stdlib.h>
// #include <seccomp.h>
@@ -34,19 +41,25 @@ type VersionError struct {
minimum string
}
func init() {
// This forces the cgo libseccomp to initialize its internal API support state,
// which is necessary on older versions of libseccomp in order to work
// correctly.
GetAPI()
}
func (e VersionError) Error() string {
format := "Libseccomp version too low: "
messageStr := ""
if e.message != "" {
format += e.message + ": "
messageStr = e.message + ": "
}
format += "minimum supported is "
minimumStr := ""
if e.minimum != "" {
format += e.minimum + ": "
minimumStr = e.minimum
} else {
format += "2.2.0: "
minimumStr = "2.2.0"
}
format += "detected %d.%d.%d"
return fmt.Sprintf(format, verMajor, verMinor, verMicro)
return fmt.Sprintf("Libseccomp version too low: %sminimum supported is %s: detected %d.%d.%d", messageStr, minimumStr, verMajor, verMinor, verMicro)
}
// ScmpArch represents a CPU architecture. Seccomp can restrict syscalls on a
@@ -69,9 +82,61 @@ type ScmpCondition struct {
Operand2 uint64 `json:"operand_two,omitempty"`
}
// ScmpSyscall represents a Linux System Call
// Seccomp userspace notification structures associated with filters that use the ActNotify action.
// ScmpSyscall identifies a Linux System Call by its number.
type ScmpSyscall int32
// ScmpFd represents a file-descriptor used for seccomp userspace notifications.
type ScmpFd int32
// ScmpNotifData describes the system call context that triggered a notification.
//
// Syscall: the syscall number
// Arch: the filter architecture
// InstrPointer: address of the instruction that triggered a notification
// Args: arguments (up to 6) for the syscall
//
type ScmpNotifData struct {
Syscall ScmpSyscall `json:"syscall,omitempty"`
Arch ScmpArch `json:"arch,omitempty"`
InstrPointer uint64 `json:"instr_pointer,omitempty"`
Args []uint64 `json:"args,omitempty"`
}
// ScmpNotifReq represents a seccomp userspace notification. See NotifReceive() for
// info on how to pull such a notification.
//
// ID: notification ID
// Pid: process that triggered the notification event
// Flags: filter flags (see seccomp(2))
// Data: system call context that triggered the notification
//
type ScmpNotifReq struct {
ID uint64 `json:"id,omitempty"`
Pid uint32 `json:"pid,omitempty"`
Flags uint32 `json:"flags,omitempty"`
Data ScmpNotifData `json:"data,omitempty"`
}
// ScmpNotifResp represents a seccomp userspace notification response. See NotifRespond()
// for info on how to push such a response.
//
// ID: notification ID (must match the corresponding ScmpNotifReq ID)
// Error: must be 0 if no error occurred, or an error constant from package
// syscall (e.g., syscall.EPERM, etc). In the latter case, it's used
// as an error return from the syscall that created the notification.
// Val: return value for the syscall that created the notification. Only
// relevant if Error is 0.
// Flags: userspace notification response flag (e.g., NotifRespFlagContinue)
//
type ScmpNotifResp struct {
ID uint64 `json:"id,omitempty"`
Error int32 `json:"error,omitempty"`
Val uint64 `json:"val,omitempty"`
Flags uint32 `json:"flags,omitempty"`
}
// Exported Constants
const (
@@ -117,6 +182,10 @@ const (
ArchS390 ScmpArch = iota
// ArchS390X represents 64-bit System z/390 syscalls
ArchS390X ScmpArch = iota
// ArchPARISC represents 32-bit PA-RISC
ArchPARISC ScmpArch = iota
// ArchPARISC64 represents 64-bit PA-RISC
ArchPARISC64 ScmpArch = iota
)
const (
@@ -125,10 +194,14 @@ const (
// ActInvalid is a placeholder to ensure uninitialized ScmpAction
// variables are invalid
ActInvalid ScmpAction = iota
// ActKill kills the process
// ActKill kills the thread that violated the rule. It is the same as ActKillThread.
// All other threads from the same thread group will continue to execute.
ActKill ScmpAction = iota
// ActTrap throws SIGSYS
ActTrap ScmpAction = iota
// ActNotify triggers a userspace notification. This action is only usable when
// libseccomp API level 6 or higher is supported.
ActNotify ScmpAction = iota
// ActErrno causes the syscall to return a negative error code. This
// code can be set with the SetReturnCode method
ActErrno ScmpAction = iota
@@ -141,6 +214,14 @@ const (
// This action is only usable when libseccomp API level 3 or higher is
// supported.
ActLog ScmpAction = iota
// ActKillThread kills the thread that violated the rule. It is the same as ActKill.
// All other threads from the same thread group will continue to execute.
ActKillThread ScmpAction = iota
// ActKillProcess kills the process that violated the rule.
// All threads in the thread group are also terminated.
// This action is only usable when libseccomp API level 3 or higher is
// supported.
ActKillProcess ScmpAction = iota
)
const (
@@ -172,6 +253,21 @@ const (
CompareMaskedEqual ScmpCompareOp = iota
)
var (
// ErrSyscallDoesNotExist represents an error condition where
// libseccomp is unable to resolve the syscall
ErrSyscallDoesNotExist = fmt.Errorf("could not resolve syscall name")
)
const (
// Userspace notification response flags
// NotifRespFlagContinue tells the kernel to continue executing the system
// call that triggered the notification. Must only be used when the notication
// response's error is 0.
NotifRespFlagContinue uint32 = 1
)
// Helpers for types
// GetArchFromString returns an ScmpArch constant from a string representing an
@@ -214,6 +310,10 @@ func GetArchFromString(arch string) (ScmpArch, error) {
return ArchS390, nil
case "s390x":
return ArchS390X, nil
case "parisc":
return ArchPARISC, nil
case "parisc64":
return ArchPARISC64, nil
default:
return ArchInvalid, fmt.Errorf("cannot convert unrecognized string %q", arch)
}
@@ -254,6 +354,10 @@ func (a ScmpArch) String() string {
return "s390"
case ArchS390X:
return "s390x"
case ArchPARISC:
return "parisc"
case ArchPARISC64:
return "parisc64"
case ArchNative:
return "native"
case ArchInvalid:
@@ -290,8 +394,10 @@ func (a ScmpCompareOp) String() string {
// 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 ActKill, ActKillThread:
return "Action: Kill thread"
case ActKillProcess:
return "Action: Kill process"
case ActTrap:
return "Action: Send SIGSYS"
case ActErrno:
@@ -299,6 +405,8 @@ func (a ScmpAction) String() string {
case ActTrace:
return fmt.Sprintf("Action: Notify tracing processes with code %d",
(a >> 16))
case ActNotify:
return "Action: Notify userspace"
case ActLog:
return "Action: Log system call"
case ActAllow:
@@ -334,23 +442,23 @@ 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.
// 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()
// https://github.com/seccomp/libseccomp/blob/main/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
// 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)
// https://github.com/seccomp/libseccomp/blob/main/doc/man/man3/seccomp_api_get.3
func SetAPI(api uint) error {
return setAPI(api)
}
// Syscall functions
@@ -375,7 +483,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 for %#x", int32(s))
return "", ErrSyscallDoesNotExist
}
defer C.free(unsafe.Pointer(cString))
@@ -398,7 +506,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: %q", name)
return 0, ErrSyscallDoesNotExist
}
return ScmpSyscall(result), nil
@@ -422,7 +530,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: %q on %v", name, arch)
return 0, ErrSyscallDoesNotExist
}
return ScmpSyscall(result), nil
@@ -495,11 +603,10 @@ type ScmpFilter struct {
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.
// 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
@@ -519,8 +626,8 @@ 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
// 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)
@@ -552,9 +659,8 @@ func (f *ScmpFilter) Reset(defaultAction ScmpAction) error {
return errBadFilter
}
retCode := C.seccomp_reset(f.filterCtx, defaultAction.toNative())
if retCode != 0 {
return syscall.Errno(-1 * retCode)
if retCode := C.seccomp_reset(f.filterCtx, defaultAction.toNative()); retCode != 0 {
return errRc(retCode)
}
return nil
@@ -600,11 +706,12 @@ func (f *ScmpFilter) Merge(src *ScmpFilter) error {
}
// 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)
if retCode := C.seccomp_merge(f.filterCtx, src.filterCtx); retCode != 0 {
e := errRc(retCode)
if e == syscall.EINVAL {
return fmt.Errorf("filters could not be merged due to a mismatch in attributes or invalid filter")
}
return e
}
src.valid = false
@@ -633,12 +740,13 @@ func (f *ScmpFilter) IsArchPresent(arch ScmpArch) (bool, error) {
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)
if retCode := C.seccomp_arch_exist(f.filterCtx, arch.toNative()); retCode != 0 {
e := errRc(retCode)
if e == syscall.EEXIST {
// -EEXIST is "arch not present"
return false, nil
}
return false, e
}
return true, nil
@@ -661,9 +769,10 @@ func (f *ScmpFilter) AddArch(arch ScmpArch) error {
// 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)
if retCode := C.seccomp_arch_add(f.filterCtx, arch.toNative()); retCode != 0 {
if e := errRc(retCode); e != syscall.EEXIST {
return e
}
}
return nil
@@ -686,9 +795,10 @@ func (f *ScmpFilter) RemoveArch(arch ScmpArch) error {
// 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)
if retCode := C.seccomp_arch_remove(f.filterCtx, arch.toNative()); retCode != 0 {
if e := errRc(retCode); e != syscall.EEXIST {
return e
}
}
return nil
@@ -705,7 +815,7 @@ func (f *ScmpFilter) Load() error {
}
if retCode := C.seccomp_load(f.filterCtx); retCode != 0 {
return syscall.Errno(-1 * retCode)
return errRc(retCode)
}
return nil
@@ -764,8 +874,9 @@ func (f *ScmpFilter) GetNoNewPrivsBit() (bool, error) {
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) {
// Ignore error, if not supported returns apiLevel == 0
apiLevel, _ := GetAPI()
if apiLevel < 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")
}
@@ -779,6 +890,30 @@ func (f *ScmpFilter) GetLogBit() (bool, error) {
return true, nil
}
// GetSSB returns the current state the SSB bit will be set to on the filter
// being loaded, or an error if an issue was encountered retrieving the value.
// The SSB bit tells the kernel that a seccomp user is not interested in enabling
// Speculative Store Bypass mitigation.
// The SSB bit is only usable when libseccomp API level 4 or higher is
// supported.
func (f *ScmpFilter) GetSSB() (bool, error) {
ssb, err := f.getFilterAttr(filterAttrSSB)
if err != nil {
api, apiErr := getAPI()
if (apiErr != nil && api == 0) || (apiErr == nil && api < 4) {
return false, fmt.Errorf("getting the SSB flag is only supported in libseccomp 2.5.0 and newer with API level 4 or higher")
}
return false, err
}
if ssb == 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.
@@ -818,8 +953,9 @@ func (f *ScmpFilter) SetLogBit(state bool) error {
err := f.setFilterAttr(filterAttrLog, toSet)
if err != nil {
api, apiErr := getApi()
if (apiErr != nil && api == 0) || (apiErr == nil && api < 3) {
// Ignore error, if not supported returns apiLevel == 0
apiLevel, _ := GetAPI()
if apiLevel < 3 {
return fmt.Errorf("setting the log bit is only supported in libseccomp 2.4.0 and newer with API level 3 or higher")
}
}
@@ -827,6 +963,28 @@ func (f *ScmpFilter) SetLogBit(state bool) error {
return err
}
// SetSSB sets the state of the SSB bit, which will be applied on filter
// load, or an error if an issue was encountered setting the value.
// The SSB bit is only usable when libseccomp API level 4 or higher is
// supported.
func (f *ScmpFilter) SetSSB(state bool) error {
var toSet C.uint32_t = 0x0
if state {
toSet = 0x1
}
err := f.setFilterAttr(filterAttrSSB, toSet)
if err != nil {
api, apiErr := getAPI()
if (apiErr != nil && api == 0) || (apiErr == nil && api < 4) {
return fmt.Errorf("setting the SSB flag is only supported in libseccomp 2.5.0 and newer with API level 4 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
@@ -842,7 +1000,7 @@ func (f *ScmpFilter) SetSyscallPriority(call ScmpSyscall, priority uint8) error
if retCode := C.seccomp_syscall_priority(f.filterCtx, C.int(call),
C.uint8_t(priority)); retCode != 0 {
return syscall.Errno(-1 * retCode)
return errRc(retCode)
}
return nil
@@ -907,7 +1065,7 @@ func (f *ScmpFilter) ExportPFC(file *os.File) error {
}
if retCode := C.seccomp_export_pfc(f.filterCtx, C.int(fd)); retCode != 0 {
return syscall.Errno(-1 * retCode)
return errRc(retCode)
}
return nil
@@ -928,8 +1086,41 @@ func (f *ScmpFilter) ExportBPF(file *os.File) error {
}
if retCode := C.seccomp_export_bpf(f.filterCtx, C.int(fd)); retCode != 0 {
return syscall.Errno(-1 * retCode)
return errRc(retCode)
}
return nil
}
// Userspace Notification API
// GetNotifFd returns the userspace notification file descriptor associated with the given
// filter context. Such a file descriptor is only valid after the filter has been loaded
// and only when the filter uses the ActNotify action. The file descriptor can be used to
// retrieve and respond to notifications associated with the filter (see NotifReceive(),
// NotifRespond(), and NotifIDValid()).
func (f *ScmpFilter) GetNotifFd() (ScmpFd, error) {
return f.getNotifFd()
}
// NotifReceive retrieves a seccomp userspace notification from a filter whose ActNotify
// action has triggered. The caller is expected to process the notification and return a
// response via NotifRespond(). Each invocation of this function returns one
// notification. As multiple notifications may be pending at any time, this function is
// normally called within a polling loop.
func NotifReceive(fd ScmpFd) (*ScmpNotifReq, error) {
return notifReceive(fd)
}
// NotifRespond responds to a notification retrieved via NotifReceive(). The response Id
// must match that of the corresponding notification retrieved via NotifReceive().
func NotifRespond(fd ScmpFd, scmpResp *ScmpNotifResp) error {
return notifRespond(fd, scmpResp)
}
// NotifIDValid checks if a notification is still valid. An return value of nil means the
// notification is still valid. Otherwise the notification is not valid. This can be used
// to mitigate time-of-check-time-of-use (TOCTOU) attacks as described in seccomp_notify_id_valid(2).
func NotifIDValid(fd ScmpFd, id uint64) error {
return notifIDValid(fd, id)
}

View File

@@ -14,6 +14,13 @@ import (
// Get the seccomp header in scope
// Need stdlib.h for free() on cstrings
// To compile libseccomp-golang against a specific version of libseccomp:
// cd ../libseccomp && mkdir -p prefix
// ./configure --prefix=$PWD/prefix && make && make install
// cd ../libseccomp-golang
// PKG_CONFIG_PATH=$PWD/../libseccomp/prefix/lib/pkgconfig/ make
// LD_PRELOAD=$PWD/../libseccomp/prefix/lib/libseccomp.so.2.5.0 PKG_CONFIG_PATH=$PWD/../libseccomp/prefix/lib/pkgconfig/ make test
// #cgo pkg-config: libseccomp
/*
#include <errno.h>
@@ -50,6 +57,14 @@ const uint32_t C_ARCH_BAD = ARCH_BAD;
#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
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;
@@ -67,17 +82,34 @@ 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_ARCH_PARISC = SCMP_ARCH_PARISC;
const uint32_t C_ARCH_PARISC64 = SCMP_ARCH_PARISC64;
#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;
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;
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
@@ -85,12 +117,16 @@ const uint32_t C_ACT_ALLOW = SCMP_ACT_ALLOW;
(SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 4)
#define SCMP_FLTATR_CTL_LOG _SCMP_FLTATR_MIN
#endif
#if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 5
#define SCMP_FLTATR_CTL_SSB _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 uint32_t C_ATTRIBUTE_SSB = (uint32_t)SCMP_FLTATR_CTL_SSB;
const int C_CMP_NE = (int)SCMP_CMP_NE;
const int C_CMP_LT = (int)SCMP_CMP_LT;
@@ -179,6 +215,51 @@ void add_struct_arg_cmp(
return;
}
// The seccomp notify API functions were added in v2.5.0
#if (SCMP_VER_MAJOR < 2) || \
(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"
@@ -193,6 +274,7 @@ const (
filterAttrNNP scmpFilterAttr = iota
filterAttrTsync scmpFilterAttr = iota
filterAttrLog scmpFilterAttr = iota
filterAttrSSB scmpFilterAttr = iota
)
const (
@@ -200,10 +282,10 @@ const (
scmpError C.int = -1
// Comparison boundaries to check for architecture validity
archStart ScmpArch = ArchNative
archEnd ScmpArch = ArchS390X
archEnd ScmpArch = ArchPARISC64
// Comparison boundaries to check for action validity
actionStart ScmpAction = ActKill
actionEnd ScmpAction = ActLog
actionEnd ScmpAction = ActKillProcess
// Comparison boundaries to check for comparison operator validity
compareOpStart ScmpCompareOp = CompareNotEqual
compareOpEnd ScmpCompareOp = CompareMaskedEqual
@@ -236,7 +318,7 @@ func ensureSupportedVersion() error {
}
// Get the API level
func getApi() (uint, error) {
func getAPI() (uint, error) {
api := C.seccomp_api_get()
if api == 0 {
return 0, fmt.Errorf("API level operations are not supported")
@@ -246,9 +328,9 @@ func getApi() (uint, error) {
}
// Set the API level
func setApi(api uint) error {
func setAPI(api uint) error {
if retCode := C.seccomp_api_set(C.uint(api)); retCode != 0 {
if syscall.Errno(-1*retCode) == syscall.EOPNOTSUPP {
if errRc(retCode) == syscall.EOPNOTSUPP {
return fmt.Errorf("API level operations are not supported")
}
@@ -265,6 +347,10 @@ func filterFinalizer(f *ScmpFilter) {
f.Release()
}
func errRc(rc C.int) error {
return syscall.Errno(-1 * rc)
}
// Get a raw filter attribute
func (f *ScmpFilter) getFilterAttr(attr scmpFilterAttr) (C.uint32_t, error) {
f.lock.Lock()
@@ -278,7 +364,7 @@ func (f *ScmpFilter) getFilterAttr(attr scmpFilterAttr) (C.uint32_t, error) {
retCode := C.seccomp_attr_get(f.filterCtx, attr.toNative(), &attribute)
if retCode != 0 {
return 0x0, syscall.Errno(-1 * retCode)
return 0x0, errRc(retCode)
}
return attribute, nil
@@ -295,7 +381,7 @@ func (f *ScmpFilter) setFilterAttr(attr scmpFilterAttr, value C.uint32_t) error
retCode := C.seccomp_attr_set(f.filterCtx, attr.toNative(), value)
if retCode != 0 {
return syscall.Errno(-1 * retCode)
return errRc(retCode)
}
return nil
@@ -316,14 +402,17 @@ func (f *ScmpFilter) addRuleWrapper(call ScmpSyscall, action ScmpAction, exact b
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 %#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)
if retCode != 0 {
switch e := errRc(retCode); e {
case syscall.EFAULT:
return fmt.Errorf("unrecognized syscall %#x", int32(call))
case syscall.EPERM:
return fmt.Errorf("requested action matches default action of filter")
case syscall.EINVAL:
return fmt.Errorf("two checks on same syscall argument")
default:
return e
}
}
return nil
@@ -443,6 +532,10 @@ func archFromNative(a C.uint32_t) (ScmpArch, error) {
return ArchS390, nil
case C.C_ARCH_S390X:
return ArchS390X, nil
case C.C_ARCH_PARISC:
return ArchPARISC, nil
case C.C_ARCH_PARISC64:
return ArchPARISC64, nil
default:
return 0x0, fmt.Errorf("unrecognized architecture %#x", uint32(a))
}
@@ -483,6 +576,10 @@ func (a ScmpArch) toNative() C.uint32_t {
return C.C_ARCH_S390
case ArchS390X:
return C.C_ARCH_S390X
case ArchPARISC:
return C.C_ARCH_PARISC
case ArchPARISC64:
return C.C_ARCH_PARISC64
case ArchNative:
return C.C_ARCH_NATIVE
default:
@@ -517,6 +614,10 @@ func actionFromNative(a C.uint32_t) (ScmpAction, error) {
switch a & 0xFFFF0000 {
case C.C_ACT_KILL:
return ActKill, nil
case C.C_ACT_KILL_PROCESS:
return ActKillProcess, nil
case C.C_ACT_KILL_THREAD:
return ActKillThread, nil
case C.C_ACT_TRAP:
return ActTrap, nil
case C.C_ACT_ERRNO:
@@ -527,6 +628,8 @@ func actionFromNative(a C.uint32_t) (ScmpAction, error) {
return ActLog, nil
case C.C_ACT_ALLOW:
return ActAllow, nil
case C.C_ACT_NOTIFY:
return ActNotify, nil
default:
return 0x0, fmt.Errorf("unrecognized action %#x", uint32(a))
}
@@ -537,6 +640,10 @@ func (a ScmpAction) toNative() C.uint32_t {
switch a & 0xFFFF {
case ActKill:
return C.C_ACT_KILL
case ActKillProcess:
return C.C_ACT_KILL_PROCESS
case ActKillThread:
return C.C_ACT_KILL_THREAD
case ActTrap:
return C.C_ACT_TRAP
case ActErrno:
@@ -547,6 +654,8 @@ func (a ScmpAction) toNative() C.uint32_t {
return C.C_ACT_LOG
case ActAllow:
return C.C_ACT_ALLOW
case ActNotify:
return C.C_ACT_NOTIFY
default:
return 0x0
}
@@ -565,7 +674,181 @@ func (a scmpFilterAttr) toNative() uint32 {
return uint32(C.C_ATTRIBUTE_TSYNC)
case filterAttrLog:
return uint32(C.C_ATTRIBUTE_LOG)
case filterAttrSSB:
return uint32(C.C_ATTRIBUTE_SSB)
default:
return 0x0
}
}
func (a ScmpSyscall) toNative() C.uint32_t {
return C.uint32_t(a)
}
func syscallFromNative(a C.int) ScmpSyscall {
return ScmpSyscall(a)
}
func notifReqFromNative(req *C.struct_seccomp_notif) (*ScmpNotifReq, error) {
scmpArgs := make([]uint64, 6)
for i := 0; i < len(scmpArgs); i++ {
scmpArgs[i] = uint64(req.data.args[i])
}
arch, err := archFromNative(req.data.arch)
if err != nil {
return nil, err
}
scmpData := ScmpNotifData{
Syscall: syscallFromNative(req.data.nr),
Arch: arch,
InstrPointer: uint64(req.data.instruction_pointer),
Args: scmpArgs,
}
scmpReq := &ScmpNotifReq{
ID: uint64(req.id),
Pid: uint32(req.pid),
Flags: uint32(req.flags),
Data: scmpData,
}
return scmpReq, nil
}
func (scmpResp *ScmpNotifResp) toNative(resp *C.struct_seccomp_notif_resp) {
resp.id = C.__u64(scmpResp.ID)
resp.val = C.__s64(scmpResp.Val)
resp.error = (C.__s32(scmpResp.Error) * -1) // kernel requires a negated value
resp.flags = C.__u32(scmpResp.Flags)
}
// Userspace Notification API
// Calls to C.seccomp_notify* hidden from seccomp.go
func (f *ScmpFilter) getNotifFd() (ScmpFd, error) {
f.lock.Lock()
defer f.lock.Unlock()
if !f.valid {
return -1, errBadFilter
}
// Ignore error, if not supported returns apiLevel == 0
apiLevel, _ := GetAPI()
if apiLevel < 6 {
return -1, fmt.Errorf("seccomp notification requires API level >= 6; current level = %d", apiLevel)
}
fd := C.seccomp_notify_fd(f.filterCtx)
return ScmpFd(fd), nil
}
func notifReceive(fd ScmpFd) (*ScmpNotifReq, error) {
var req *C.struct_seccomp_notif
var resp *C.struct_seccomp_notif_resp
// Ignore error, if not supported returns apiLevel == 0
apiLevel, _ := GetAPI()
if apiLevel < 6 {
return nil, fmt.Errorf("seccomp notification requires API level >= 6; current level = %d", apiLevel)
}
// we only use the request here; the response is unused
if retCode := C.seccomp_notify_alloc(&req, &resp); retCode != 0 {
return nil, errRc(retCode)
}
defer func() {
C.seccomp_notify_free(req, resp)
}()
for {
retCode, errno := C.seccomp_notify_receive(C.int(fd), req)
if retCode == 0 {
break
}
if errno == syscall.EINTR {
continue
}
if errno == syscall.ENOENT {
return nil, errno
}
return nil, errRc(retCode)
}
return notifReqFromNative(req)
}
func notifRespond(fd ScmpFd, scmpResp *ScmpNotifResp) error {
var req *C.struct_seccomp_notif
var resp *C.struct_seccomp_notif_resp
// Ignore error, if not supported returns apiLevel == 0
apiLevel, _ := GetAPI()
if apiLevel < 6 {
return fmt.Errorf("seccomp notification requires API level >= 6; current level = %d", apiLevel)
}
// we only use the reponse here; the request is discarded
if retCode := C.seccomp_notify_alloc(&req, &resp); retCode != 0 {
return errRc(retCode)
}
defer func() {
C.seccomp_notify_free(req, resp)
}()
scmpResp.toNative(resp)
for {
retCode, errno := C.seccomp_notify_respond(C.int(fd), resp)
if retCode == 0 {
break
}
if errno == syscall.EINTR {
continue
}
if errno == syscall.ENOENT {
return errno
}
return errRc(retCode)
}
return nil
}
func notifIDValid(fd ScmpFd, id uint64) error {
// Ignore error, if not supported returns apiLevel == 0
apiLevel, _ := GetAPI()
if apiLevel < 6 {
return fmt.Errorf("seccomp notification requires API level >= 6; current level = %d", apiLevel)
}
for {
retCode, errno := C.seccomp_notify_id_valid(C.int(fd), C.uint64_t(id))
if retCode == 0 {
break
}
if errno == syscall.EINTR {
continue
}
if errno == syscall.ENOENT {
return errno
}
return errRc(retCode)
}
return nil
}