vendor: bump runc to 1.1.3

Release notes:
 https://github.com/opencontainers/runc/releases/tag/v1.1.3

In particular, this one is important:

 * Retry on dbus disconnect logic in libcontainer/cgroups/systemd now
   works as intended; this fix does not affect runc binary itself but
   is important for libcontainer users such as Kubernetes. (#3476)

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
Kir Kolyshkin 2022-06-09 16:18:21 -07:00
parent 5f40fb05cb
commit 865c9e8fb9
No known key found for this signature in database
GPG Key ID: 17DE5ECB75A1100E
20 changed files with 408 additions and 323 deletions

8
go.mod
View File

@ -56,7 +56,7 @@ require (
github.com/mvdan/xurls v1.1.0 github.com/mvdan/xurls v1.1.0
github.com/onsi/ginkgo v1.14.0 github.com/onsi/ginkgo v1.14.0
github.com/onsi/gomega v1.10.1 github.com/onsi/gomega v1.10.1
github.com/opencontainers/runc v1.1.1 github.com/opencontainers/runc v1.1.3
github.com/opencontainers/selinux v1.10.0 github.com/opencontainers/selinux v1.10.0
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/pmezard/go-difflib v1.0.0 github.com/pmezard/go-difflib v1.0.0
@ -216,7 +216,7 @@ require (
github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021 // indirect github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021 // indirect
github.com/russross/blackfriday v1.5.2 // indirect github.com/russross/blackfriday v1.5.2 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921 // indirect github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect github.com/sirupsen/logrus v1.8.1 // indirect
github.com/soheilhy/cmux v0.1.5 // indirect github.com/soheilhy/cmux v0.1.5 // indirect
github.com/stoewer/go-strcase v1.2.0 // indirect github.com/stoewer/go-strcase v1.2.0 // indirect
@ -456,7 +456,7 @@ replace (
github.com/onsi/gomega => github.com/onsi/gomega v1.10.1 github.com/onsi/gomega => github.com/onsi/gomega v1.10.1
github.com/opencontainers/go-digest => github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/go-digest => github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec => github.com/opencontainers/image-spec v1.0.2 github.com/opencontainers/image-spec => github.com/opencontainers/image-spec v1.0.2
github.com/opencontainers/runc => github.com/opencontainers/runc v1.1.1 github.com/opencontainers/runc => github.com/opencontainers/runc v1.1.3
github.com/opencontainers/runtime-spec => github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 github.com/opencontainers/runtime-spec => github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
github.com/opencontainers/selinux => github.com/opencontainers/selinux v1.10.0 github.com/opencontainers/selinux => github.com/opencontainers/selinux v1.10.0
github.com/opentracing/opentracing-go => github.com/opentracing/opentracing-go v1.1.0 github.com/opentracing/opentracing-go => github.com/opentracing/opentracing-go v1.1.0
@ -477,7 +477,7 @@ replace (
github.com/rubiojr/go-vhd => github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021 github.com/rubiojr/go-vhd => github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021
github.com/russross/blackfriday => github.com/russross/blackfriday v1.5.2 github.com/russross/blackfriday => github.com/russross/blackfriday v1.5.2
github.com/russross/blackfriday/v2 => github.com/russross/blackfriday/v2 v2.1.0 github.com/russross/blackfriday/v2 => github.com/russross/blackfriday/v2 v2.1.0
github.com/seccomp/libseccomp-golang => github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921 github.com/seccomp/libseccomp-golang => github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646
github.com/sergi/go-diff => github.com/sergi/go-diff v1.1.0 github.com/sergi/go-diff => github.com/sergi/go-diff v1.1.0
github.com/sirupsen/logrus => github.com/sirupsen/logrus v1.8.1 github.com/sirupsen/logrus => github.com/sirupsen/logrus v1.8.1
github.com/smartystreets/assertions => github.com/smartystreets/assertions v1.1.0 github.com/smartystreets/assertions => github.com/smartystreets/assertions v1.1.0

8
go.sum
View File

@ -337,8 +337,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v1.1.1 h1:PJ9DSs2sVwE0iVr++pAHE6QkS9tzcVWozlPifdwMgrU= github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w=
github.com/opencontainers/runc v1.1.1/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc=
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/selinux v1.10.0 h1:rAiKF8hTcgLI3w0DHm6i0ylVVcOrlgR1kK99DRLDhyU= github.com/opencontainers/selinux v1.10.0 h1:rAiKF8hTcgLI3w0DHm6i0ylVVcOrlgR1kK99DRLDhyU=
@ -374,8 +374,8 @@ github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNue
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921 h1:58EBmR2dMNL2n/FnbQewK3D14nXr0V9CObDSvMJLq+Y= github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646 h1:RpforrEYXWkmGwJHIGnLZ3tTWStkjVVstwzNGqxX2Ds=
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=

View File

@ -96,22 +96,6 @@ config := &configs.Config{
"CAP_KILL", "CAP_KILL",
"CAP_AUDIT_WRITE", "CAP_AUDIT_WRITE",
}, },
Inheritable: []string{
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_FSETID",
"CAP_FOWNER",
"CAP_MKNOD",
"CAP_NET_RAW",
"CAP_SETGID",
"CAP_SETUID",
"CAP_SETFCAP",
"CAP_SETPCAP",
"CAP_NET_BIND_SERVICE",
"CAP_SYS_CHROOT",
"CAP_KILL",
"CAP_AUDIT_WRITE",
},
Permitted: []string{ Permitted: []string{
"CAP_CHOWN", "CAP_CHOWN",
"CAP_DAC_OVERRIDE", "CAP_DAC_OVERRIDE",

View File

@ -289,7 +289,13 @@ func generateDeviceProperties(r *configs.Resources) ([]systemdDbus.Property, err
entry.Path = fmt.Sprintf("/dev/char/%d:%d", rule.Major, rule.Minor) entry.Path = fmt.Sprintf("/dev/char/%d:%d", rule.Major, rule.Minor)
} }
} }
deviceAllowList = append(deviceAllowList, entry) // systemd will issue a warning if the path we give here doesn't exist.
// Since all of this logic is best-effort anyway (we manually set these
// rules separately to systemd) we can safely skip entries that don't
// have a corresponding path.
if _, err := os.Stat(entry.Path); err == nil {
deviceAllowList = append(deviceAllowList, entry)
}
} }
properties = append(properties, newProp("DeviceAllow", deviceAllowList)) properties = append(properties, newProp("DeviceAllow", deviceAllowList))

View File

@ -2,6 +2,7 @@ package systemd
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"sync" "sync"
@ -80,8 +81,6 @@ func (d *dbusConnManager) resetConnection(conn *systemdDbus.Conn) {
} }
} }
var errDbusConnClosed = dbus.ErrClosed.Error()
// retryOnDisconnect calls op, and if the error it returns is about closed dbus // retryOnDisconnect calls op, and if the error it returns is about closed dbus
// connection, the connection is re-established and the op is retried. This helps // connection, the connection is re-established and the op is retried. This helps
// with the situation when dbus is restarted and we have a stale connection. // with the situation when dbus is restarted and we have a stale connection.
@ -92,7 +91,10 @@ func (d *dbusConnManager) retryOnDisconnect(op func(*systemdDbus.Conn) error) er
return err return err
} }
err = op(conn) err = op(conn)
if !isDbusError(err, errDbusConnClosed) { if err == nil {
return nil
}
if !errors.Is(err, dbus.ErrClosed) {
return err return err
} }
d.resetConnection(conn) d.resetConnection(conn)

View File

