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:
51
vendor/github.com/opencontainers/runc/libcontainer/seccomp/config.go
generated
vendored
51
vendor/github.com/opencontainers/runc/libcontainer/seccomp/config.go
generated
vendored
@@ -2,6 +2,7 @@ package seccomp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
)
|
||||
@@ -16,13 +17,36 @@ var operators = map[string]configs.Operator{
|
||||
"SCMP_CMP_MASKED_EQ": configs.MaskEqualTo,
|
||||
}
|
||||
|
||||
// KnownOperators returns the list of the known operations.
|
||||
// Used by `runc features`.
|
||||
func KnownOperators() []string {
|
||||
var res []string
|
||||
for k := range operators {
|
||||
res = append(res, k)
|
||||
}
|
||||
sort.Strings(res)
|
||||
return res
|
||||
}
|
||||
|
||||
var actions = map[string]configs.Action{
|
||||
"SCMP_ACT_KILL": configs.Kill,
|
||||
"SCMP_ACT_ERRNO": configs.Errno,
|
||||
"SCMP_ACT_TRAP": configs.Trap,
|
||||
"SCMP_ACT_ALLOW": configs.Allow,
|
||||
"SCMP_ACT_TRACE": configs.Trace,
|
||||
"SCMP_ACT_LOG": configs.Log,
|
||||
"SCMP_ACT_KILL": configs.Kill,
|
||||
"SCMP_ACT_ERRNO": configs.Errno,
|
||||
"SCMP_ACT_TRAP": configs.Trap,
|
||||
"SCMP_ACT_ALLOW": configs.Allow,
|
||||
"SCMP_ACT_TRACE": configs.Trace,
|
||||
"SCMP_ACT_LOG": configs.Log,
|
||||
"SCMP_ACT_NOTIFY": configs.Notify,
|
||||
}
|
||||
|
||||
// KnownActions returns the list of the known actions.
|
||||
// Used by `runc features`.
|
||||
func KnownActions() []string {
|
||||
var res []string
|
||||
for k := range actions {
|
||||
res = append(res, k)
|
||||
}
|
||||
sort.Strings(res)
|
||||
return res
|
||||
}
|
||||
|
||||
var archs = map[string]string{
|
||||
@@ -44,6 +68,17 @@ var archs = map[string]string{
|
||||
"SCMP_ARCH_S390X": "s390x",
|
||||
}
|
||||
|
||||
// KnownArchs returns the list of the known archs.
|
||||
// Used by `runc features`.
|
||||
func KnownArchs() []string {
|
||||
var res []string
|
||||
for k := range archs {
|
||||
res = append(res, k)
|
||||
}
|
||||
sort.Strings(res)
|
||||
return res
|
||||
}
|
||||
|
||||
// ConvertStringToOperator converts a string into a Seccomp comparison operator.
|
||||
// Comparison operators use the names they are assigned by Libseccomp's header.
|
||||
// Attempting to convert a string that is not a valid operator results in an
|
||||
@@ -56,9 +91,7 @@ func ConvertStringToOperator(in string) (configs.Operator, error) {
|
||||
}
|
||||
|
||||
// ConvertStringToAction converts a string into a Seccomp rule match action.
|
||||
// Actions use the names they are assigned in Libseccomp's header, though some
|
||||
// (notable, SCMP_ACT_TRACE) are not available in this implementation and will
|
||||
// return errors.
|
||||
// Actions use the names they are assigned in Libseccomp's header.
|
||||
// Attempting to convert a string that is not a valid action results in an
|
||||
// error.
|
||||
func ConvertStringToAction(in string) (configs.Action, error) {
|
||||
|
||||
116
vendor/github.com/opencontainers/runc/libcontainer/seccomp/patchbpf/enosys_linux.go
generated
vendored
116
vendor/github.com/opencontainers/runc/libcontainer/seccomp/patchbpf/enosys_linux.go
generated
vendored
@@ -1,23 +1,25 @@
|
||||
// +build linux,cgo,seccomp
|
||||
//go:build cgo && seccomp
|
||||
// +build cgo,seccomp
|
||||
|
||||
package patchbpf
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
"github.com/opencontainers/runc/libcontainer/utils"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
libseccomp "github.com/seccomp/libseccomp-golang"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/bpf"
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
"github.com/opencontainers/runc/libcontainer/utils"
|
||||
)
|
||||
|
||||
// #cgo pkg-config: libseccomp
|
||||
@@ -41,6 +43,11 @@ const uintptr_t C_SET_MODE_FILTER = SECCOMP_SET_MODE_FILTER;
|
||||
#endif
|
||||
const uintptr_t C_FILTER_FLAG_LOG = SECCOMP_FILTER_FLAG_LOG;
|
||||
|
||||
#ifndef SECCOMP_FILTER_FLAG_NEW_LISTENER
|
||||
# define SECCOMP_FILTER_FLAG_NEW_LISTENER (1UL << 3)
|
||||
#endif
|
||||
const uintptr_t C_FILTER_FLAG_NEW_LISTENER = SECCOMP_FILTER_FLAG_NEW_LISTENER;
|
||||
|
||||
// We use the AUDIT_ARCH_* values because those are the ones used by the kernel
|
||||
// and SCMP_ARCH_* sometimes has fake values (such as SCMP_ARCH_X32). But we
|
||||
// use <seccomp.h> so we get libseccomp's fallback definitions of AUDIT_ARCH_*.
|
||||
@@ -85,17 +92,16 @@ loop:
|
||||
// seccomp_export_bpf outputs the program in *host* endian-ness.
|
||||
var insn unix.SockFilter
|
||||
if err := binary.Read(rdr, utils.NativeEndian, &insn); err != nil {
|
||||
switch err {
|
||||
case io.EOF:
|
||||
if errors.Is(err, io.EOF) {
|
||||
// Parsing complete.
|
||||
break loop
|
||||
case io.ErrUnexpectedEOF:
|
||||
// Parsing stopped mid-instruction.
|
||||
return nil, errors.Wrap(err, "program parsing halted mid-instruction")
|
||||
default:
|
||||
// All other errors.
|
||||
return nil, errors.Wrap(err, "parsing instructions")
|
||||
}
|
||||
if errors.Is(err, io.ErrUnexpectedEOF) {
|
||||
// Parsing stopped mid-instruction.
|
||||
return nil, fmt.Errorf("program parsing halted mid-instruction: %w", err)
|
||||
}
|
||||
// All other errors.
|
||||
return nil, fmt.Errorf("error parsing instructions: %w", err)
|
||||
}
|
||||
program = append(program, bpf.RawInstruction{
|
||||
Op: insn.Code,
|
||||
@@ -110,7 +116,7 @@ loop:
|
||||
func disassembleFilter(filter *libseccomp.ScmpFilter) ([]bpf.Instruction, error) {
|
||||
rdr, wtr, err := os.Pipe()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "creating scratch pipe")
|
||||
return nil, fmt.Errorf("error creating scratch pipe: %w", err)
|
||||
}
|
||||
defer wtr.Close()
|
||||
defer rdr.Close()
|
||||
@@ -124,23 +130,23 @@ func disassembleFilter(filter *libseccomp.ScmpFilter) ([]bpf.Instruction, error)
|
||||
}()
|
||||
|
||||
if err := filter.ExportBPF(wtr); err != nil {
|
||||
return nil, errors.Wrap(err, "exporting BPF")
|
||||
return nil, fmt.Errorf("error exporting BPF: %w", err)
|
||||
}
|
||||
// Close so that the reader actually gets EOF.
|
||||
_ = wtr.Close()
|
||||
|
||||
if copyErr := <-errChan; copyErr != nil {
|
||||
return nil, errors.Wrap(copyErr, "reading from ExportBPF pipe")
|
||||
return nil, fmt.Errorf("error reading from ExportBPF pipe: %w", copyErr)
|
||||
}
|
||||
|
||||
// Parse the instructions.
|
||||
rawProgram, err := parseProgram(readerBuffer)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "parsing generated BPF filter")
|
||||
return nil, fmt.Errorf("parsing generated BPF filter: %w", err)
|
||||
}
|
||||
program, ok := bpf.Disassemble(rawProgram)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("could not disassemble entire BPF filter")
|
||||
return nil, errors.New("could not disassemble entire BPF filter")
|
||||
}
|
||||
return program, nil
|
||||
}
|
||||
@@ -155,7 +161,7 @@ func archToNative(arch libseccomp.ScmpArch) (nativeArch, error) {
|
||||
// Convert to actual native architecture.
|
||||
arch, err := libseccomp.GetNativeArch()
|
||||
if err != nil {
|
||||
return invalidArch, errors.Wrap(err, "get native arch")
|
||||
return invalidArch, fmt.Errorf("unable to get native arch: %w", err)
|
||||
}
|
||||
return archToNative(arch)
|
||||
case libseccomp.ArchX86:
|
||||
@@ -192,7 +198,7 @@ func archToNative(arch libseccomp.ScmpArch) (nativeArch, error) {
|
||||
case libseccomp.ArchS390X:
|
||||
return nativeArch(C.C_AUDIT_ARCH_S390X), nil
|
||||
default:
|
||||
return invalidArch, errors.Errorf("unknown architecture: %v", arch)
|
||||
return invalidArch, fmt.Errorf("unknown architecture: %v", arch)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,7 +215,7 @@ func findLastSyscalls(config *configs.Seccomp) (lastSyscallMap, error) {
|
||||
for _, ociArch := range config.Architectures {
|
||||
arch, err := libseccomp.GetArchFromString(ociArch)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "validating seccomp architecture")
|
||||
return nil, fmt.Errorf("unable to validate seccomp architecture: %w", err)
|
||||
}
|
||||
|
||||
// Map native architecture to a real architecture value to avoid
|
||||
@@ -217,7 +223,7 @@ func findLastSyscalls(config *configs.Seccomp) (lastSyscallMap, error) {
|
||||
if arch == libseccomp.ArchNative {
|
||||
nativeArch, err := libseccomp.GetNativeArch()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get native arch")
|
||||
return nil, fmt.Errorf("unable to get native architecture: %w", err)
|
||||
}
|
||||
arch = nativeArch
|
||||
}
|
||||
@@ -225,7 +231,7 @@ func findLastSyscalls(config *configs.Seccomp) (lastSyscallMap, error) {
|
||||
// Figure out native architecture representation of the architecture.
|
||||
nativeArch, err := archToNative(arch)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "cannot map architecture %v to AUDIT_ARCH_ constant", arch)
|
||||
return nil, fmt.Errorf("cannot map architecture %v to AUDIT_ARCH_ constant: %w", arch, err)
|
||||
}
|
||||
|
||||
if _, ok := lastSyscalls[nativeArch]; !ok {
|
||||
@@ -370,7 +376,7 @@ func generateEnosysStub(lastSyscalls lastSyscallMap) ([]bpf.Instruction, error)
|
||||
},
|
||||
}, sectionTail...)
|
||||
default:
|
||||
return nil, errors.Errorf("unknown amd64 native architecture %#x", scmpArch)
|
||||
return nil, fmt.Errorf("unknown amd64 native architecture %#x", scmpArch)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,16 +384,16 @@ func generateEnosysStub(lastSyscalls lastSyscallMap) ([]bpf.Instruction, error)
|
||||
case 2:
|
||||
// x32 and x86_64 are a unique case, we can't handle any others.
|
||||
if uint32(nativeArch) != uint32(C.C_AUDIT_ARCH_X86_64) {
|
||||
return nil, errors.Errorf("unknown architecture overlap on native arch %#x", nativeArch)
|
||||
return nil, fmt.Errorf("unknown architecture overlap on native arch %#x", nativeArch)
|
||||
}
|
||||
|
||||
x32sysno, ok := maxSyscalls[libseccomp.ArchX32]
|
||||
if !ok {
|
||||
return nil, errors.Errorf("missing %v in overlapping x86_64 arch: %v", libseccomp.ArchX32, maxSyscalls)
|
||||
return nil, fmt.Errorf("missing %v in overlapping x86_64 arch: %v", libseccomp.ArchX32, maxSyscalls)
|
||||
}
|
||||
x86sysno, ok := maxSyscalls[libseccomp.ArchAMD64]
|
||||
if !ok {
|
||||
return nil, errors.Errorf("missing %v in overlapping x86_64 arch: %v", libseccomp.ArchAMD64, maxSyscalls)
|
||||
return nil, fmt.Errorf("missing %v in overlapping x86_64 arch: %v", libseccomp.ArchAMD64, maxSyscalls)
|
||||
}
|
||||
|
||||
// The x32 ABI indicates that a syscall is being made by an x32
|
||||
@@ -448,7 +454,7 @@ func generateEnosysStub(lastSyscalls lastSyscallMap) ([]bpf.Instruction, error)
|
||||
}...)
|
||||
}
|
||||
default:
|
||||
return nil, errors.Errorf("invalid number of architecture overlaps: %v", len(maxSyscalls))
|
||||
return nil, fmt.Errorf("invalid number of architecture overlaps: %v", len(maxSyscalls))
|
||||
}
|
||||
|
||||
// Prepend this section to the tail.
|
||||
@@ -517,7 +523,7 @@ func generateEnosysStub(lastSyscalls lastSyscallMap) ([]bpf.Instruction, error)
|
||||
func assemble(program []bpf.Instruction) ([]unix.SockFilter, error) {
|
||||
rawProgram, err := bpf.Assemble(program)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "assembling program")
|
||||
return nil, fmt.Errorf("error assembling program: %w", err)
|
||||
}
|
||||
|
||||
// Convert to []unix.SockFilter for unix.SockFilter.
|
||||
@@ -547,11 +553,11 @@ func generatePatch(config *configs.Seccomp) ([]bpf.Instruction, error) {
|
||||
|
||||
lastSyscalls, err := findLastSyscalls(config)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "finding last syscalls for -ENOSYS stub")
|
||||
return nil, fmt.Errorf("error finding last syscalls for -ENOSYS stub: %w", err)
|
||||
}
|
||||
stubProgram, err := generateEnosysStub(lastSyscalls)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "generating -ENOSYS stub")
|
||||
return nil, fmt.Errorf("error generating -ENOSYS stub: %w", err)
|
||||
}
|
||||
return stubProgram, nil
|
||||
}
|
||||
@@ -559,12 +565,12 @@ func generatePatch(config *configs.Seccomp) ([]bpf.Instruction, error) {
|
||||
func enosysPatchFilter(config *configs.Seccomp, filter *libseccomp.ScmpFilter) ([]unix.SockFilter, error) {
|
||||
program, err := disassembleFilter(filter)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "disassembling original filter")
|
||||
return nil, fmt.Errorf("error disassembling original filter: %w", err)
|
||||
}
|
||||
|
||||
patch, err := generatePatch(config)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "generating patch for filter")
|
||||
return nil, fmt.Errorf("error generating patch for filter: %w", err)
|
||||
}
|
||||
fullProgram := append(patch, program...)
|
||||
|
||||
@@ -576,49 +582,61 @@ func enosysPatchFilter(config *configs.Seccomp, filter *libseccomp.ScmpFilter) (
|
||||
|
||||
fprog, err := assemble(fullProgram)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "assembling modified filter")
|
||||
return nil, fmt.Errorf("error assembling modified filter: %w", err)
|
||||
}
|
||||
return fprog, nil
|
||||
}
|
||||
|
||||
func filterFlags(filter *libseccomp.ScmpFilter) (flags uint, noNewPrivs bool, err error) {
|
||||
func filterFlags(config *configs.Seccomp, filter *libseccomp.ScmpFilter) (flags uint, noNewPrivs bool, err error) {
|
||||
// Ignore the error since pre-2.4 libseccomp is treated as API level 0.
|
||||
apiLevel, _ := libseccomp.GetApi()
|
||||
apiLevel, _ := libseccomp.GetAPI()
|
||||
|
||||
noNewPrivs, err = filter.GetNoNewPrivsBit()
|
||||
if err != nil {
|
||||
return 0, false, errors.Wrap(err, "fetch no_new_privs filter bit")
|
||||
return 0, false, fmt.Errorf("unable to fetch no_new_privs filter bit: %w", err)
|
||||
}
|
||||
|
||||
if apiLevel >= 3 {
|
||||
if logBit, err := filter.GetLogBit(); err != nil {
|
||||
return 0, false, errors.Wrap(err, "fetch SECCOMP_FILTER_FLAG_LOG bit")
|
||||
return 0, false, fmt.Errorf("unable to fetch SECCOMP_FILTER_FLAG_LOG bit: %w", err)
|
||||
} else if logBit {
|
||||
flags |= uint(C.C_FILTER_FLAG_LOG)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Support seccomp flags not yet added to libseccomp-golang...
|
||||
|
||||
for _, call := range config.Syscalls {
|
||||
if call.Action == configs.Notify {
|
||||
flags |= uint(C.C_FILTER_FLAG_NEW_LISTENER)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func sysSeccompSetFilter(flags uint, filter []unix.SockFilter) (err error) {
|
||||
func sysSeccompSetFilter(flags uint, filter []unix.SockFilter) (fd int, err error) {
|
||||
fprog := unix.SockFprog{
|
||||
Len: uint16(len(filter)),
|
||||
Filter: &filter[0],
|
||||
}
|
||||
fd = -1 // only return a valid fd when C_FILTER_FLAG_NEW_LISTENER is set
|
||||
// If no seccomp flags were requested we can use the old-school prctl(2).
|
||||
if flags == 0 {
|
||||
err = unix.Prctl(unix.PR_SET_SECCOMP,
|
||||
unix.SECCOMP_MODE_FILTER,
|
||||
uintptr(unsafe.Pointer(&fprog)), 0, 0)
|
||||
} else {
|
||||
_, _, errno := unix.RawSyscall(unix.SYS_SECCOMP,
|
||||
fdptr, _, errno := unix.RawSyscall(unix.SYS_SECCOMP,
|
||||
uintptr(C.C_SET_MODE_FILTER),
|
||||
uintptr(flags), uintptr(unsafe.Pointer(&fprog)))
|
||||
if errno != 0 {
|
||||
err = errno
|
||||
}
|
||||
if flags&uint(C.C_FILTER_FLAG_NEW_LISTENER) != 0 {
|
||||
fd = int(fdptr)
|
||||
}
|
||||
}
|
||||
runtime.KeepAlive(filter)
|
||||
runtime.KeepAlive(fprog)
|
||||
@@ -630,17 +648,17 @@ func sysSeccompSetFilter(flags uint, filter []unix.SockFilter) (err error) {
|
||||
// patches said filter to handle -ENOSYS in a much nicer manner than the
|
||||
// default libseccomp default action behaviour, and loads the patched filter
|
||||
// into the kernel for the current process.
|
||||
func PatchAndLoad(config *configs.Seccomp, filter *libseccomp.ScmpFilter) error {
|
||||
func PatchAndLoad(config *configs.Seccomp, filter *libseccomp.ScmpFilter) (int, error) {
|
||||
// Generate a patched filter.
|
||||
fprog, err := enosysPatchFilter(config, filter)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "patching filter")
|
||||
return -1, fmt.Errorf("error patching filter: %w", err)
|
||||
}
|
||||
|
||||
// Get the set of libseccomp flags set.
|
||||
seccompFlags, noNewPrivs, err := filterFlags(filter)
|
||||
seccompFlags, noNewPrivs, err := filterFlags(config, filter)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetch seccomp filter flags")
|
||||
return -1, fmt.Errorf("unable to fetch seccomp filter flags: %w", err)
|
||||
}
|
||||
|
||||
// Set no_new_privs if it was requested, though in runc we handle
|
||||
@@ -648,13 +666,15 @@ func PatchAndLoad(config *configs.Seccomp, filter *libseccomp.ScmpFilter) error
|
||||
if noNewPrivs {
|
||||
logrus.Warnf("potentially misconfigured filter -- setting no_new_privs in seccomp path")
|
||||
if err := unix.Prctl(unix.PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); err != nil {
|
||||
return errors.Wrap(err, "enable no_new_privs bit")
|
||||
return -1, fmt.Errorf("error enabling no_new_privs bit: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, load the filter.
|
||||
if err := sysSeccompSetFilter(seccompFlags, fprog); err != nil {
|
||||
return errors.Wrap(err, "loading seccomp filter")
|
||||
fd, err := sysSeccompSetFilter(seccompFlags, fprog)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf("error loading seccomp filter: %w", err)
|
||||
}
|
||||
return nil
|
||||
|
||||
return fd, nil
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build !linux || !cgo || !seccomp
|
||||
// +build !linux !cgo !seccomp
|
||||
|
||||
package patchbpf
|
||||
|
||||
111
vendor/github.com/opencontainers/runc/libcontainer/seccomp/seccomp_linux.go
generated
vendored
111
vendor/github.com/opencontainers/runc/libcontainer/seccomp/seccomp_linux.go
generated
vendored
@@ -1,4 +1,5 @@
|
||||
// +build linux,cgo,seccomp
|
||||
//go:build cgo && seccomp
|
||||
// +build cgo,seccomp
|
||||
|
||||
package seccomp
|
||||
|
||||
@@ -6,19 +7,16 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
libseccomp "github.com/seccomp/libseccomp-golang"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
"github.com/opencontainers/runc/libcontainer/seccomp/patchbpf"
|
||||
|
||||
libseccomp "github.com/seccomp/libseccomp-golang"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
var (
|
||||
actAllow = libseccomp.ActAllow
|
||||
actTrap = libseccomp.ActTrap
|
||||
actKill = libseccomp.ActKill
|
||||
actTrace = libseccomp.ActTrace.SetReturnCode(int16(unix.EPERM))
|
||||
actLog = libseccomp.ActLog
|
||||
actErrno = libseccomp.ActErrno.SetReturnCode(int16(unix.EPERM))
|
||||
)
|
||||
|
||||
@@ -27,77 +25,118 @@ const (
|
||||
syscallMaxArguments int = 6
|
||||
)
|
||||
|
||||
// Filters given syscalls in a container, preventing them from being used
|
||||
// Started in the container init process, and carried over to all child processes
|
||||
// Setns calls, however, require a separate invocation, as they are not children
|
||||
// of the init until they join the namespace
|
||||
func InitSeccomp(config *configs.Seccomp) error {
|
||||
// InitSeccomp installs the seccomp filters to be used in the container as
|
||||
// specified in config.
|
||||
// Returns the seccomp file descriptor if any of the filters include a
|
||||
// SCMP_ACT_NOTIFY action, otherwise returns -1.
|
||||
func InitSeccomp(config *configs.Seccomp) (int, error) {
|
||||
if config == nil {
|
||||
return errors.New("cannot initialize Seccomp - nil config passed")
|
||||
return -1, errors.New("cannot initialize Seccomp - nil config passed")
|
||||
}
|
||||
|
||||
defaultAction, err := getAction(config.DefaultAction, config.DefaultErrnoRet)
|
||||
if err != nil {
|
||||
return errors.New("error initializing seccomp - invalid default action")
|
||||
return -1, errors.New("error initializing seccomp - invalid default action")
|
||||
}
|
||||
|
||||
// Ignore the error since pre-2.4 libseccomp is treated as API level 0.
|
||||
apiLevel, _ := libseccomp.GetAPI()
|
||||
for _, call := range config.Syscalls {
|
||||
if call.Action == configs.Notify {
|
||||
if apiLevel < 6 {
|
||||
return -1, fmt.Errorf("seccomp notify unsupported: API level: got %d, want at least 6. Please try with libseccomp >= 2.5.0 and Linux >= 5.7", apiLevel)
|
||||
}
|
||||
|
||||
// We can't allow the write syscall to notify to the seccomp agent.
|
||||
// After InitSeccomp() is called, we need to syncParentSeccomp() to write the seccomp fd plain
|
||||
// number, so the parent sends it to the seccomp agent. If we use SCMP_ACT_NOTIFY on write, we
|
||||
// never can write the seccomp fd to the parent and therefore the seccomp agent never receives
|
||||
// the seccomp fd and runc is hang during initialization.
|
||||
//
|
||||
// Note that read()/close(), that are also used in syncParentSeccomp(), _can_ use SCMP_ACT_NOTIFY.
|
||||
// Because we write the seccomp fd on the pipe to the parent, the parent is able to proceed and
|
||||
// send the seccomp fd to the agent (it is another process and not subject to the seccomp
|
||||
// filter). We will be blocked on read()/close() inside syncParentSeccomp() but if the seccomp
|
||||
// agent allows those syscalls to proceed, initialization works just fine and the agent can
|
||||
// handle future read()/close() syscalls as it wanted.
|
||||
if call.Name == "write" {
|
||||
return -1, errors.New("SCMP_ACT_NOTIFY cannot be used for the write syscall")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See comment on why write is not allowed. The same reason applies, as this can mean handling write too.
|
||||
if defaultAction == libseccomp.ActNotify {
|
||||
return -1, errors.New("SCMP_ACT_NOTIFY cannot be used as default action")
|
||||
}
|
||||
|
||||
filter, err := libseccomp.NewFilter(defaultAction)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating filter: %s", err)
|
||||
return -1, fmt.Errorf("error creating filter: %w", err)
|
||||
}
|
||||
|
||||
// Add extra architectures
|
||||
for _, arch := range config.Architectures {
|
||||
scmpArch, err := libseccomp.GetArchFromString(arch)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error validating Seccomp architecture: %s", err)
|
||||
return -1, fmt.Errorf("error validating Seccomp architecture: %w", err)
|
||||
}
|
||||
if err := filter.AddArch(scmpArch); err != nil {
|
||||
return fmt.Errorf("error adding architecture to seccomp filter: %s", err)
|
||||
return -1, fmt.Errorf("error adding architecture to seccomp filter: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Unset no new privs bit
|
||||
if err := filter.SetNoNewPrivsBit(false); err != nil {
|
||||
return fmt.Errorf("error setting no new privileges: %s", err)
|
||||
return -1, fmt.Errorf("error setting no new privileges: %w", err)
|
||||
}
|
||||
|
||||
// Add a rule for each syscall
|
||||
for _, call := range config.Syscalls {
|
||||
if call == nil {
|
||||
return errors.New("encountered nil syscall while initializing Seccomp")
|
||||
return -1, errors.New("encountered nil syscall while initializing Seccomp")
|
||||
}
|
||||
|
||||
if err := matchCall(filter, call, defaultAction); err != nil {
|
||||
return err
|
||||
return -1, err
|
||||
}
|
||||
}
|
||||
if err := patchbpf.PatchAndLoad(config, filter); err != nil {
|
||||
return fmt.Errorf("error loading seccomp filter into kernel: %s", err)
|
||||
|
||||
seccompFd, err := patchbpf.PatchAndLoad(config, filter)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf("error loading seccomp filter into kernel: %w", err)
|
||||
}
|
||||
return nil
|
||||
|
||||
return seccompFd, nil
|
||||
}
|
||||
|
||||
// Convert Libcontainer Action to Libseccomp ScmpAction
|
||||
func getAction(act configs.Action, errnoRet *uint) (libseccomp.ScmpAction, error) {
|
||||
switch act {
|
||||
case configs.Kill:
|
||||
return actKill, nil
|
||||
return libseccomp.ActKill, nil
|
||||
case configs.Errno:
|
||||
if errnoRet != nil {
|
||||
return libseccomp.ActErrno.SetReturnCode(int16(*errnoRet)), nil
|
||||
}
|
||||
return actErrno, nil
|
||||
case configs.Trap:
|
||||
return actTrap, nil
|
||||
return libseccomp.ActTrap, nil
|
||||
case configs.Allow:
|
||||
return actAllow, nil
|
||||
return libseccomp.ActAllow, nil
|
||||
case configs.Trace:
|
||||
if errnoRet != nil {
|
||||
return libseccomp.ActTrace.SetReturnCode(int16(*errnoRet)), nil
|
||||
}
|
||||
return actTrace, nil
|
||||
case configs.Log:
|
||||
return actLog, nil
|
||||
return libseccomp.ActLog, nil
|
||||
case configs.Notify:
|
||||
return libseccomp.ActNotify, nil
|
||||
case configs.KillThread:
|
||||
return libseccomp.ActKillThread, nil
|
||||
case configs.KillProcess:
|
||||
return libseccomp.ActKillProcess, nil
|
||||
default:
|
||||
return libseccomp.ActInvalid, errors.New("invalid action, cannot use in rule")
|
||||
}
|
||||
@@ -162,17 +201,18 @@ func matchCall(filter *libseccomp.ScmpFilter, call *configs.Syscall, defAct libs
|
||||
return nil
|
||||
}
|
||||
|
||||
// If we can't resolve the syscall, assume it's not supported on this kernel
|
||||
// Ignore it, don't error out
|
||||
// If we can't resolve the syscall, assume it is not supported
|
||||
// by this kernel. Warn about it, don't error out.
|
||||
callNum, err := libseccomp.GetSyscallFromName(call.Name)
|
||||
if err != nil {
|
||||
logrus.Debugf("unknown seccomp syscall %q ignored", call.Name)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unconditional match - just add the rule
|
||||
if len(call.Args) == 0 {
|
||||
if err := filter.AddRule(callNum, callAct); err != nil {
|
||||
return fmt.Errorf("error adding seccomp filter rule for syscall %s: %s", call.Name, err)
|
||||
return fmt.Errorf("error adding seccomp filter rule for syscall %s: %w", call.Name, err)
|
||||
}
|
||||
} else {
|
||||
// If two or more arguments have the same condition,
|
||||
@@ -183,7 +223,7 @@ func matchCall(filter *libseccomp.ScmpFilter, call *configs.Syscall, defAct libs
|
||||
for _, cond := range call.Args {
|
||||
newCond, err := getCondition(cond)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating seccomp syscall condition for syscall %s: %s", call.Name, err)
|
||||
return fmt.Errorf("error creating seccomp syscall condition for syscall %s: %w", call.Name, err)
|
||||
}
|
||||
|
||||
argCounts[cond.Index] += 1
|
||||
@@ -206,14 +246,14 @@ func matchCall(filter *libseccomp.ScmpFilter, call *configs.Syscall, defAct libs
|
||||
condArr := []libseccomp.ScmpCondition{cond}
|
||||
|
||||
if err := filter.AddRuleConditional(callNum, callAct, condArr); err != nil {
|
||||
return fmt.Errorf("error adding seccomp rule for syscall %s: %s", call.Name, err)
|
||||
return fmt.Errorf("error adding seccomp rule for syscall %s: %w", call.Name, err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No conditions share same argument
|
||||
// Use new, proper behavior
|
||||
if err := filter.AddRuleConditional(callNum, callAct, conditions); err != nil {
|
||||
return fmt.Errorf("error adding seccomp rule for syscall %s: %s", call.Name, err)
|
||||
return fmt.Errorf("error adding seccomp rule for syscall %s: %w", call.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,3 +265,6 @@ func matchCall(filter *libseccomp.ScmpFilter, call *configs.Syscall, defAct libs
|
||||
func Version() (uint, uint, uint) {
|
||||
return libseccomp.GetLibraryVersion()
|
||||
}
|
||||
|
||||
// Enabled is true if seccomp support is compiled in.
|
||||
const Enabled = true
|
||||
|
||||
10
vendor/github.com/opencontainers/runc/libcontainer/seccomp/seccomp_unsupported.go
generated
vendored
10
vendor/github.com/opencontainers/runc/libcontainer/seccomp/seccomp_unsupported.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build !linux || !cgo || !seccomp
|
||||
// +build !linux !cgo !seccomp
|
||||
|
||||
package seccomp
|
||||
@@ -11,14 +12,17 @@ import (
|
||||
var ErrSeccompNotEnabled = errors.New("seccomp: config provided but seccomp not supported")
|
||||
|
||||
// InitSeccomp does nothing because seccomp is not supported.
|
||||
func InitSeccomp(config *configs.Seccomp) error {
|
||||
func InitSeccomp(config *configs.Seccomp) (int, error) {
|
||||
if config != nil {
|
||||
return ErrSeccompNotEnabled
|
||||
return -1, ErrSeccompNotEnabled
|
||||
}
|
||||
return nil
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
// Version returns major, minor, and micro.
|
||||
func Version() (uint, uint, uint) {
|
||||
return 0, 0, 0
|
||||
}
|
||||
|
||||
// Enabled is true if seccomp support is compiled in.
|
||||
const Enabled = false
|
||||
|
||||
Reference in New Issue
Block a user