@ -338,7 +338,12 @@ func (l *LinuxFactory) StartInitialization() (err error) {
defer func() { defer func() {
if e := recover(); e != nil { if e := recover(); e != nil {
err = fmt.Errorf("panic from initialization: %w, %v", e, string(debug.Stack())) if e, ok := e.(error); ok {
err = fmt.Errorf("panic from initialization: %w, %s", e, debug.Stack())
} else {
//nolint:errorlint // here e is not of error type
err = fmt.Errorf("panic from initialization: %v, %s", e, debug.Stack())
}
} }
}() }()

View File

@ -39,13 +39,9 @@ type parentProcess interface {
// startTime returns the process start time. // startTime returns the process start time.
startTime() (uint64, error) startTime() (uint64, error)
signal(os.Signal) error signal(os.Signal) error
externalDescriptors() []string externalDescriptors() []string
setExternalDescriptors(fds []string) setExternalDescriptors(fds []string)
forwardChildLogs() chan error forwardChildLogs() chan error
} }

View File

@ -577,6 +577,7 @@ func checkProcMount(rootfs, dest, source string) error {
"/proc/loadavg", "/proc/loadavg",
"/proc/slabinfo", "/proc/slabinfo",
"/proc/net/dev", "/proc/net/dev",
"/proc/sys/kernel/ns_last_pid",
} }
for _, valid := range validProcMounts { for _, valid := range validProcMounts {
path, err := filepath.Rel(filepath.Join(rootfs, valid), dest) path, err := filepath.Rel(filepath.Join(rootfs, valid), dest)

View File

@ -29,13 +29,15 @@ func KnownOperators() []string {
} }
var actions = map[string]configs.Action{ var actions = map[string]configs.Action{
"SCMP_ACT_KILL": configs.Kill, "SCMP_ACT_KILL": configs.Kill,
"SCMP_ACT_ERRNO": configs.Errno, "SCMP_ACT_ERRNO": configs.Errno,
"SCMP_ACT_TRAP": configs.Trap, "SCMP_ACT_TRAP": configs.Trap,
"SCMP_ACT_ALLOW": configs.Allow, "SCMP_ACT_ALLOW": configs.Allow,
"SCMP_ACT_TRACE": configs.Trace, "SCMP_ACT_TRACE": configs.Trace,
"SCMP_ACT_LOG": configs.Log, "SCMP_ACT_LOG": configs.Log,
"SCMP_ACT_NOTIFY": configs.Notify, "SCMP_ACT_NOTIFY": configs.Notify,
"SCMP_ACT_KILL_THREAD": configs.KillThread,
"SCMP_ACT_KILL_PROCESS": configs.KillProcess,
} }
// KnownActions returns the list of the known actions. // KnownActions returns the list of the known actions.

View File

@ -72,6 +72,11 @@ import "C"
var retErrnoEnosys = uint32(C.C_ACT_ERRNO_ENOSYS) var retErrnoEnosys = uint32(C.C_ACT_ERRNO_ENOSYS)
// This syscall is used for multiplexing "large" syscalls on s390(x). Unknown
// syscalls will end up with this syscall number, so we need to explcitly
// return -ENOSYS for this syscall on those architectures.
const s390xMultiplexSyscall libseccomp.ScmpSyscall = 0
func isAllowAction(action configs.Action) bool { func isAllowAction(action configs.Action) bool {
switch action { switch action {
// Trace is considered an "allow" action because a good tracer should // Trace is considered an "allow" action because a good tracer should
@ -305,7 +310,7 @@ func generateEnosysStub(lastSyscalls lastSyscallMap) ([]bpf.Instruction, error)
// directly from the arch code so we need to do it here. Sadly we can't // directly from the arch code so we need to do it here. Sadly we can't
// share this code between architecture branches. // share this code between architecture branches.
section := []bpf.Instruction{ section := []bpf.Instruction{
// load [0] // load [0] (syscall number)
bpf.LoadAbsolute{Off: 0, Size: 4}, // NOTE: We assume sizeof(int) == 4. bpf.LoadAbsolute{Off: 0, Size: 4}, // NOTE: We assume sizeof(int) == 4.
} }
@ -314,10 +319,37 @@ func generateEnosysStub(lastSyscalls lastSyscallMap) ([]bpf.Instruction, error)
// No syscalls found for this arch -- skip it and move on. // No syscalls found for this arch -- skip it and move on.
continue continue
case 1: case 1:
// Get the only syscall in the map. // Get the only syscall and scmpArch in the map.
var sysno libseccomp.ScmpSyscall var (
for _, no := range maxSyscalls { scmpArch libseccomp.ScmpArch
sysno libseccomp.ScmpSyscall
)
for arch, no := range maxSyscalls {
sysno = no sysno = no
scmpArch = arch
}
switch scmpArch {
// Return -ENOSYS for setup(2) on s390(x). This syscall is used for
// multiplexing "large syscall number" syscalls, but if the syscall
// number is not known to the kernel then the syscall number is
// left unchanged (and because it is sysno=0, you'll end up with
// EPERM for syscalls the kernel doesn't know about).
//
// The actual setup(2) syscall is never used by userspace anymore
// (and hasn't existed for decades) outside of this multiplexing
// scheme so returning -ENOSYS is fine.
case libseccomp.ArchS390, libseccomp.ArchS390X:
section = append(section, []bpf.Instruction{
// jne [setup=0],1
bpf.JumpIf{
Cond: bpf.JumpNotEqual,
Val: uint32(s390xMultiplexSyscall),
SkipTrue: 1,
},
// ret [ENOSYS]
bpf.RetConstant{Val: retErrnoEnosys},
}...)
} }
// The simplest case just boils down to a single jgt instruction, // The simplest case just boils down to a single jgt instruction,
@ -349,12 +381,6 @@ func generateEnosysStub(lastSyscalls lastSyscallMap) ([]bpf.Instruction, error)
// If we're on x86 we need to add a check for x32 and if we're in // If we're on x86 we need to add a check for x32 and if we're in
// the wrong mode we jump over the section. // the wrong mode we jump over the section.
if uint32(nativeArch) == uint32(C.C_AUDIT_ARCH_X86_64) { if uint32(nativeArch) == uint32(C.C_AUDIT_ARCH_X86_64) {
// Grab the only architecture in the map.
var scmpArch libseccomp.ScmpArch
for arch := range maxSyscalls {
scmpArch = arch
}
// Generate a prefix to check the mode. // Generate a prefix to check the mode.
switch scmpArch { switch scmpArch {
case libseccomp.ArchAMD64: case libseccomp.ArchAMD64:
@ -512,7 +538,7 @@ func generateEnosysStub(lastSyscalls lastSyscallMap) ([]bpf.Instruction, error)
// Prepend the load instruction for the architecture. // Prepend the load instruction for the architecture.
programTail = append([]bpf.Instruction{ programTail = append([]bpf.Instruction{
// load [4] // load [4] (architecture)
bpf.LoadAbsolute{Off: 4, Size: 4}, // NOTE: We assume sizeof(int) == 4. bpf.LoadAbsolute{Off: 4, Size: 4}, // NOTE: We assume sizeof(int) == 4.
}, programTail...) }, programTail...)

View File

@ -113,8 +113,8 @@ func InitSeccomp(config *configs.Seccomp) (int, error) {
// Convert Libcontainer Action to Libseccomp ScmpAction // Convert Libcontainer Action to Libseccomp ScmpAction
func getAction(act configs.Action, errnoRet *uint) (libseccomp.ScmpAction, error) { func getAction(act configs.Action, errnoRet *uint) (libseccomp.ScmpAction, error) {
switch act { switch act {
case configs.Kill: case configs.Kill, configs.KillThread:
return libseccomp.ActKill, nil return libseccomp.ActKillThread, nil
case configs.Errno: case configs.Errno:
if errnoRet != nil { if errnoRet != nil {
return libseccomp.ActErrno.SetReturnCode(int16(*errnoRet)), nil return libseccomp.ActErrno.SetReturnCode(int16(*errnoRet)), nil
@ -133,8 +133,6 @@ func getAction(act configs.Action, errnoRet *uint) (libseccomp.ScmpAction, error
return libseccomp.ActLog, nil return libseccomp.ActLog, nil
case configs.Notify: case configs.Notify:
return libseccomp.ActNotify, nil return libseccomp.ActNotify, nil
case configs.KillThread:
return libseccomp.ActKillThread, nil
case configs.KillProcess: case configs.KillProcess:
return libseccomp.ActKillProcess, nil return libseccomp.ActKillProcess, nil
default: default:

View File

@ -0,0 +1,4 @@
# For documentation, see https://golangci-lint.run/usage/configuration/
linters:
enable:
- gofumpt

View File

@ -1,57 +0,0 @@
# 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

@ -1,31 +1,23 @@
How to Submit Patches to the libseccomp Project How to Submit Patches to the libseccomp-golang Project
=============================================================================== ===============================================================================
https://github.com/seccomp/libseccomp-golang https://github.com/seccomp/libseccomp-golang
This document is intended to act as a guide to help you contribute to the This document is intended to act as a guide to help you contribute to the
libseccomp project. It is not perfect, and there will always be exceptions libseccomp-golang project. It is not perfect, and there will always be
to the rules described here, but by following the instructions below you exceptions to the rules described here, but by following the instructions below
should have a much easier time getting your work merged with the upstream you should have a much easier time getting your work merged with the upstream
project. project.
## Test Your Code Using Existing Tests ## Test Your Code Using Existing Tests
There are two possible tests you can run to verify your code. The first A number of tests and lint related recipes are provided in the Makefile, if
test is used to check the formatting and coding style of your changes, you you want to run the standard regression tests, you can execute the following:
can run the test with the following command:
# make check-syntax
... if there are any problems with your changes a diff/patch will be shown
which indicates the problems and how to fix them.
The second possible test is used to ensure the sanity of your code changes
and to test these changes against the included tests. You can run the test
with the following command:
# make check # make check
... if there are any faults or errors they will be displayed. In order to use it, the 'golangci-lint' tool is needed, which can be found at:
* https://github.com/golangci/golangci-lint
## Add New Tests for New Functionality ## Add New Tests for New Functionality

View File

@ -4,7 +4,7 @@
all: check-build all: check-build
check: vet test check: lint test
check-build: check-build:
go build go build
@ -16,7 +16,7 @@ fix-syntax:
gofmt -w . gofmt -w .
vet: vet:
go vet -v go vet -v ./...
# Previous bugs have made the tests freeze until the timeout. Golang default # 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 # timeout for tests is 10 minutes, which is too long, considering current tests
@ -28,5 +28,4 @@ test:
go test -v -timeout $(TEST_TIMEOUT) go test -v -timeout $(TEST_TIMEOUT)
lint: lint:
@$(if $(shell which golint),true,$(error "install golint and include it in your PATH")) golangci-lint run .
golint -set_exit_status

View File

@ -2,7 +2,9 @@
=============================================================================== ===============================================================================
https://github.com/seccomp/libseccomp-golang https://github.com/seccomp/libseccomp-golang
[![Build Status](https://img.shields.io/travis/seccomp/libseccomp-golang/main.svg)](https://travis-ci.org/seccomp/libseccomp-golang) [![Go Reference](https://pkg.go.dev/badge/github.com/seccomp/libseccomp-golang.svg)](https://pkg.go.dev/github.com/seccomp/libseccomp-golang)
[![validate](https://github.com/seccomp/libseccomp-golang/actions/workflows/validate.yml/badge.svg)](https://github.com/seccomp/libseccomp-golang/actions/workflows/validate.yml)
[![test](https://github.com/seccomp/libseccomp-golang/actions/workflows/test.yml/badge.svg)](https://github.com/seccomp/libseccomp-golang/actions/workflows/test.yml)
The libseccomp library provides an easy to use, platform independent, interface The libseccomp library provides an easy to use, platform independent, interface
to the Linux Kernel's syscall filtering mechanism. The libseccomp API is to the Linux Kernel's syscall filtering mechanism. The libseccomp API is
@ -26,26 +28,14 @@ list.
* https://groups.google.com/d/forum/libseccomp * https://groups.google.com/d/forum/libseccomp
Documentation is also available at: Documentation for this package is also available at:
* https://godoc.org/github.com/seccomp/libseccomp-golang * https://pkg.go.dev/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 ## Contributing
A number of tests and lint related recipes are provided in the Makefile, if See [CONTRIBUTING.md](CONTRIBUTING.md).
you want to run the standard regression tests, you can excute the following:
# 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

View File

@ -0,0 +1,47 @@
The libseccomp-golang Security Vulnerability Handling Process
===============================================================================
https://github.com/seccomp/libseccomp-golang
This document document attempts to describe the processes through which
sensitive security relevant bugs can be responsibly disclosed to the
libseccomp-golang project and how the project maintainers should handle these
reports. Just like the other libseccomp-golang process documents, this
document should be treated as a guiding document and not a hard, unyielding set
of regulations; the bug reporters and project maintainers are encouraged to
work together to address the issues as best they can, in a manner which works
best for all parties involved.
### Reporting Problems
Problems with the libseccomp-golang library that are not suitable for immediate
public disclosure should be emailed to the current libseccomp-golang
maintainers, the list is below. We typically request at most a 90 day time
period to address the issue before it is made public, but we will make every
effort to address the issue as quickly as possible and shorten the disclosure
window.
* Paul Moore, paul@paul-moore.com
* Tom Hromatka, tom.hromatka@oracle.com
### Resolving Sensitive Security Issues
Upon disclosure of a bug, the maintainers should work together to investigate
the problem and decide on a solution. In order to prevent an early disclosure
of the problem, those working on the solution should do so privately and
outside of the traditional libseccomp-golang development practices. One
possible solution to this is to leverage the GitHub "Security" functionality to
create a private development fork that can be shared among the maintainers, and
optionally the reporter. A placeholder GitHub issue may be created, but
details should remain extremely limited until such time as the problem has been
fixed and responsibly disclosed. If a CVE, or other tag, has been assigned to
the problem, the GitHub issue title should include the vulnerability tag once
the problem has been disclosed.
### Public Disclosure
Whenever possible, responsible reporting and patching practices should be
followed, including notification to the linux-distros and oss-security mailing
lists.
* https://oss-security.openwall.org/wiki/mailing-lists/distros
* https://oss-security.openwall.org/wiki/mailing-lists/oss-security

View File

@ -1,5 +1,3 @@
// +build linux
// Public API specification for libseccomp Go bindings // Public API specification for libseccomp Go bindings
// Contains public API for the bindings // Contains public API for the bindings
@ -18,48 +16,36 @@ import (
"unsafe" "unsafe"
) )
// 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 <stdlib.h>
// #include <seccomp.h> // #include <seccomp.h>
import "C" import "C"
// Exported types // Exported types
// VersionError denotes that the system libseccomp version is incompatible // VersionError represents an error when either the system libseccomp version
// with this package. // or the kernel version is too old to perform the operation requested.
type VersionError struct { type VersionError struct {
message string op string // operation that failed or would fail
minimum string major, minor, micro uint // minimally required libseccomp version
curAPI, minAPI uint // current and minimally required API versions
} }
func init() { func init() {
// This forces the cgo libseccomp to initialize its internal API support state, // This forces the cgo libseccomp to initialize its internal API support state,
// which is necessary on older versions of libseccomp in order to work // which is necessary on older versions of libseccomp in order to work
// correctly. // correctly.
GetAPI() _, _ = getAPI()
} }
func (e VersionError) Error() string { func (e VersionError) Error() string {
messageStr := "" if e.minAPI != 0 {
if e.message != "" { return fmt.Sprintf("%s requires libseccomp >= %d.%d.%d and API level >= %d "+
messageStr = e.message + ": " "(current version: %d.%d.%d, API level: %d)",
e.op, e.major, e.minor, e.micro, e.minAPI,
verMajor, verMinor, verMicro, e.curAPI)
} }
minimumStr := "" return fmt.Sprintf("%s requires libseccomp >= %d.%d.%d (current version: %d.%d.%d)",
if e.minimum != "" { e.op, e.major, e.minor, e.micro, verMajor, verMinor, verMicro)
minimumStr = e.minimum
} else {
minimumStr = "2.2.0"
}
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 // ScmpArch represents a CPU architecture. Seccomp can restrict syscalls on a
@ -148,44 +134,46 @@ const (
// variables are invalid // variables are invalid
ArchInvalid ScmpArch = iota ArchInvalid ScmpArch = iota
// ArchNative is the native architecture of the kernel // ArchNative is the native architecture of the kernel
ArchNative ScmpArch = iota ArchNative
// ArchX86 represents 32-bit x86 syscalls // ArchX86 represents 32-bit x86 syscalls
ArchX86 ScmpArch = iota ArchX86
// ArchAMD64 represents 64-bit x86-64 syscalls // ArchAMD64 represents 64-bit x86-64 syscalls
ArchAMD64 ScmpArch = iota ArchAMD64
// ArchX32 represents 64-bit x86-64 syscalls (32-bit pointers) // ArchX32 represents 64-bit x86-64 syscalls (32-bit pointers)
ArchX32 ScmpArch = iota ArchX32
// ArchARM represents 32-bit ARM syscalls // ArchARM represents 32-bit ARM syscalls
ArchARM ScmpArch = iota ArchARM
// ArchARM64 represents 64-bit ARM syscalls // ArchARM64 represents 64-bit ARM syscalls
ArchARM64 ScmpArch = iota ArchARM64
// ArchMIPS represents 32-bit MIPS syscalls // ArchMIPS represents 32-bit MIPS syscalls
ArchMIPS ScmpArch = iota ArchMIPS
// ArchMIPS64 represents 64-bit MIPS syscalls // ArchMIPS64 represents 64-bit MIPS syscalls
ArchMIPS64 ScmpArch = iota ArchMIPS64
// ArchMIPS64N32 represents 64-bit MIPS syscalls (32-bit pointers) // ArchMIPS64N32 represents 64-bit MIPS syscalls (32-bit pointers)
ArchMIPS64N32 ScmpArch = iota ArchMIPS64N32
// ArchMIPSEL represents 32-bit MIPS syscalls (little endian) // ArchMIPSEL represents 32-bit MIPS syscalls (little endian)
ArchMIPSEL ScmpArch = iota ArchMIPSEL
// ArchMIPSEL64 represents 64-bit MIPS syscalls (little endian) // ArchMIPSEL64 represents 64-bit MIPS syscalls (little endian)
ArchMIPSEL64 ScmpArch = iota ArchMIPSEL64
// ArchMIPSEL64N32 represents 64-bit MIPS syscalls (little endian, // ArchMIPSEL64N32 represents 64-bit MIPS syscalls (little endian,
// 32-bit pointers) // 32-bit pointers)
ArchMIPSEL64N32 ScmpArch = iota ArchMIPSEL64N32
// ArchPPC represents 32-bit POWERPC syscalls // ArchPPC represents 32-bit POWERPC syscalls
ArchPPC ScmpArch = iota ArchPPC
// ArchPPC64 represents 64-bit POWER syscalls (big endian) // ArchPPC64 represents 64-bit POWER syscalls (big endian)
ArchPPC64 ScmpArch = iota ArchPPC64
// ArchPPC64LE represents 64-bit POWER syscalls (little endian) // ArchPPC64LE represents 64-bit POWER syscalls (little endian)
ArchPPC64LE ScmpArch = iota ArchPPC64LE
// ArchS390 represents 31-bit System z/390 syscalls // ArchS390 represents 31-bit System z/390 syscalls
ArchS390 ScmpArch = iota ArchS390
// ArchS390X represents 64-bit System z/390 syscalls // ArchS390X represents 64-bit System z/390 syscalls
ArchS390X ScmpArch = iota ArchS390X
// ArchPARISC represents 32-bit PA-RISC // ArchPARISC represents 32-bit PA-RISC
ArchPARISC ScmpArch = iota ArchPARISC
// ArchPARISC64 represents 64-bit PA-RISC // ArchPARISC64 represents 64-bit PA-RISC
ArchPARISC64 ScmpArch = iota ArchPARISC64
// ArchRISCV64 represents RISCV64
ArchRISCV64
) )
const ( const (
@ -194,34 +182,36 @@ const (
// ActInvalid is a placeholder to ensure uninitialized ScmpAction // ActInvalid is a placeholder to ensure uninitialized ScmpAction
// variables are invalid // variables are invalid
ActInvalid ScmpAction = iota ActInvalid ScmpAction = iota
// ActKill kills the thread that violated the rule. It is the same as ActKillThread. // ActKillThread kills the thread that violated the rule.
// All other threads from the same thread group will continue to execute. // All other threads from the same thread group will continue to execute.
ActKill ScmpAction = iota ActKillThread
// ActTrap throws SIGSYS // ActTrap throws SIGSYS
ActTrap ScmpAction = iota ActTrap
// ActNotify triggers a userspace notification. This action is only usable when // ActNotify triggers a userspace notification. This action is only usable when
// libseccomp API level 6 or higher is supported. // libseccomp API level 6 or higher is supported.
ActNotify ScmpAction = iota ActNotify
// ActErrno causes the syscall to return a negative error code. This // ActErrno causes the syscall to return a negative error code. This
// code can be set with the SetReturnCode method // code can be set with the SetReturnCode method
ActErrno ScmpAction = iota ActErrno
// ActTrace causes the syscall to notify tracing processes with the // ActTrace causes the syscall to notify tracing processes with the
// given error code. This code can be set with the SetReturnCode method // given error code. This code can be set with the SetReturnCode method
ActTrace ScmpAction = iota ActTrace
// ActAllow permits the syscall to continue execution // ActAllow permits the syscall to continue execution
ActAllow ScmpAction = iota ActAllow
// ActLog permits the syscall to continue execution after logging it. // ActLog permits the syscall to continue execution after logging it.
// This action is only usable when libseccomp API level 3 or higher is // This action is only usable when libseccomp API level 3 or higher is
// supported. // supported.
ActLog ScmpAction = iota ActLog
// 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. // ActKillProcess kills the process that violated the rule.
// All threads in the thread group are also terminated. // All threads in the thread group are also terminated.
// This action is only usable when libseccomp API level 3 or higher is // This action is only usable when libseccomp API level 3 or higher is
// supported. // supported.
ActKillProcess ScmpAction = iota ActKillProcess
// ActKill kills the thread that violated the rule.
// All other threads from the same thread group will continue to execute.
//
// Deprecated: use ActKillThread
ActKill = ActKillThread
) )
const ( const (
@ -234,36 +224,35 @@ const (
CompareInvalid ScmpCompareOp = iota CompareInvalid ScmpCompareOp = iota
// CompareNotEqual returns true if the argument is not equal to the // CompareNotEqual returns true if the argument is not equal to the
// given value // given value
CompareNotEqual ScmpCompareOp = iota CompareNotEqual
// CompareLess returns true if the argument is less than the given value // CompareLess returns true if the argument is less than the given value
CompareLess ScmpCompareOp = iota CompareLess
// CompareLessOrEqual returns true if the argument is less than or equal // CompareLessOrEqual returns true if the argument is less than or equal
// to the given value // to the given value
CompareLessOrEqual ScmpCompareOp = iota CompareLessOrEqual
// CompareEqual returns true if the argument is equal to the given value // CompareEqual returns true if the argument is equal to the given value
CompareEqual ScmpCompareOp = iota CompareEqual
// CompareGreaterEqual returns true if the argument is greater than or // CompareGreaterEqual returns true if the argument is greater than or
// equal to the given value // equal to the given value
CompareGreaterEqual ScmpCompareOp = iota CompareGreaterEqual
// CompareGreater returns true if the argument is greater than the given // CompareGreater returns true if the argument is greater than the given
// value // value
CompareGreater ScmpCompareOp = iota CompareGreater
// CompareMaskedEqual returns true if the argument is equal to the given // CompareMaskedEqual returns true if the masked argument value is
// value, when masked (bitwise &) against the second given value // equal to the masked datum value. Mask is the first argument, and
CompareMaskedEqual ScmpCompareOp = iota // datum is the second one.
CompareMaskedEqual
) )
var ( // ErrSyscallDoesNotExist represents an error condition where
// ErrSyscallDoesNotExist represents an error condition where // libseccomp is unable to resolve the syscall
// libseccomp is unable to resolve the syscall var ErrSyscallDoesNotExist = fmt.Errorf("could not resolve syscall name")
ErrSyscallDoesNotExist = fmt.Errorf("could not resolve syscall name")
)
const ( const (
// Userspace notification response flags // Userspace notification response flags
// NotifRespFlagContinue tells the kernel to continue executing the system // NotifRespFlagContinue tells the kernel to continue executing the system
// call that triggered the notification. Must only be used when the notication // call that triggered the notification. Must only be used when the notification
// response's error is 0. // response's error is 0.
NotifRespFlagContinue uint32 = 1 NotifRespFlagContinue uint32 = 1
) )
@ -314,6 +303,8 @@ func GetArchFromString(arch string) (ScmpArch, error) {
return ArchPARISC, nil return ArchPARISC, nil
case "parisc64": case "parisc64":
return ArchPARISC64, nil return ArchPARISC64, nil
case "riscv64":
return ArchRISCV64, nil
default: default:
return ArchInvalid, fmt.Errorf("cannot convert unrecognized string %q", arch) return ArchInvalid, fmt.Errorf("cannot convert unrecognized string %q", arch)
} }
@ -358,6 +349,8 @@ func (a ScmpArch) String() string {
return "parisc" return "parisc"
case ArchPARISC64: case ArchPARISC64:
return "parisc64" return "parisc64"
case ArchRISCV64:
return "riscv64"
case ArchNative: case ArchNative:
return "native" return "native"
case ArchInvalid: case ArchInvalid:
@ -394,7 +387,7 @@ func (a ScmpCompareOp) String() string {
// String returns a string representation of a seccomp match action // String returns a string representation of a seccomp match action
func (a ScmpAction) String() string { func (a ScmpAction) String() string {
switch a & 0xFFFF { switch a & 0xFFFF {
case ActKill, ActKillThread: case ActKillThread:
return "Action: Kill thread" return "Action: Kill thread"
case ActKillProcess: case ActKillProcess:
return "Action: Kill process" return "Action: Kill process"
@ -556,8 +549,8 @@ func MakeCondition(arg uint, comparison ScmpCompareOp, values ...uint64) (ScmpCo
return condStruct, err return condStruct, err
} }
if comparison == CompareInvalid { if err := sanitizeCompareOp(comparison); err != nil {
return condStruct, fmt.Errorf("invalid comparison operator") return condStruct, err
} else if arg > 5 { } else if arg > 5 {
return condStruct, fmt.Errorf("syscalls only have up to 6 arguments (%d given)", arg) return condStruct, fmt.Errorf("syscalls only have up to 6 arguments (%d given)", arg)
} else if len(values) > 2 { } else if len(values) > 2 {
@ -874,10 +867,8 @@ func (f *ScmpFilter) GetNoNewPrivsBit() (bool, error) {
func (f *ScmpFilter) GetLogBit() (bool, error) { func (f *ScmpFilter) GetLogBit() (bool, error) {
log, err := f.getFilterAttr(filterAttrLog) log, err := f.getFilterAttr(filterAttrLog)
if err != nil { if err != nil {
// Ignore error, if not supported returns apiLevel == 0 if e := checkAPI("GetLogBit", 3, 2, 4, 0); e != nil {
apiLevel, _ := GetAPI() err = e
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")
} }
return false, err return false, err
@ -899,9 +890,8 @@ func (f *ScmpFilter) GetLogBit() (bool, error) {
func (f *ScmpFilter) GetSSB() (bool, error) { func (f *ScmpFilter) GetSSB() (bool, error) {
ssb, err := f.getFilterAttr(filterAttrSSB) ssb, err := f.getFilterAttr(filterAttrSSB)
if err != nil { if err != nil {
api, apiErr := getAPI() if e := checkAPI("GetSSB", 4, 2, 5, 0); e != nil {
if (apiErr != nil && api == 0) || (apiErr == nil && api < 4) { err = e
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 return false, err
@ -914,6 +904,42 @@ func (f *ScmpFilter) GetSSB() (bool, error) {
return true, nil return true, nil
} }
// GetOptimize returns the current optimization level of the filter,
// or an error if an issue was encountered retrieving the value.
// See SetOptimize for more details.
func (f *ScmpFilter) GetOptimize() (int, error) {
level, err := f.getFilterAttr(filterAttrOptimize)
if err != nil {
if e := checkAPI("GetOptimize", 4, 2, 5, 0); e != nil {
err = e
}
return 0, err
}
return int(level), nil
}
// GetRawRC returns the current state of RawRC flag, or an error
// if an issue was encountered retrieving the value.
// See SetRawRC for more details.
func (f *ScmpFilter) GetRawRC() (bool, error) {
rawrc, err := f.getFilterAttr(filterAttrRawRC)
if err != nil {
if e := checkAPI("GetRawRC", 4, 2, 5, 0); e != nil {
err = e
}
return false, err
}
if rawrc == 0 {
return false, nil
}
return true, nil
}
// SetBadArchAction sets the default action taken on a syscall for an // SetBadArchAction sets the default action taken on a syscall for an
// architecture not in the filter, or an error if an issue was encountered // architecture not in the filter, or an error if an issue was encountered
// setting the value. // setting the value.
@ -953,10 +979,8 @@ func (f *ScmpFilter) SetLogBit(state bool) error {
err := f.setFilterAttr(filterAttrLog, toSet) err := f.setFilterAttr(filterAttrLog, toSet)
if err != nil { if err != nil {
// Ignore error, if not supported returns apiLevel == 0 if e := checkAPI("SetLogBit", 3, 2, 4, 0); e != nil {
apiLevel, _ := GetAPI() err = e
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")
} }
} }
@ -976,9 +1000,52 @@ func (f *ScmpFilter) SetSSB(state bool) error {
err := f.setFilterAttr(filterAttrSSB, toSet) err := f.setFilterAttr(filterAttrSSB, toSet)
if err != nil { if err != nil {
api, apiErr := getAPI() if e := checkAPI("SetSSB", 4, 2, 5, 0); e != nil {
if (apiErr != nil && api == 0) || (apiErr == nil && api < 4) { err = e
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
}
// SetOptimize sets optimization level of the seccomp filter. By default
// libseccomp generates a set of sequential "if" statements for each rule in
// the filter. SetSyscallPriority can be used to prioritize the order for the
// default cause. The binary tree optimization sorts by syscall numbers and
// generates consistent O(log n) filter traversal for every rule in the filter.
// The binary tree may be advantageous for large filters. Note that
// SetSyscallPriority is ignored when level == 2.
//
// The different optimization levels are:
// 0: Reserved value, not currently used.
// 1: Rules sorted by priority and complexity (DEFAULT).
// 2: Binary tree sorted by syscall number.
func (f *ScmpFilter) SetOptimize(level int) error {
cLevel := C.uint32_t(level)
err := f.setFilterAttr(filterAttrOptimize, cLevel)
if err != nil {
if e := checkAPI("SetOptimize", 4, 2, 5, 0); e != nil {
err = e
}
}
return err
}
// SetRawRC sets whether libseccomp should pass system error codes back to the
// caller, instead of the default ECANCELED. Defaults to false.
func (f *ScmpFilter) SetRawRC(state bool) error {
var toSet C.uint32_t = 0x0
if state {
toSet = 0x1
}
err := f.setFilterAttr(filterAttrRawRC, toSet)
if err != nil {
if e := checkAPI("SetRawRC", 4, 2, 5, 0); e != nil {
err = e
} }
} }
@ -1029,9 +1096,6 @@ func (f *ScmpFilter) AddRuleExact(call ScmpSyscall, action ScmpAction) error {
// AddRuleConditional adds a single rule for a conditional action on a syscall. // AddRuleConditional adds a single rule for a conditional action on a syscall.
// Returns an error if an issue was encountered adding the rule. // Returns an error if an issue was encountered adding the rule.
// All conditions must match for the rule to match. // All conditions must match for the rule to match.
// There is a bug in library versions below v2.2.1 which can, in some cases,
// cause conditions to be lost when more than one are used. Consequently,
// AddRuleConditional is disabled on library versions lower than v2.2.1
func (f *ScmpFilter) AddRuleConditional(call ScmpSyscall, action ScmpAction, conds []ScmpCondition) error { func (f *ScmpFilter) AddRuleConditional(call ScmpSyscall, action ScmpAction, conds []ScmpCondition) error {
return f.addRuleGeneric(call, action, false, conds) return f.addRuleGeneric(call, action, false, conds)
} }
@ -1043,9 +1107,6 @@ func (f *ScmpFilter) AddRuleConditional(call ScmpSyscall, action ScmpAction, con
// The rule will function exactly as described, but it may not function identically // The rule will function exactly as described, but it may not function identically
// (or be able to be applied to) all architectures. // (or be able to be applied to) all architectures.
// Returns an error if an issue was encountered adding the rule. // Returns an error if an issue was encountered adding the rule.
// There is a bug in library versions below v2.2.1 which can, in some cases,
// cause conditions to be lost when more than one are used. Consequently,
// AddRuleConditionalExact is disabled on library versions lower than v2.2.1
func (f *ScmpFilter) AddRuleConditionalExact(call ScmpSyscall, action ScmpAction, conds []ScmpCondition) error { func (f *ScmpFilter) AddRuleConditionalExact(call ScmpSyscall, action ScmpAction, conds []ScmpCondition) error {
return f.addRuleGeneric(call, action, true, conds) return f.addRuleGeneric(call, action, true, conds)
} }

View File

@ -1,11 +1,10 @@
// +build linux
// Internal functions for libseccomp Go bindings // Internal functions for libseccomp Go bindings
// No exported functions // No exported functions
package seccomp package seccomp
import ( import (
"errors"
"fmt" "fmt"
"syscall" "syscall"
) )
@ -27,10 +26,10 @@ import (
#include <stdlib.h> #include <stdlib.h>
#include <seccomp.h> #include <seccomp.h>
#if SCMP_VER_MAJOR < 2 #if (SCMP_VER_MAJOR < 2) || \
#error Minimum supported version of Libseccomp is v2.2.0 (SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 3) || \
#elif SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 2 (SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR == 3 && SCMP_VER_MICRO < 1)
#error Minimum supported version of Libseccomp is v2.2.0 #error This package requires libseccomp >= v2.3.1
#endif #endif
#define ARCH_BAD ~0 #define ARCH_BAD ~0
@ -65,6 +64,10 @@ const uint32_t C_ARCH_BAD = ARCH_BAD;
#define SCMP_ARCH_PARISC64 ARCH_BAD #define SCMP_ARCH_PARISC64 ARCH_BAD
#endif #endif
#ifndef SCMP_ARCH_RISCV64
#define SCMP_ARCH_RISCV64 ARCH_BAD
#endif
const uint32_t C_ARCH_NATIVE = SCMP_ARCH_NATIVE; const uint32_t C_ARCH_NATIVE = SCMP_ARCH_NATIVE;
const uint32_t C_ARCH_X86 = SCMP_ARCH_X86; const uint32_t C_ARCH_X86 = SCMP_ARCH_X86;
const uint32_t C_ARCH_X86_64 = SCMP_ARCH_X86_64; const uint32_t C_ARCH_X86_64 = SCMP_ARCH_X86_64;
@ -84,6 +87,7 @@ const uint32_t C_ARCH_S390 = SCMP_ARCH_S390;
const uint32_t C_ARCH_S390X = SCMP_ARCH_S390X; const uint32_t C_ARCH_S390X = SCMP_ARCH_S390X;
const uint32_t C_ARCH_PARISC = SCMP_ARCH_PARISC; const uint32_t C_ARCH_PARISC = SCMP_ARCH_PARISC;
const uint32_t C_ARCH_PARISC64 = SCMP_ARCH_PARISC64; const uint32_t C_ARCH_PARISC64 = SCMP_ARCH_PARISC64;
const uint32_t C_ARCH_RISCV64 = SCMP_ARCH_RISCV64;
#ifndef SCMP_ACT_LOG #ifndef SCMP_ACT_LOG
#define SCMP_ACT_LOG 0x7ffc0000U #define SCMP_ACT_LOG 0x7ffc0000U
@ -113,20 +117,25 @@ const uint32_t C_ACT_NOTIFY = SCMP_ACT_NOTIFY;
// The libseccomp SCMP_FLTATR_CTL_LOG member of the scmp_filter_attr enum was // The libseccomp SCMP_FLTATR_CTL_LOG member of the scmp_filter_attr enum was
// added in v2.4.0 // added in v2.4.0
#if (SCMP_VER_MAJOR < 2) || \ #if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 4
(SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 4)
#define SCMP_FLTATR_CTL_LOG _SCMP_FLTATR_MIN #define SCMP_FLTATR_CTL_LOG _SCMP_FLTATR_MIN
#endif #endif
// The following SCMP_FLTATR_* were added in libseccomp v2.5.0.
#if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 5 #if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 5
#define SCMP_FLTATR_CTL_SSB _SCMP_FLTATR_MIN #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 #endif
const uint32_t C_ATTRIBUTE_DEFAULT = (uint32_t)SCMP_FLTATR_ACT_DEFAULT; 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_BADARCH = (uint32_t)SCMP_FLTATR_ACT_BADARCH;
const uint32_t C_ATTRIBUTE_NNP = (uint32_t)SCMP_FLTATR_CTL_NNP; 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_TSYNC = (uint32_t)SCMP_FLTATR_CTL_TSYNC;
const uint32_t C_ATTRIBUTE_LOG = (uint32_t)SCMP_FLTATR_CTL_LOG; 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 uint32_t C_ATTRIBUTE_SSB = (uint32_t)SCMP_FLTATR_CTL_SSB;
const uint32_t C_ATTRIBUTE_OPTIMIZE = (uint32_t)SCMP_FLTATR_CTL_OPTIMIZE;
const uint32_t C_ATTRIBUTE_SYSRAWRC = (uint32_t)SCMP_FLTATR_API_SYSRAWRC;
const int C_CMP_NE = (int)SCMP_CMP_NE; const int C_CMP_NE = (int)SCMP_CMP_NE;
const int C_CMP_LT = (int)SCMP_CMP_LT; const int C_CMP_LT = (int)SCMP_CMP_LT;
@ -173,8 +182,7 @@ unsigned int get_micro_version()
#endif #endif
// The libseccomp API level functions were added in v2.4.0 // The libseccomp API level functions were added in v2.4.0
#if (SCMP_VER_MAJOR < 2) || \ #if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 4
(SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 4)
const unsigned int seccomp_api_get(void) const unsigned int seccomp_api_get(void)
{ {
// libseccomp-golang requires libseccomp v2.2.0, at a minimum, which // libseccomp-golang requires libseccomp v2.2.0, at a minimum, which
@ -217,8 +225,7 @@ void add_struct_arg_cmp(
} }
// The seccomp notify API functions were added in v2.5.0 // The seccomp notify API functions were added in v2.5.0
#if (SCMP_VER_MAJOR < 2) || \ #if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 5
(SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 5)
struct seccomp_data { struct seccomp_data {
int nr; int nr;
@ -270,11 +277,13 @@ type scmpFilterAttr uint32
const ( const (
filterAttrActDefault scmpFilterAttr = iota filterAttrActDefault scmpFilterAttr = iota
filterAttrActBadArch scmpFilterAttr = iota filterAttrActBadArch
filterAttrNNP scmpFilterAttr = iota filterAttrNNP
filterAttrTsync scmpFilterAttr = iota filterAttrTsync
filterAttrLog scmpFilterAttr = iota filterAttrLog
filterAttrSSB scmpFilterAttr = iota filterAttrSSB
filterAttrOptimize
filterAttrRawRC
) )
const ( const (
@ -282,9 +291,9 @@ const (
scmpError C.int = -1 scmpError C.int = -1
// Comparison boundaries to check for architecture validity // Comparison boundaries to check for architecture validity
archStart ScmpArch = ArchNative archStart ScmpArch = ArchNative
archEnd ScmpArch = ArchPARISC64 archEnd ScmpArch = ArchRISCV64
// Comparison boundaries to check for action validity // Comparison boundaries to check for action validity
actionStart ScmpAction = ActKill actionStart ScmpAction = ActKillThread
actionEnd ScmpAction = ActKillProcess actionEnd ScmpAction = ActKillProcess
// Comparison boundaries to check for comparison operator validity // Comparison boundaries to check for comparison operator validity
compareOpStart ScmpCompareOp = CompareNotEqual compareOpStart ScmpCompareOp = CompareNotEqual
@ -292,8 +301,9 @@ const (
) )
var ( var (
// Error thrown on bad filter context // errBadFilter is thrown on bad filter context.
errBadFilter = fmt.Errorf("filter is invalid or uninitialized") 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 // Constants representing library major, minor, and micro versions
verMajor = uint(C.get_major_version()) verMajor = uint(C.get_major_version())
verMinor = uint(C.get_minor_version()) verMinor = uint(C.get_minor_version())
@ -302,19 +312,28 @@ var (
// Nonexported functions // Nonexported functions
// Check if library version is greater than or equal to the given one // checkVersion returns an error if the libseccomp version being used
func checkVersionAbove(major, minor, micro uint) bool { // is less than the one specified by major, minor, and micro arguments.
return (verMajor > major) || // 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) ||
(verMajor == major && verMinor == minor && verMicro >= micro) (verMajor == major && verMinor == minor && verMicro >= micro) {
return nil
}
return &VersionError{
op: op,
major: major,
minor: minor,
micro: micro,
}
} }
// Ensure that the library is supported, i.e. >= 2.2.0.
func ensureSupportedVersion() error { func ensureSupportedVersion() error {
if !checkVersionAbove(2, 2, 0) { return checkVersion("seccomp", 2, 3, 1)
return VersionError{}
}
return nil
} }
// Get the API level // Get the API level
@ -406,8 +425,10 @@ func (f *ScmpFilter) addRuleWrapper(call ScmpSyscall, action ScmpAction, exact b
switch e := errRc(retCode); e { switch e := errRc(retCode); e {
case syscall.EFAULT: case syscall.EFAULT:
return fmt.Errorf("unrecognized syscall %#x", int32(call)) return fmt.Errorf("unrecognized syscall %#x", int32(call))
case syscall.EPERM: // libseccomp >= v2.5.0 returns EACCES, older versions return EPERM.
return fmt.Errorf("requested action matches default action of filter") // TODO: remove EPERM once libseccomp < v2.5.0 is not supported.
case syscall.EPERM, syscall.EACCES:
return errDefAction
case syscall.EINVAL: case syscall.EINVAL:
return fmt.Errorf("two checks on same syscall argument") return fmt.Errorf("two checks on same syscall argument")
default: default:
@ -432,14 +453,6 @@ func (f *ScmpFilter) addRuleGeneric(call ScmpSyscall, action ScmpAction, exact b
return err return err
} }
} else { } else {
// We don't support conditional filtering in library version v2.1
if !checkVersionAbove(2, 2, 1) {
return VersionError{
message: "conditional filtering is not supported",
minimum: "2.2.1",
}
}
argsArr := C.make_arg_cmp_array(C.uint(len(conds))) argsArr := C.make_arg_cmp_array(C.uint(len(conds)))
if argsArr == nil { if argsArr == nil {
return fmt.Errorf("error allocating memory for conditions") return fmt.Errorf("error allocating memory for conditions")
@ -536,6 +549,8 @@ func archFromNative(a C.uint32_t) (ScmpArch, error) {
return ArchPARISC, nil return ArchPARISC, nil
case C.C_ARCH_PARISC64: case C.C_ARCH_PARISC64:
return ArchPARISC64, nil return ArchPARISC64, nil
case C.C_ARCH_RISCV64:
return ArchRISCV64, nil
default: default:
return 0x0, fmt.Errorf("unrecognized architecture %#x", uint32(a)) return 0x0, fmt.Errorf("unrecognized architecture %#x", uint32(a))
} }
@ -580,6 +595,8 @@ func (a ScmpArch) toNative() C.uint32_t {
return C.C_ARCH_PARISC return C.C_ARCH_PARISC
case ArchPARISC64: case ArchPARISC64:
return C.C_ARCH_PARISC64 return C.C_ARCH_PARISC64
case ArchRISCV64:
return C.C_ARCH_RISCV64
case ArchNative: case ArchNative:
return C.C_ARCH_NATIVE return C.C_ARCH_NATIVE
default: default:
@ -612,8 +629,6 @@ func (a ScmpCompareOp) toNative() C.int {
func actionFromNative(a C.uint32_t) (ScmpAction, error) { func actionFromNative(a C.uint32_t) (ScmpAction, error) {
aTmp := a & 0xFFFF aTmp := a & 0xFFFF
switch a & 0xFFFF0000 { switch a & 0xFFFF0000 {
case C.C_ACT_KILL:
return ActKill, nil
case C.C_ACT_KILL_PROCESS: case C.C_ACT_KILL_PROCESS:
return ActKillProcess, nil return ActKillProcess, nil
case C.C_ACT_KILL_THREAD: case C.C_ACT_KILL_THREAD:
@ -638,8 +653,6 @@ func actionFromNative(a C.uint32_t) (ScmpAction, error) {
// Only use with sanitized actions, no error handling // Only use with sanitized actions, no error handling
func (a ScmpAction) toNative() C.uint32_t { func (a ScmpAction) toNative() C.uint32_t {
switch a & 0xFFFF { switch a & 0xFFFF {
case ActKill:
return C.C_ACT_KILL
case ActKillProcess: case ActKillProcess:
return C.C_ACT_KILL_PROCESS return C.C_ACT_KILL_PROCESS
case ActKillThread: case ActKillThread:
@ -676,15 +689,15 @@ func (a scmpFilterAttr) toNative() uint32 {
return uint32(C.C_ATTRIBUTE_LOG) return uint32(C.C_ATTRIBUTE_LOG)
case filterAttrSSB: case filterAttrSSB:
return uint32(C.C_ATTRIBUTE_SSB) return uint32(C.C_ATTRIBUTE_SSB)
case filterAttrOptimize:
return uint32(C.C_ATTRIBUTE_OPTIMIZE)
case filterAttrRawRC:
return uint32(C.C_ATTRIBUTE_SYSRAWRC)
default: default:
return 0x0 return 0x0
} }
} }
func (a ScmpSyscall) toNative() C.uint32_t {
return C.uint32_t(a)
}
func syscallFromNative(a C.int) ScmpSyscall { func syscallFromNative(a C.int) ScmpSyscall {
return ScmpSyscall(a) return ScmpSyscall(a)
} }
@ -724,9 +737,34 @@ func (scmpResp *ScmpNotifResp) toNative(resp *C.struct_seccomp_notif_resp) {
resp.flags = C.__u32(scmpResp.Flags) resp.flags = C.__u32(scmpResp.Flags)
} }
// checkAPI checks that both the API level and the seccomp version is equal to
// or greater than the specified minLevel and major, minor, micro,
// respectively, and returns an error otherwise. Argument op is an arbitrary
// non-empty operation description, used as a part of the error message
// returned.
func checkAPI(op string, minLevel uint, major, minor, micro uint) error {
// Ignore error from getAPI, as it returns level == 0 in case of error.
level, _ := getAPI()
if level >= minLevel {
return checkVersion(op, major, minor, micro)
}
return &VersionError{
op: op,
curAPI: level,
minAPI: minLevel,
major: major,
minor: minor,
micro: micro,
}
}
// Userspace Notification API // Userspace Notification API
// Calls to C.seccomp_notify* hidden from seccomp.go // Calls to C.seccomp_notify* hidden from seccomp.go
func notifSupported() error {
return checkAPI("seccomp notification", 6, 2, 5, 0)
}
func (f *ScmpFilter) getNotifFd() (ScmpFd, error) { func (f *ScmpFilter) getNotifFd() (ScmpFd, error) {
f.lock.Lock() f.lock.Lock()
defer f.lock.Unlock() defer f.lock.Unlock()
@ -734,11 +772,8 @@ func (f *ScmpFilter) getNotifFd() (ScmpFd, error) {
if !f.valid { if !f.valid {
return -1, errBadFilter return -1, errBadFilter
} }
if err := notifSupported(); err != nil {
// Ignore error, if not supported returns apiLevel == 0 return -1, err
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) fd := C.seccomp_notify_fd(f.filterCtx)
@ -750,10 +785,8 @@ func notifReceive(fd ScmpFd) (*ScmpNotifReq, error) {
var req *C.struct_seccomp_notif var req *C.struct_seccomp_notif
var resp *C.struct_seccomp_notif_resp var resp *C.struct_seccomp_notif_resp
// Ignore error, if not supported returns apiLevel == 0 if err := notifSupported(); err != nil {
apiLevel, _ := GetAPI() return nil, err
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 // we only use the request here; the response is unused
@ -789,13 +822,11 @@ func notifRespond(fd ScmpFd, scmpResp *ScmpNotifResp) error {
var req *C.struct_seccomp_notif var req *C.struct_seccomp_notif
var resp *C.struct_seccomp_notif_resp var resp *C.struct_seccomp_notif_resp
// Ignore error, if not supported returns apiLevel == 0 if err := notifSupported(); err != nil {
apiLevel, _ := GetAPI() return err
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 // we only use the response here; the request is discarded
if retCode := C.seccomp_notify_alloc(&req, &resp); retCode != 0 { if retCode := C.seccomp_notify_alloc(&req, &resp); retCode != 0 {
return errRc(retCode) return errRc(retCode)
} }
@ -827,10 +858,8 @@ func notifRespond(fd ScmpFd, scmpResp *ScmpNotifResp) error {
} }
func notifIDValid(fd ScmpFd, id uint64) error { func notifIDValid(fd ScmpFd, id uint64) error {
// Ignore error, if not supported returns apiLevel == 0 if err := notifSupported(); err != nil {
apiLevel, _ := GetAPI() return err
if apiLevel < 6 {
return fmt.Errorf("seccomp notification requires API level >= 6; current level = %d", apiLevel)
} }
for { for {

8
vendor/modules.txt vendored
View File

@ -668,7 +668,7 @@ github.com/onsi/gomega/types
# github.com/opencontainers/go-digest v1.0.0 => github.com/opencontainers/go-digest v1.0.0 # github.com/opencontainers/go-digest v1.0.0 => github.com/opencontainers/go-digest v1.0.0
## explicit; go 1.13 ## explicit; go 1.13
github.com/opencontainers/go-digest github.com/opencontainers/go-digest
# github.com/opencontainers/runc v1.1.1 => github.com/opencontainers/runc v1.1.1 # github.com/opencontainers/runc v1.1.3 => github.com/opencontainers/runc v1.1.3
## explicit; go 1.16 ## explicit; go 1.16
github.com/opencontainers/runc/libcontainer github.com/opencontainers/runc/libcontainer
github.com/opencontainers/runc/libcontainer/apparmor github.com/opencontainers/runc/libcontainer/apparmor
@ -752,7 +752,7 @@ github.com/russross/blackfriday
# github.com/russross/blackfriday/v2 v2.1.0 => github.com/russross/blackfriday/v2 v2.1.0 # github.com/russross/blackfriday/v2 v2.1.0 => github.com/russross/blackfriday/v2 v2.1.0
## explicit ## explicit
github.com/russross/blackfriday/v2 github.com/russross/blackfriday/v2
# github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921 => github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921 # github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646 => github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646
## explicit; go 1.14 ## explicit; go 1.14
github.com/seccomp/libseccomp-golang github.com/seccomp/libseccomp-golang
# github.com/sirupsen/logrus v1.8.1 => github.com/sirupsen/logrus v1.8.1 # github.com/sirupsen/logrus v1.8.1 => github.com/sirupsen/logrus v1.8.1
@ -2738,7 +2738,7 @@ sigs.k8s.io/yaml
# github.com/onsi/gomega => github.com/onsi/gomega v1.10.1 # github.com/onsi/gomega => github.com/onsi/gomega v1.10.1
# github.com/opencontainers/go-digest => github.com/opencontainers/go-digest v1.0.0 # github.com/opencontainers/go-digest => github.com/opencontainers/go-digest v1.0.0
# github.com/opencontainers/image-spec => github.com/opencontainers/image-spec v1.0.2 # github.com/opencontainers/image-spec => github.com/opencontainers/image-spec v1.0.2
# github.com/opencontainers/runc => github.com/opencontainers/runc v1.1.1 # github.com/opencontainers/runc => github.com/opencontainers/runc v1.1.3
# github.com/opencontainers/runtime-spec => github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 # github.com/opencontainers/runtime-spec => github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
# github.com/opencontainers/selinux => github.com/opencontainers/selinux v1.10.0 # github.com/opencontainers/selinux => github.com/opencontainers/selinux v1.10.0
# github.com/opentracing/opentracing-go => github.com/opentracing/opentracing-go v1.1.0 # github.com/opentracing/opentracing-go => github.com/opentracing/opentracing-go v1.1.0
@ -2759,7 +2759,7 @@ sigs.k8s.io/yaml
# github.com/rubiojr/go-vhd => github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021 # github.com/rubiojr/go-vhd => github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021
# github.com/russross/blackfriday => github.com/russross/blackfriday v1.5.2 # github.com/russross/blackfriday => github.com/russross/blackfriday v1.5.2
# github.com/russross/blackfriday/v2 => github.com/russross/blackfriday/v2 v2.1.0 # github.com/russross/blackfriday/v2 => github.com/russross/blackfriday/v2 v2.1.0
# github.com/seccomp/libseccomp-golang => github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921 # github.com/seccomp/libseccomp-golang => github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646
# github.com/sergi/go-diff => github.com/sergi/go-diff v1.1.0 # github.com/sergi/go-diff => github.com/sergi/go-diff v1.1.0
# github.com/sirupsen/logrus => github.com/sirupsen/logrus v1.8.1 # github.com/sirupsen/logrus => github.com/sirupsen/logrus v1.8.1
# github.com/smartystreets/assertions => github.com/smartystreets/assertions v1.1.0 # github.com/smartystreets/assertions => github.com/smartystreets/assertions v1.1.0