Switch to containers/common for seccomp

The seccomp/containers-golang library is not maintained any more and we
should stick to containers/common.

Signed-off-by: Sascha Grunert <sgrunert@suse.com>
This commit is contained in:
Sascha Grunert
2020-08-27 21:14:55 +02:00
parent 72c5b35ea5
commit 98ead36531
48 changed files with 2604 additions and 221 deletions

5
go.mod
View File

@ -11,11 +11,11 @@ require (
github.com/containernetworking/cni v0.7.2-0.20200304161608-4fae32b84921 github.com/containernetworking/cni v0.7.2-0.20200304161608-4fae32b84921
github.com/containernetworking/plugins v0.8.6 github.com/containernetworking/plugins v0.8.6
github.com/containers/buildah v1.15.1-0.20200813183340-0a8dc1f8064c github.com/containers/buildah v1.15.1-0.20200813183340-0a8dc1f8064c
github.com/containers/common v0.20.3 github.com/containers/common v0.20.3-0.20200827091701-a550d6a98aa3
github.com/containers/conmon v2.0.19+incompatible github.com/containers/conmon v2.0.19+incompatible
github.com/containers/image/v5 v5.5.2 github.com/containers/image/v5 v5.5.2
github.com/containers/psgo v1.5.1 github.com/containers/psgo v1.5.1
github.com/containers/storage v1.23.0 github.com/containers/storage v1.23.2
github.com/coreos/go-systemd/v22 v22.1.0 github.com/coreos/go-systemd/v22 v22.1.0
github.com/cri-o/ocicni v0.2.0 github.com/cri-o/ocicni v0.2.0
github.com/cyphar/filepath-securejoin v0.2.2 github.com/cyphar/filepath-securejoin v0.2.2
@ -47,7 +47,6 @@ require (
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
github.com/rootless-containers/rootlesskit v0.10.0 github.com/rootless-containers/rootlesskit v0.10.0
github.com/seccomp/containers-golang v0.6.0
github.com/sirupsen/logrus v1.6.0 github.com/sirupsen/logrus v1.6.0
github.com/spf13/cobra v0.0.7 github.com/spf13/cobra v0.0.7
github.com/spf13/pflag v1.0.5 github.com/spf13/pflag v1.0.5

10
go.sum
View File

@ -73,8 +73,8 @@ github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHV
github.com/containers/buildah v1.15.1-0.20200813183340-0a8dc1f8064c h1:elGbJcB3UjBdk7fBxfAzUNS3IT288U1Dzm0gmhgsnB8= github.com/containers/buildah v1.15.1-0.20200813183340-0a8dc1f8064c h1:elGbJcB3UjBdk7fBxfAzUNS3IT288U1Dzm0gmhgsnB8=
github.com/containers/buildah v1.15.1-0.20200813183340-0a8dc1f8064c/go.mod h1:+IklBLPix5wxPEWn26aDay5f5q4A5VtmNjkdyK5YVsI= github.com/containers/buildah v1.15.1-0.20200813183340-0a8dc1f8064c/go.mod h1:+IklBLPix5wxPEWn26aDay5f5q4A5VtmNjkdyK5YVsI=
github.com/containers/common v0.19.0/go.mod h1:+NUHV8V5Kmo260ja9Dxtr8ialrDnK4RNzyeEbSgmLac= github.com/containers/common v0.19.0/go.mod h1:+NUHV8V5Kmo260ja9Dxtr8ialrDnK4RNzyeEbSgmLac=
github.com/containers/common v0.20.3 h1:d8vSReNkrySKE3ZPya2vt6Wc/xuQiB30pNXTYHz2iHM= github.com/containers/common v0.20.3-0.20200827091701-a550d6a98aa3 h1:rTSiIMOH3fbCBN+2L8Xr9BJ19AejEIaBQvzkAXZCz/k=
github.com/containers/common v0.20.3/go.mod h1:+NUHV8V5Kmo260ja9Dxtr8ialrDnK4RNzyeEbSgmLac= github.com/containers/common v0.20.3-0.20200827091701-a550d6a98aa3/go.mod h1:z5HJtHWU8sopAHO0Od5s9EpVkXPrLIcNszVvN1Fc3fQ=
github.com/containers/conmon v2.0.19+incompatible h1:1bDVRvHy2MUNTUT/SW6LlHsJHQBTSwXvnKNdcB/a1vQ= github.com/containers/conmon v2.0.19+incompatible h1:1bDVRvHy2MUNTUT/SW6LlHsJHQBTSwXvnKNdcB/a1vQ=
github.com/containers/conmon v2.0.19+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/conmon v2.0.19+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/image/v5 v5.5.1/go.mod h1:4PyNYR0nwlGq/ybVJD9hWlhmIsNra4Q8uOQX2s6E2uM= github.com/containers/image/v5 v5.5.1/go.mod h1:4PyNYR0nwlGq/ybVJD9hWlhmIsNra4Q8uOQX2s6E2uM=
@ -90,6 +90,8 @@ github.com/containers/psgo v1.5.1/go.mod h1:2ubh0SsreMZjSXW1Hif58JrEcFudQyIy9EzP
github.com/containers/storage v1.20.2/go.mod h1:oOB9Ie8OVPojvoaKWEGSEtHbXUAs+tSyr7RO7ZGteMc= github.com/containers/storage v1.20.2/go.mod h1:oOB9Ie8OVPojvoaKWEGSEtHbXUAs+tSyr7RO7ZGteMc=
github.com/containers/storage v1.23.0 h1:gYyNkBiihC2FvGiHOjOjpnfojYwgxpLVooTUlmD6pxs= github.com/containers/storage v1.23.0 h1:gYyNkBiihC2FvGiHOjOjpnfojYwgxpLVooTUlmD6pxs=
github.com/containers/storage v1.23.0/go.mod h1:I1EIAA7B4OwWRSA0b4yq2AW1wjvvfcY0zLWQuwTa4zw= github.com/containers/storage v1.23.0/go.mod h1:I1EIAA7B4OwWRSA0b4yq2AW1wjvvfcY0zLWQuwTa4zw=
github.com/containers/storage v1.23.2 h1:GPZ8PXYezML1gmZ/uFaXQpyps7AH645lmdvvOJwJYNc=
github.com/containers/storage v1.23.2/go.mod h1:AyTMMiE5ANvZJiqvatQgSZ85wAl5yHucY3NDN/kemr4=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-iptables v0.4.5 h1:DpHb9vJrZQEFMcVLFKAAGMUVX0XoRC0ptCthinRYm38= github.com/coreos/go-iptables v0.4.5 h1:DpHb9vJrZQEFMcVLFKAAGMUVX0XoRC0ptCthinRYm38=
@ -259,6 +261,8 @@ github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
github.com/klauspost/compress v1.10.8/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.10.8/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.10.10 h1:a/y8CglcM7gLGYmlbP/stPE5sR3hbhFRUjCBfd/0B3I= github.com/klauspost/compress v1.10.10 h1:a/y8CglcM7gLGYmlbP/stPE5sR3hbhFRUjCBfd/0B3I=
github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.10.11 h1:K9z59aO18Aywg2b/WSgBaUX99mHy2BES18Cr5lBKZHk=
github.com/klauspost/compress v1.10.11/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/pgzip v1.2.4 h1:TQ7CNpYKovDOmqzRHKxJh0BeaBI7UdQZYc6p7pMQh1A= github.com/klauspost/pgzip v1.2.4 h1:TQ7CNpYKovDOmqzRHKxJh0BeaBI7UdQZYc6p7pMQh1A=
github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@ -400,6 +404,8 @@ github.com/seccomp/containers-golang v0.6.0 h1:VWPMMIDr8pAtNjCX0WvLEEK9EQi5lAm4H
github.com/seccomp/containers-golang v0.6.0/go.mod h1:Dd9mONHvW4YdbSzdm23yf2CFw0iqvqLhO0mEFvPIvm4= github.com/seccomp/containers-golang v0.6.0/go.mod h1:Dd9mONHvW4YdbSzdm23yf2CFw0iqvqLhO0mEFvPIvm4=
github.com/seccomp/libseccomp-golang v0.9.1 h1:NJjM5DNFOs0s3kYE1WUOr6G8V97sdt46rlXTMfXGWBo= github.com/seccomp/libseccomp-golang v0.9.1 h1:NJjM5DNFOs0s3kYE1WUOr6G8V97sdt46rlXTMfXGWBo=
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
github.com/seccomp/libseccomp-golang v0.9.2-0.20200616122406-847368b35ebf h1:b0+ZBD3rohnkQ4q5duD1+RyTXTg9yk+qTOPMSQtapO0=
github.com/seccomp/libseccomp-golang v0.9.2-0.20200616122406-847368b35ebf/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v0.0.0-20190403091019-9b3cdde74fbe/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v0.0.0-20190403091019-9b3cdde74fbe/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=

View File

@ -5,10 +5,10 @@ package createconfig
import ( import (
"io/ioutil" "io/ioutil"
goSeccomp "github.com/containers/common/pkg/seccomp"
"github.com/containers/podman/v2/pkg/seccomp" "github.com/containers/podman/v2/pkg/seccomp"
spec "github.com/opencontainers/runtime-spec/specs-go" spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors" "github.com/pkg/errors"
goSeccomp "github.com/seccomp/containers-golang"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )

View File

@ -6,12 +6,12 @@ import (
"context" "context"
"io/ioutil" "io/ioutil"
goSeccomp "github.com/containers/common/pkg/seccomp"
"github.com/containers/podman/v2/libpod/image" "github.com/containers/podman/v2/libpod/image"
"github.com/containers/podman/v2/pkg/seccomp" "github.com/containers/podman/v2/pkg/seccomp"
"github.com/containers/podman/v2/pkg/specgen" "github.com/containers/podman/v2/pkg/specgen"
spec "github.com/opencontainers/runtime-spec/specs-go" spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors" "github.com/pkg/errors"
goSeccomp "github.com/seccomp/containers-golang"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )

View File

@ -13,6 +13,7 @@ import (
"strings" "strings"
"text/template" "text/template"
"github.com/containers/common/pkg/apparmor/internal/supported"
"github.com/containers/storage/pkg/unshare" "github.com/containers/storage/pkg/unshare"
runcaa "github.com/opencontainers/runc/libcontainer/apparmor" runcaa "github.com/opencontainers/runc/libcontainer/apparmor"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -22,12 +23,11 @@ import (
// profileDirectory is the file store for apparmor profiles and macros. // profileDirectory is the file store for apparmor profiles and macros.
var profileDirectory = "/etc/apparmor.d" var profileDirectory = "/etc/apparmor.d"
// IsEnabled returns true if AppArmor is enabled on the host. // IsEnabled returns true if AppArmor is enabled on the host. It also checks
// for the existence of the `apparmor_parser` binary, which will be required to
// apply profiles.
func IsEnabled() bool { func IsEnabled() bool {
if unshare.IsRootless() { return supported.NewAppArmorVerifier().IsSupported() == nil
return false
}
return runcaa.IsEnabled()
} }
// profileData holds information about the given profile for generation. // profileData holds information about the given profile for generation.
@ -43,7 +43,7 @@ type profileData struct {
} }
// generateDefault creates an apparmor profile from ProfileData. // generateDefault creates an apparmor profile from ProfileData.
func (p *profileData) generateDefault(out io.Writer) error { func (p *profileData) generateDefault(apparmorParserPath string, out io.Writer) error {
compiled, err := template.New("apparmor_profile").Parse(defaultProfileTemplate) compiled, err := template.New("apparmor_profile").Parse(defaultProfileTemplate)
if err != nil { if err != nil {
return errors.Wrap(err, "create AppArmor profile from template") return errors.Wrap(err, "create AppArmor profile from template")
@ -59,7 +59,7 @@ func (p *profileData) generateDefault(out io.Writer) error {
p.InnerImports = append(p.InnerImports, "#include <abstractions/base>") p.InnerImports = append(p.InnerImports, "#include <abstractions/base>")
} }
ver, err := getAAParserVersion() ver, err := getAAParserVersion(apparmorParserPath)
if err != nil { if err != nil {
return errors.Wrap(err, "get AppArmor version") return errors.Wrap(err, "get AppArmor version")
} }
@ -85,18 +85,23 @@ func InstallDefault(name string) error {
Name: name, Name: name,
} }
cmd := exec.Command("apparmor_parser", "-Kr") apparmorParserPath, err := supported.NewAppArmorVerifier().FindAppArmorParserBinary()
if err != nil {
return errors.Wrap(err, "find `apparmor_parser` binary")
}
cmd := exec.Command(apparmorParserPath, "-Kr")
pipe, err := cmd.StdinPipe() pipe, err := cmd.StdinPipe()
if err != nil { if err != nil {
return errors.Wrap(err, "execute apparmor_parser") return errors.Wrapf(err, "execute %s", apparmorParserPath)
} }
if err := cmd.Start(); err != nil { if err := cmd.Start(); err != nil {
if pipeErr := pipe.Close(); pipeErr != nil { if pipeErr := pipe.Close(); pipeErr != nil {
logrus.Errorf("unable to close AppArmor pipe: %q", pipeErr) logrus.Errorf("unable to close AppArmor pipe: %q", pipeErr)
} }
return errors.Wrap(err, "start apparmor_parser command") return errors.Wrapf(err, "start %s command", apparmorParserPath)
} }
if err := p.generateDefault(pipe); err != nil { if err := p.generateDefault(apparmorParserPath, pipe); err != nil {
if pipeErr := pipe.Close(); pipeErr != nil { if pipeErr := pipe.Close(); pipeErr != nil {
logrus.Errorf("unable to close AppArmor pipe: %q", pipeErr) logrus.Errorf("unable to close AppArmor pipe: %q", pipeErr)
} }
@ -118,11 +123,17 @@ func InstallDefault(name string) error {
// generation fails. // generation fails.
func DefaultContent(name string) ([]byte, error) { func DefaultContent(name string) ([]byte, error) {
p := profileData{Name: name} p := profileData{Name: name}
var bytes bytes.Buffer buffer := &bytes.Buffer{}
if err := p.generateDefault(&bytes); err != nil {
apparmorParserPath, err := supported.NewAppArmorVerifier().FindAppArmorParserBinary()
if err != nil {
return nil, errors.Wrap(err, "find `apparmor_parser` binary")
}
if err := p.generateDefault(apparmorParserPath, buffer); err != nil {
return nil, errors.Wrap(err, "generate default AppAmor profile") return nil, errors.Wrap(err, "generate default AppAmor profile")
} }
return bytes.Bytes(), nil return buffer.Bytes(), nil
} }
// IsLoaded checks if a profile with the given name has been loaded into the // IsLoaded checks if a profile with the given name has been loaded into the
@ -159,8 +170,8 @@ func IsLoaded(name string) (bool, error) {
} }
// execAAParser runs `apparmor_parser` with the passed arguments. // execAAParser runs `apparmor_parser` with the passed arguments.
func execAAParser(dir string, args ...string) (string, error) { func execAAParser(apparmorParserPath, dir string, args ...string) (string, error) {
c := exec.Command("apparmor_parser", args...) c := exec.Command(apparmorParserPath, args...)
c.Dir = dir c.Dir = dir
output, err := c.Output() output, err := c.Output()
@ -172,8 +183,8 @@ func execAAParser(dir string, args ...string) (string, error) {
} }
// getAAParserVersion returns the major and minor version of apparmor_parser. // getAAParserVersion returns the major and minor version of apparmor_parser.
func getAAParserVersion() (int, error) { func getAAParserVersion(apparmorParserPath string) (int, error) {
output, err := execAAParser("", "--version") output, err := execAAParser(apparmorParserPath, "", "--version")
if err != nil { if err != nil {
return -1, errors.Wrap(err, "execute apparmor_parser") return -1, errors.Wrap(err, "execute apparmor_parser")
} }

View File

@ -0,0 +1,113 @@
package supported
import (
"os"
"os/exec"
"path/filepath"
"sync"
"github.com/containers/storage/pkg/unshare"
runcaa "github.com/opencontainers/runc/libcontainer/apparmor"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate
// ApparmorVerifier is the global struct for verifying if AppAmor is available
// on the system.
type ApparmorVerifier struct {
impl verifierImpl
parserBinaryPath string
}
var (
singleton *ApparmorVerifier
once sync.Once
)
// NewAppArmorVerifier can be used to retrieve a new ApparmorVerifier instance.
func NewAppArmorVerifier() *ApparmorVerifier {
once.Do(func() {
singleton = &ApparmorVerifier{impl: &defaultVerifier{}}
})
return singleton
}
// IsSupported returns nil if AppAmor is supported by the host system.
// The method will error if:
// - the process runs in rootless mode
// - AppArmor is disabled by the host system
// - the `apparmor_parser` binary is not discoverable
func (a *ApparmorVerifier) IsSupported() error {
if a.impl.UnshareIsRootless() {
return errors.New("AppAmor is not supported on rootless containers")
}
if !a.impl.RuncIsEnabled() {
return errors.New("AppArmor not supported by the host system")
}
_, err := a.FindAppArmorParserBinary()
return err
}
// FindAppArmorParserBinary returns the `apparmor_parser` binary either from
// `/sbin` or from `$PATH`. It returns an error if the binary could not be
// found.
func (a *ApparmorVerifier) FindAppArmorParserBinary() (string, error) {
// Use the memoized path if available
if a.parserBinaryPath != "" {
logrus.Debugf("Using %s binary", a.parserBinaryPath)
return a.parserBinaryPath, nil
}
const (
binary = "apparmor_parser"
sbin = "/sbin"
)
// `/sbin` is not always in `$PATH`, so we check it explicitly
sbinBinaryPath := filepath.Join(sbin, binary)
if _, err := a.impl.OsStat(sbinBinaryPath); err == nil {
logrus.Debugf("Found %s binary in %s", binary, sbinBinaryPath)
a.parserBinaryPath = sbinBinaryPath
return sbinBinaryPath, nil
}
// Fallback to checking $PATH
if path, err := a.impl.ExecLookPath(binary); err == nil {
logrus.Debugf("Found %s binary in %s", binary, path)
a.parserBinaryPath = path
return path, nil
}
return "", errors.Errorf(
"%s binary neither found in %s nor $PATH", binary, sbin,
)
}
//counterfeiter:generate . verifierImpl
type verifierImpl interface {
UnshareIsRootless() bool
RuncIsEnabled() bool
OsStat(name string) (os.FileInfo, error)
ExecLookPath(file string) (string, error)
}
type defaultVerifier struct{}
func (d *defaultVerifier) UnshareIsRootless() bool {
return unshare.IsRootless()
}
func (d *defaultVerifier) RuncIsEnabled() bool {
return runcaa.IsEnabled()
}
func (d *defaultVerifier) OsStat(name string) (os.FileInfo, error) {
return os.Stat(name)
}
func (d *defaultVerifier) ExecLookPath(file string) (string, error) {
return exec.LookPath(file)
}

View File

@ -40,8 +40,8 @@ func CheckAuthFile(authfile string) error {
// data with the original parameter. // data with the original parameter.
func systemContextWithOptions(sys *types.SystemContext, authFile, certDir string) *types.SystemContext { func systemContextWithOptions(sys *types.SystemContext, authFile, certDir string) *types.SystemContext {
if sys != nil { if sys != nil {
copy := *sys sysCopy := *sys
sys = &copy sys = &sysCopy
} else { } else {
sys = &types.SystemContext{} sys = &types.SystemContext{}
} }
@ -126,7 +126,7 @@ func Login(ctx context.Context, systemContext *types.SystemContext, opts *LoginO
if err = docker.CheckAuth(ctx, systemContext, username, password, server); err == nil { if err = docker.CheckAuth(ctx, systemContext, username, password, server); err == nil {
// Write the new credentials to the authfile // Write the new credentials to the authfile
if err = config.SetAuthentication(systemContext, server, username, password); err != nil { if err := config.SetAuthentication(systemContext, server, username, password); err != nil {
return err return err
} }
} }
@ -156,8 +156,7 @@ func getRegistryName(server string) string {
// getUserAndPass gets the username and password from STDIN if not given // getUserAndPass gets the username and password from STDIN if not given
// using the -u and -p flags. If the username prompt is left empty, the // using the -u and -p flags. If the username prompt is left empty, the
// displayed userFromAuthFile will be used instead. // displayed userFromAuthFile will be used instead.
func getUserAndPass(opts *LoginOptions, password, userFromAuthFile string) (string, string, error) { func getUserAndPass(opts *LoginOptions, password, userFromAuthFile string) (user, pass string, err error) {
var err error
reader := bufio.NewReader(opts.Stdin) reader := bufio.NewReader(opts.Stdin)
username := opts.Username username := opts.Username
if username == "" { if username == "" {

View File

@ -612,11 +612,11 @@ func (c *ContainersConfig) Validate() error {
} }
if c.LogSizeMax >= 0 && c.LogSizeMax < OCIBufSize { if c.LogSizeMax >= 0 && c.LogSizeMax < OCIBufSize {
return fmt.Errorf("log size max should be negative or >= %d", OCIBufSize) return errors.Errorf("log size max should be negative or >= %d", OCIBufSize)
} }
if _, err := units.FromHumanSize(c.ShmSize); err != nil { if _, err := units.FromHumanSize(c.ShmSize); err != nil {
return fmt.Errorf("invalid --shm-size %s, %q", c.ShmSize, err) return errors.Errorf("invalid --shm-size %s, %q", c.ShmSize, err)
} }
return nil return nil
@ -759,15 +759,13 @@ func (c *Config) Capabilities(user string, addCapabilities, dropCapabilities []s
// '/dev/sdc:/dev/xvdc" // '/dev/sdc:/dev/xvdc"
// '/dev/sdc:/dev/xvdc:rwm" // '/dev/sdc:/dev/xvdc:rwm"
// '/dev/sdc:rm" // '/dev/sdc:rm"
func Device(device string) (string, string, string, error) { func Device(device string) (src, dst, permissions string, err error) {
src := "" permissions = "rwm"
dst := ""
permissions := "rwm"
split := strings.Split(device, ":") split := strings.Split(device, ":")
switch len(split) { switch len(split) {
case 3: case 3:
if !IsValidDeviceMode(split[2]) { if !IsValidDeviceMode(split[2]) {
return "", "", "", fmt.Errorf("invalid device mode: %s", split[2]) return "", "", "", errors.Errorf("invalid device mode: %s", split[2])
} }
permissions = split[2] permissions = split[2]
fallthrough fallthrough
@ -775,19 +773,19 @@ func Device(device string) (string, string, string, error) {
if IsValidDeviceMode(split[1]) { if IsValidDeviceMode(split[1]) {
permissions = split[1] permissions = split[1]
} else { } else {
if len(split[1]) == 0 || split[1][0] != '/' { if split[1] == "" || split[1][0] != '/' {
return "", "", "", fmt.Errorf("invalid device mode: %s", split[1]) return "", "", "", errors.Errorf("invalid device mode: %s", split[1])
} }
dst = split[1] dst = split[1]
} }
fallthrough fallthrough
case 1: case 1:
if !strings.HasPrefix(split[0], "/dev/") { if !strings.HasPrefix(split[0], "/dev/") {
return "", "", "", fmt.Errorf("invalid device mode: %s", split[0]) return "", "", "", errors.Errorf("invalid device mode: %s", split[0])
} }
src = split[0] src = split[0]
default: default:
return "", "", "", fmt.Errorf("invalid device specification: %s", device) return "", "", "", errors.Errorf("invalid device specification: %s", device)
} }
if dst == "" { if dst == "" {
@ -908,21 +906,6 @@ func Path() string {
return OverrideContainersConfig return OverrideContainersConfig
} }
func customConfigFile() (string, error) {
path := os.Getenv("CONTAINERS_CONF")
if path != "" {
return path, nil
}
if unshare.IsRootless() {
path, err := rootlessConfigPath()
if err != nil {
return "", err
}
return path, nil
}
return OverrideContainersConfig, nil
}
// ReadCustomConfig reads the custom config and only generates a config based on it // ReadCustomConfig reads the custom config and only generates a config based on it
// If the custom config file does not exists, function will return an empty config // If the custom config file does not exists, function will return an empty config
func ReadCustomConfig() (*Config, error) { func ReadCustomConfig() (*Config, error) {
@ -943,7 +926,7 @@ func ReadCustomConfig() (*Config, error) {
newConfig := &Config{} newConfig := &Config{}
if _, err := os.Stat(path); err == nil { if _, err := os.Stat(path); err == nil {
if err = readConfigFromFile(path, newConfig); err != nil { if err := readConfigFromFile(path, newConfig); err != nil {
return nil, err return nil, err
} }
} else { } else {
@ -990,13 +973,12 @@ func Reload() (*Config, error) {
return defConfig() return defConfig()
} }
func (c *Config) ActiveDestination() (string, string, error) { func (c *Config) ActiveDestination() (uri, identity string, err error) {
if uri, found := os.LookupEnv("CONTAINER_HOST"); found { if uri, found := os.LookupEnv("CONTAINER_HOST"); found {
var ident string
if v, found := os.LookupEnv("CONTAINER_SSHKEY"); found { if v, found := os.LookupEnv("CONTAINER_SSHKEY"); found {
ident = v identity = v
} }
return uri, ident, nil return uri, identity, nil
} }
switch { switch {

View File

@ -0,0 +1,12 @@
package config
import (
"os"
)
func customConfigFile() (string, error) {
if path, found := os.LookupEnv("CONTAINERS_CONF"); found {
return path, nil
}
return rootlessConfigPath()
}

View File

@ -1,7 +1,26 @@
package config package config
import selinux "github.com/opencontainers/selinux/go-selinux" import (
"os"
"github.com/containers/storage/pkg/unshare"
selinux "github.com/opencontainers/selinux/go-selinux"
)
func selinuxEnabled() bool { func selinuxEnabled() bool {
return selinux.GetEnabled() return selinux.GetEnabled()
} }
func customConfigFile() (string, error) {
if path, found := os.LookupEnv("CONTAINERS_CONF"); found {
return path, nil
}
if unshare.IsRootless() {
path, err := rootlessConfigPath()
if err != nil {
return "", err
}
return path, nil
}
return OverrideContainersConfig, nil
}

View File

@ -3,7 +3,6 @@
package config package config
import ( import (
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
@ -11,6 +10,7 @@ import (
"syscall" "syscall"
units "github.com/docker/go-units" units "github.com/docker/go-units"
"github.com/pkg/errors"
) )
// isDirectory tests whether the given path exists and is a directory. It // isDirectory tests whether the given path exists and is a directory. It
@ -43,13 +43,13 @@ func (c *EngineConfig) validatePaths() error {
// shift between runs or even parts of the program. - The OCI runtime // shift between runs or even parts of the program. - The OCI runtime
// uses a different working directory than we do, for example. // uses a different working directory than we do, for example.
if c.StaticDir != "" && !filepath.IsAbs(c.StaticDir) { if c.StaticDir != "" && !filepath.IsAbs(c.StaticDir) {
return fmt.Errorf("static directory must be an absolute path - instead got %q", c.StaticDir) return errors.Errorf("static directory must be an absolute path - instead got %q", c.StaticDir)
} }
if c.TmpDir != "" && !filepath.IsAbs(c.TmpDir) { if c.TmpDir != "" && !filepath.IsAbs(c.TmpDir) {
return fmt.Errorf("temporary directory must be an absolute path - instead got %q", c.TmpDir) return errors.Errorf("temporary directory must be an absolute path - instead got %q", c.TmpDir)
} }
if c.VolumePath != "" && !filepath.IsAbs(c.VolumePath) { if c.VolumePath != "" && !filepath.IsAbs(c.VolumePath) {
return fmt.Errorf("volume path must be an absolute path - instead got %q", c.VolumePath) return errors.Errorf("volume path must be an absolute path - instead got %q", c.VolumePath)
} }
return nil return nil
} }
@ -68,7 +68,7 @@ func (c *ContainersConfig) validateUlimits() error {
for _, u := range c.DefaultUlimits { for _, u := range c.DefaultUlimits {
ul, err := units.ParseUlimit(u) ul, err := units.ParseUlimit(u)
if err != nil { if err != nil {
return fmt.Errorf("unrecognized ulimit %s: %v", u, err) return errors.Wrapf(err, "unrecognized ulimit %s", u)
} }
_, err = ul.GetRlimit() _, err = ul.GetRlimit()
if err != nil { if err != nil {
@ -96,8 +96,8 @@ func (c *ContainersConfig) validateTZ() error {
} }
} }
return fmt.Errorf( return errors.Errorf(
"unable to find timezone %s in paths: %s", "find timezone %s in paths: %s",
c.TZ, strings.Join(lookupPaths, ", "), c.TZ, strings.Join(lookupPaths, ", "),
) )
} }
@ -105,7 +105,7 @@ func (c *ContainersConfig) validateTZ() error {
func (c *ContainersConfig) validateUmask() error { func (c *ContainersConfig) validateUmask() error {
validUmask := regexp.MustCompile(`^[0-7]{1,4}$`) validUmask := regexp.MustCompile(`^[0-7]{1,4}$`)
if !validUmask.MatchString(c.Umask) { if !validUmask.MatchString(c.Umask) {
return fmt.Errorf("Not a valid Umask %s", c.Umask) return errors.Errorf("not a valid umask %s", c.Umask)
} }
return nil return nil
} }

View File

@ -0,0 +1,10 @@
package config
import "os"
func customConfigFile() (string, error) {
if path, found := os.LookupEnv("CONTAINERS_CONF"); found {
return path, nil
}
return os.Getenv("APPDATA") + "\\containers\\containers.conf", nil
}

View File

@ -92,7 +92,7 @@
# Ulimits has limits for non privileged container engines. # Ulimits has limits for non privileged container engines.
# #
# default_ulimits = [ # default_ulimits = [
# "nofile"="1280:2560", # "nofile=1280:2560",
# ] # ]
# List of default DNS options to be added to /etc/resolv.conf inside of the container. # List of default DNS options to be added to /etc/resolv.conf inside of the container.

View File

@ -32,10 +32,8 @@ func getDefaultProcessLimits() []string {
defaultLimits := []string{} defaultLimits := []string{}
if err := unix.Setrlimit(unix.RLIMIT_NPROC, &rlim); err == nil { if err := unix.Setrlimit(unix.RLIMIT_NPROC, &rlim); err == nil {
defaultLimits = append(defaultLimits, fmt.Sprintf("nproc=%d:%d", rlim.Cur, rlim.Max)) defaultLimits = append(defaultLimits, fmt.Sprintf("nproc=%d:%d", rlim.Cur, rlim.Max))
} else { } else if err := unix.Setrlimit(unix.RLIMIT_NPROC, &oldrlim); err == nil {
if err := unix.Setrlimit(unix.RLIMIT_NPROC, &oldrlim); err == nil {
defaultLimits = append(defaultLimits, fmt.Sprintf("nproc=%d:%d", oldrlim.Cur, oldrlim.Max)) defaultLimits = append(defaultLimits, fmt.Sprintf("nproc=%d:%d", oldrlim.Cur, oldrlim.Max))
} }
}
return defaultLimits return defaultLimits
} }

View File

@ -3,7 +3,6 @@ package config
/* libpodConfig.go contains deprecated functionality and should not be used any longer */ /* libpodConfig.go contains deprecated functionality and should not be used any longer */
import ( import (
"fmt"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
@ -247,7 +246,7 @@ func readLibpodConfigFromFile(path string, config *ConfigFromLibpod) (*ConfigFro
logrus.Debugf("Reading configuration file %q", path) logrus.Debugf("Reading configuration file %q", path)
_, err := toml.DecodeFile(path, config) _, err := toml.DecodeFile(path, config)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to decode configuration %v: %v", path, err) return nil, errors.Wrapf(err, "decode configuration %s", path)
} }
return config, err return config, err

View File

@ -49,7 +49,7 @@ func getRuntimeDir() (string, error) {
if runtimeDir == "" { if runtimeDir == "" {
home := os.Getenv("HOME") home := os.Getenv("HOME")
if home == "" { if home == "" {
rootlessRuntimeDirError = fmt.Errorf("neither XDG_RUNTIME_DIR nor HOME was set non-empty") rootlessRuntimeDirError = errors.New("neither XDG_RUNTIME_DIR nor HOME was set non-empty")
return return
} }
resolvedHome, err := filepath.EvalSymlinks(home) resolvedHome, err := filepath.EvalSymlinks(home)

View File

@ -2,6 +2,7 @@ package retry
import ( import (
"context" "context"
"io"
"math" "math"
"net" "net"
"net/url" "net/url"
@ -18,6 +19,7 @@ import (
// RetryOptions defines the option to retry // RetryOptions defines the option to retry
type RetryOptions struct { type RetryOptions struct {
MaxRetry int // The number of times to possibly retry MaxRetry int // The number of times to possibly retry
Delay time.Duration // The delay to use between retries, if set
} }
// RetryIfNecessary retries the operation in exponential backoff with the retryOptions // RetryIfNecessary retries the operation in exponential backoff with the retryOptions
@ -25,6 +27,9 @@ func RetryIfNecessary(ctx context.Context, operation func() error, retryOptions
err := operation() err := operation()
for attempt := 0; err != nil && isRetryable(err) && attempt < retryOptions.MaxRetry; attempt++ { for attempt := 0; err != nil && isRetryable(err) && attempt < retryOptions.MaxRetry; attempt++ {
delay := time.Duration(int(math.Pow(2, float64(attempt)))) * time.Second delay := time.Duration(int(math.Pow(2, float64(attempt)))) * time.Second
if retryOptions.Delay != 0 {
delay = retryOptions.Delay
}
logrus.Infof("Warning: failed, retrying in %s ... (%d/%d)", delay, attempt+1, retryOptions.MaxRetry) logrus.Infof("Warning: failed, retrying in %s ... (%d/%d)", delay, attempt+1, retryOptions.MaxRetry)
select { select {
case <-time.After(delay): case <-time.After(delay):
@ -58,7 +63,10 @@ func isRetryable(err error) bool {
return true return true
case *net.OpError: case *net.OpError:
return isRetryable(e.Err) return isRetryable(e.Err)
case *url.Error: case *url.Error: // This includes errors returned by the net/http client.
if e.Err == io.EOF { // Happens when a server accepts a HTTP connection and sends EOF
return true
}
return isRetryable(e.Err) return isRetryable(e.Err)
case syscall.Errno: case syscall.Errno:
return e != syscall.ECONNREFUSED return e != syscall.ECONNREFUSED

View File

@ -0,0 +1,32 @@
package seccomp
import "fmt"
var goArchToSeccompArchMap = map[string]Arch{
"386": ArchX86,
"amd64": ArchX86_64,
"amd64p32": ArchX32,
"arm": ArchARM,
"arm64": ArchAARCH64,
"mips": ArchMIPS,
"mips64": ArchMIPS64,
"mips64le": ArchMIPSEL64,
"mips64p32": ArchMIPS64N32,
"mips64p32le": ArchMIPSEL64N32,
"mipsle": ArchMIPSEL,
"ppc": ArchPPC,
"ppc64": ArchPPC64,
"ppc64le": ArchPPC64LE,
"s390": ArchS390,
"s390x": ArchS390X,
}
// GoArchToSeccompArch converts a runtime.GOARCH to a seccomp `Arch`. The
// function returns an error if the architecture conversion is not supported.
func GoArchToSeccompArch(goArch string) (Arch, error) {
arch, ok := goArchToSeccompArchMap[goArch]
if !ok {
return "", fmt.Errorf("unsupported go arch provided: %s", goArch)
}
return arch, nil
}

View File

@ -0,0 +1,878 @@
{
"defaultAction": "SCMP_ACT_ERRNO",
"archMap": [
{
"architecture": "SCMP_ARCH_X86_64",
"subArchitectures": [
"SCMP_ARCH_X86",
"SCMP_ARCH_X32"
]
},
{
"architecture": "SCMP_ARCH_AARCH64",
"subArchitectures": [
"SCMP_ARCH_ARM"
]
},
{
"architecture": "SCMP_ARCH_MIPS64",
"subArchitectures": [
"SCMP_ARCH_MIPS",
"SCMP_ARCH_MIPS64N32"
]
},
{
"architecture": "SCMP_ARCH_MIPS64N32",
"subArchitectures": [
"SCMP_ARCH_MIPS",
"SCMP_ARCH_MIPS64"
]
},
{
"architecture": "SCMP_ARCH_MIPSEL64",
"subArchitectures": [
"SCMP_ARCH_MIPSEL",
"SCMP_ARCH_MIPSEL64N32"
]
},
{
"architecture": "SCMP_ARCH_MIPSEL64N32",
"subArchitectures": [
"SCMP_ARCH_MIPSEL",
"SCMP_ARCH_MIPSEL64"
]
},
{
"architecture": "SCMP_ARCH_S390X",
"subArchitectures": [
"SCMP_ARCH_S390"
]
}
],
"syscalls": [
{
"names": [
"_llseek",
"_newselect",
"accept",
"accept4",
"access",
"adjtimex",
"alarm",
"bind",
"brk",
"capget",
"capset",
"chdir",
"chmod",
"chown",
"chown32",
"clock_getres",
"clock_gettime",
"clock_nanosleep",
"close",
"connect",
"copy_file_range",
"creat",
"dup",
"dup2",
"dup3",
"epoll_create",
"epoll_create1",
"epoll_ctl",
"epoll_ctl_old",
"epoll_pwait",
"epoll_wait",
"epoll_wait_old",
"eventfd",
"eventfd2",
"execve",
"execveat",
"exit",
"exit_group",
"faccessat",
"fadvise64",
"fadvise64_64",
"fallocate",
"fanotify_mark",
"fchdir",
"fchmod",
"fchmodat",
"fchown",
"fchown32",
"fchownat",
"fcntl",
"fcntl64",
"fdatasync",
"fgetxattr",
"flistxattr",
"flock",
"fork",
"fremovexattr",
"fsetxattr",
"fstat",
"fstat64",
"fstatat64",
"fstatfs",
"fstatfs64",
"fsync",
"ftruncate",
"ftruncate64",
"futex",
"futimesat",
"get_robust_list",
"get_thread_area",
"getcpu",
"getcwd",
"getdents",
"getdents64",
"getegid",
"getegid32",
"geteuid",
"geteuid32",
"getgid",
"getgid32",
"getgroups",
"getgroups32",
"getitimer",
"getpeername",
"getpgid",
"getpgrp",
"getpid",
"getppid",
"getpriority",
"getrandom",
"getresgid",
"getresgid32",
"getresuid",
"getresuid32",
"getrlimit",
"getrusage",
"getsid",
"getsockname",
"getsockopt",
"gettid",
"gettimeofday",
"getuid",
"getuid32",
"getxattr",
"inotify_add_watch",
"inotify_init",
"inotify_init1",
"inotify_rm_watch",
"io_cancel",
"io_destroy",
"io_getevents",
"io_setup",
"io_submit",
"ioctl",
"ioprio_get",
"ioprio_set",
"ipc",
"kill",
"lchown",
"lchown32",
"lgetxattr",
"link",
"linkat",
"listen",
"listxattr",
"llistxattr",
"lremovexattr",
"lseek",
"lsetxattr",
"lstat",
"lstat64",
"madvise",
"memfd_create",
"mincore",
"mkdir",
"mkdirat",
"mknod",
"mknodat",
"mlock",
"mlock2",
"mlockall",
"mmap",
"mmap2",
"mount",
"mprotect",
"mq_getsetattr",
"mq_notify",
"mq_open",
"mq_timedreceive",
"mq_timedsend",
"mq_unlink",
"mremap",
"msgctl",
"msgget",
"msgrcv",
"msgsnd",
"msync",
"munlock",
"munlockall",
"munmap",
"name_to_handle_at",
"nanosleep",
"newfstatat",
"open",
"openat",
"pause",
"pipe",
"pipe2",
"poll",
"ppoll",
"prctl",
"pread64",
"preadv",
"preadv2",
"prlimit64",
"pselect6",
"pwrite64",
"pwritev",
"pwritev2",
"read",
"readahead",
"readlink",
"readlinkat",
"readv",
"reboot",
"recv",
"recvfrom",
"recvmmsg",
"recvmsg",
"remap_file_pages",
"removexattr",
"rename",
"renameat",
"renameat2",
"restart_syscall",
"rmdir",
"rt_sigaction",
"rt_sigpending",
"rt_sigprocmask",
"rt_sigqueueinfo",
"rt_sigreturn",
"rt_sigsuspend",
"rt_sigtimedwait",
"rt_tgsigqueueinfo",
"sched_get_priority_max",
"sched_get_priority_min",
"sched_getaffinity",
"sched_getattr",
"sched_getparam",
"sched_getscheduler",
"sched_rr_get_interval",
"sched_setaffinity",
"sched_setattr",
"sched_setparam",
"sched_setscheduler",
"sched_yield",
"seccomp",
"select",
"semctl",
"semget",
"semop",
"semtimedop",
"send",
"sendfile",
"sendfile64",
"sendmmsg",
"sendmsg",
"sendto",
"set_robust_list",
"set_thread_area",
"set_tid_address",
"setfsgid",
"setfsgid32",
"setfsuid",
"setfsuid32",
"setgid",
"setgid32",
"setgroups",
"setgroups32",
"setitimer",
"setpgid",
"setpriority",
"setregid",
"setregid32",
"setresgid",
"setresgid32",
"setresuid",
"setresuid32",
"setreuid",
"setreuid32",
"setrlimit",
"setsid",
"setsockopt",
"setuid",
"setuid32",
"setxattr",
"shmat",
"shmctl",
"shmdt",
"shmget",
"shutdown",
"sigaltstack",
"signalfd",
"signalfd4",
"sigreturn",
"socketcall",
"socketpair",
"splice",
"stat",
"stat64",
"statfs",
"statfs64",
"statx",
"symlink",
"symlinkat",
"sync",
"sync_file_range",
"syncfs",
"sysinfo",
"syslog",
"tee",
"tgkill",
"time",
"timer_create",
"timer_delete",
"timer_getoverrun",
"timer_gettime",
"timer_settime",
"timerfd_create",
"timerfd_gettime",
"timerfd_settime",
"times",
"tkill",
"truncate",
"truncate64",
"ugetrlimit",
"umask",
"umount",
"umount2",
"uname",
"unlink",
"unlinkat",
"unshare",
"utime",
"utimensat",
"utimes",
"vfork",
"vmsplice",
"wait4",
"waitid",
"waitpid",
"write",
"writev"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {},
"excludes": {}
},
{
"names": [
"personality"
],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 0,
"value": 0,
"valueTwo": 0,
"op": "SCMP_CMP_EQ"
}
],
"comment": "",
"includes": {},
"excludes": {}
},
{
"names": [
"personality"
],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 0,
"value": 8,
"valueTwo": 0,
"op": "SCMP_CMP_EQ"
}
],
"comment": "",
"includes": {},
"excludes": {}
},
{
"names": [
"personality"
],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 0,
"value": 131072,
"valueTwo": 0,
"op": "SCMP_CMP_EQ"
}
],
"comment": "",
"includes": {},
"excludes": {}
},
{
"names": [
"personality"
],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 0,
"value": 131080,
"valueTwo": 0,
"op": "SCMP_CMP_EQ"
}
],
"comment": "",
"includes": {},
"excludes": {}
},
{
"names": [
"personality"
],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 0,
"value": 4294967295,
"valueTwo": 0,
"op": "SCMP_CMP_EQ"
}
],
"comment": "",
"includes": {},
"excludes": {}
},
{
"names": [
"sync_file_range2"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"arches": [
"ppc64le"
]
},
"excludes": {}
},
{
"names": [
"arm_fadvise64_64",
"arm_sync_file_range",
"sync_file_range2",
"breakpoint",
"cacheflush",
"set_tls"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"arches": [
"arm",
"arm64"
]
},
"excludes": {}
},
{
"names": [
"arch_prctl"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"arches": [
"amd64",
"x32"
]
},
"excludes": {}
},
{
"names": [
"modify_ldt"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"arches": [
"amd64",
"x32",
"x86"
]
},
"excludes": {}
},
{
"names": [
"s390_pci_mmio_read",
"s390_pci_mmio_write",
"s390_runtime_instr"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"arches": [
"s390",
"s390x"
]
},
"excludes": {}
},
{
"names": [
"open_by_handle_at"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_DAC_READ_SEARCH"
]
},
"excludes": {}
},
{
"names": [
"bpf",
"clone",
"fanotify_init",
"lookup_dcookie",
"mount",
"name_to_handle_at",
"perf_event_open",
"quotactl",
"setdomainname",
"sethostname",
"setns",
"umount",
"umount2",
"unshare"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_ADMIN"
]
},
"excludes": {}
},
{
"names": [
"clone"
],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 0,
"value": 2080505856,
"valueTwo": 0,
"op": "SCMP_CMP_MASKED_EQ"
}
],
"comment": "",
"includes": {},
"excludes": {
"caps": [
"CAP_SYS_ADMIN"
],
"arches": [
"s390",
"s390x"
]
}
},
{
"names": [
"clone"
],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 1,
"value": 2080505856,
"valueTwo": 0,
"op": "SCMP_CMP_MASKED_EQ"
}
],
"comment": "s390 parameter ordering for clone is different",
"includes": {
"arches": [
"s390",
"s390x"
]
},
"excludes": {
"caps": [
"CAP_SYS_ADMIN"
]
}
},
{
"names": [
"reboot"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_BOOT"
]
},
"excludes": {}
},
{
"names": [
"chroot"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_CHROOT"
]
},
"excludes": {}
},
{
"names": [
"delete_module",
"init_module",
"finit_module",
"query_module"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_MODULE"
]
},
"excludes": {}
},
{
"names": [
"get_mempolicy",
"mbind",
"name_to_handle_at",
"set_mempolicy"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_NICE"
]
},
"excludes": {}
},
{
"names": [
"acct"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_PACCT"
]
},
"excludes": {}
},
{
"names": [
"kcmp",
"process_vm_readv",
"process_vm_writev",
"ptrace"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_PTRACE"
]
},
"excludes": {}
},
{
"names": [
"iopl",
"ioperm"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_RAWIO"
]
},
"excludes": {}
},
{
"names": [
"settimeofday",
"stime",
"clock_settime"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_TIME"
]
},
"excludes": {}
},
{
"names": [
"vhangup"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_TTY_CONFIG"
]
},
"excludes": {}
},
{
"names": [
"socket"
],
"action": "SCMP_ACT_ERRNO",
"args": [
{
"index": 0,
"value": 16,
"valueTwo": 0,
"op": "SCMP_CMP_EQ"
},
{
"index": 2,
"value": 9,
"valueTwo": 0,
"op": "SCMP_CMP_EQ"
}
],
"comment": "",
"includes": {},
"excludes": {
"caps": [
"CAP_AUDIT_WRITE"
]
},
"errnoRet": 22
},
{
"names": [
"socket"
],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 2,
"value": 9,
"valueTwo": 0,
"op": "SCMP_CMP_NE"
}
],
"comment": "",
"includes": {},
"excludes": {
"caps": [
"CAP_AUDIT_WRITE"
]
}
},
{
"names": [
"socket"
],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 0,
"value": 16,
"valueTwo": 0,
"op": "SCMP_CMP_NE"
}
],
"comment": "",
"includes": {},
"excludes": {
"caps": [
"CAP_AUDIT_WRITE"
]
}
},
{
"names": [
"socket"
],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 2,
"value": 9,
"valueTwo": 0,
"op": "SCMP_CMP_NE"
}
],
"comment": "",
"includes": {},
"excludes": {
"caps": [
"CAP_AUDIT_WRITE"
]
}
},
{
"names": [
"socket"
],
"action": "SCMP_ACT_ALLOW",
"args": null,
"comment": "",
"includes": {
"caps": [
"CAP_AUDIT_WRITE"
]
},
"excludes": {}
}
]
}

View File

@ -0,0 +1,742 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2013-2018 Docker, Inc.
package seccomp
import (
"syscall"
"golang.org/x/sys/unix"
)
func arches() []Architecture {
return []Architecture{
{
Arch: ArchX86_64,
SubArches: []Arch{ArchX86, ArchX32},
},
{
Arch: ArchAARCH64,
SubArches: []Arch{ArchARM},
},
{
Arch: ArchMIPS64,
SubArches: []Arch{ArchMIPS, ArchMIPS64N32},
},
{
Arch: ArchMIPS64N32,
SubArches: []Arch{ArchMIPS, ArchMIPS64},
},
{
Arch: ArchMIPSEL64,
SubArches: []Arch{ArchMIPSEL, ArchMIPSEL64N32},
},
{
Arch: ArchMIPSEL64N32,
SubArches: []Arch{ArchMIPSEL, ArchMIPSEL64},
},
{
Arch: ArchS390X,
SubArches: []Arch{ArchS390},
},
}
}
// DefaultProfile defines the allowlist for the default seccomp profile.
func DefaultProfile() *Seccomp {
einval := uint(syscall.EINVAL)
syscalls := []*Syscall{
{
Names: []string{
"_llseek",
"_newselect",
"accept",
"accept4",
"access",
"adjtimex",
"alarm",
"bind",
"brk",
"capget",
"capset",
"chdir",
"chmod",
"chown",
"chown32",
"clock_getres",
"clock_gettime",
"clock_nanosleep",
"close",
"connect",
"copy_file_range",
"creat",
"dup",
"dup2",
"dup3",
"epoll_create",
"epoll_create1",
"epoll_ctl",
"epoll_ctl_old",
"epoll_pwait",
"epoll_wait",
"epoll_wait_old",
"eventfd",
"eventfd2",
"execve",
"execveat",
"exit",
"exit_group",
"faccessat",
"fadvise64",
"fadvise64_64",
"fallocate",
"fanotify_mark",
"fchdir",
"fchmod",
"fchmodat",
"fchown",
"fchown32",
"fchownat",
"fcntl",
"fcntl64",
"fdatasync",
"fgetxattr",
"flistxattr",
"flock",
"fork",
"fremovexattr",
"fsetxattr",
"fstat",
"fstat64",
"fstatat64",
"fstatfs",
"fstatfs64",
"fsync",
"ftruncate",
"ftruncate64",
"futex",
"futimesat",
"get_robust_list",
"get_thread_area",
"getcpu",
"getcwd",
"getdents",
"getdents64",
"getegid",
"getegid32",
"geteuid",
"geteuid32",
"getgid",
"getgid32",
"getgroups",
"getgroups32",
"getitimer",
"getpeername",
"getpgid",
"getpgrp",
"getpid",
"getppid",
"getpriority",
"getrandom",
"getresgid",
"getresgid32",
"getresuid",
"getresuid32",
"getrlimit",
"getrusage",
"getsid",
"getsockname",
"getsockopt",
"gettid",
"gettimeofday",
"getuid",
"getuid32",
"getxattr",
"inotify_add_watch",
"inotify_init",
"inotify_init1",
"inotify_rm_watch",
"io_cancel",
"io_destroy",
"io_getevents",
"io_setup",
"io_submit",
"ioctl",
"ioprio_get",
"ioprio_set",
"ipc",
"kill",
"lchown",
"lchown32",
"lgetxattr",
"link",
"linkat",
"listen",
"listxattr",
"llistxattr",
"lremovexattr",
"lseek",
"lsetxattr",
"lstat",
"lstat64",
"madvise",
"memfd_create",
"mincore",
"mkdir",
"mkdirat",
"mknod",
"mknodat",
"mlock",
"mlock2",
"mlockall",
"mmap",
"mmap2",
"mount",
"mprotect",
"mq_getsetattr",
"mq_notify",
"mq_open",
"mq_timedreceive",
"mq_timedsend",
"mq_unlink",
"mremap",
"msgctl",
"msgget",
"msgrcv",
"msgsnd",
"msync",
"munlock",
"munlockall",
"munmap",
"name_to_handle_at",
"nanosleep",
"newfstatat",
"open",
"openat",
"pause",
"pipe",
"pipe2",
"poll",
"ppoll",
"prctl",
"pread64",
"preadv",
"preadv2",
"prlimit64",
"pselect6",
"pwrite64",
"pwritev",
"pwritev2",
"read",
"readahead",
"readlink",
"readlinkat",
"readv",
"reboot",
"recv",
"recvfrom",
"recvmmsg",
"recvmsg",
"remap_file_pages",
"removexattr",
"rename",
"renameat",
"renameat2",
"restart_syscall",
"rmdir",
"rt_sigaction",
"rt_sigpending",
"rt_sigprocmask",
"rt_sigqueueinfo",
"rt_sigreturn",
"rt_sigsuspend",
"rt_sigtimedwait",
"rt_tgsigqueueinfo",
"sched_get_priority_max",
"sched_get_priority_min",
"sched_getaffinity",
"sched_getattr",
"sched_getparam",
"sched_getscheduler",
"sched_rr_get_interval",
"sched_setaffinity",
"sched_setattr",
"sched_setparam",
"sched_setscheduler",
"sched_yield",
"seccomp",
"select",
"semctl",
"semget",
"semop",
"semtimedop",
"send",
"sendfile",
"sendfile64",
"sendmmsg",
"sendmsg",
"sendto",
"set_robust_list",
"set_thread_area",
"set_tid_address",
"setfsgid",
"setfsgid32",
"setfsuid",
"setfsuid32",
"setgid",
"setgid32",
"setgroups",
"setgroups32",
"setitimer",
"setpgid",
"setpriority",
"setregid",
"setregid32",
"setresgid",
"setresgid32",
"setresuid",
"setresuid32",
"setreuid",
"setreuid32",
"setrlimit",
"setsid",
"setsockopt",
"setuid",
"setuid32",
"setxattr",
"shmat",
"shmctl",
"shmdt",
"shmget",
"shutdown",
"sigaltstack",
"signalfd",
"signalfd4",
"sigreturn",
"socketcall",
"socketpair",
"splice",
"stat",
"stat64",
"statfs",
"statfs64",
"statx",
"symlink",
"symlinkat",
"sync",
"sync_file_range",
"syncfs",
"sysinfo",
"syslog",
"tee",
"tgkill",
"time",
"timer_create",
"timer_delete",
"timer_getoverrun",
"timer_gettime",
"timer_settime",
"timerfd_create",
"timerfd_gettime",
"timerfd_settime",
"times",
"tkill",
"truncate",
"truncate64",
"ugetrlimit",
"umask",
"umount",
"umount2",
"uname",
"unlink",
"unlinkat",
"unshare",
"utime",
"utimensat",
"utimes",
"vfork",
"vmsplice",
"wait4",
"waitid",
"waitpid",
"write",
"writev",
},
Action: ActAllow,
Args: []*Arg{},
},
{
Names: []string{"personality"},
Action: ActAllow,
Args: []*Arg{
{
Index: 0,
Value: 0x0,
Op: OpEqualTo,
},
},
},
{
Names: []string{"personality"},
Action: ActAllow,
Args: []*Arg{
{
Index: 0,
Value: 0x0008,
Op: OpEqualTo,
},
},
},
{
Names: []string{"personality"},
Action: ActAllow,
Args: []*Arg{
{
Index: 0,
Value: 0x20000,
Op: OpEqualTo,
},
},
},
{
Names: []string{"personality"},
Action: ActAllow,
Args: []*Arg{
{
Index: 0,
Value: 0x20008,
Op: OpEqualTo,
},
},
},
{
Names: []string{"personality"},
Action: ActAllow,
Args: []*Arg{
{
Index: 0,
Value: 0xffffffff,
Op: OpEqualTo,
},
},
},
{
Names: []string{
"sync_file_range2",
},
Action: ActAllow,
Args: []*Arg{},
Includes: Filter{
Arches: []string{"ppc64le"},
},
},
{
Names: []string{
"arm_fadvise64_64",
"arm_sync_file_range",
"sync_file_range2",
"breakpoint",
"cacheflush",
"set_tls",
},
Action: ActAllow,
Args: []*Arg{},
Includes: Filter{
Arches: []string{"arm", "arm64"},
},
},
{
Names: []string{
"arch_prctl",
},
Action: ActAllow,
Args: []*Arg{},
Includes: Filter{
Arches: []string{"amd64", "x32"},
},
},
{
Names: []string{
"modify_ldt",
},
Action: ActAllow,
Args: []*Arg{},
Includes: Filter{
Arches: []string{"amd64", "x32", "x86"},
},
},
{
Names: []string{
"s390_pci_mmio_read",
"s390_pci_mmio_write",
"s390_runtime_instr",
},
Action: ActAllow,
Args: []*Arg{},
Includes: Filter{
Arches: []string{"s390", "s390x"},
},
},
{
Names: []string{
"open_by_handle_at",
},
Action: ActAllow,
Args: []*Arg{},
Includes: Filter{
Caps: []string{"CAP_DAC_READ_SEARCH"},
},
},
{
Names: []string{
"bpf",
"clone",
"fanotify_init",
"lookup_dcookie",
"mount",
"name_to_handle_at",
"perf_event_open",
"quotactl",
"setdomainname",
"sethostname",
"setns",
"umount",
"umount2",
"unshare",
},
Action: ActAllow,
Args: []*Arg{},
Includes: Filter{
Caps: []string{"CAP_SYS_ADMIN"},
},
},
{
Names: []string{
"clone",
},
Action: ActAllow,
Args: []*Arg{
{
Index: 0,
Value: unix.CLONE_NEWNS | unix.CLONE_NEWUTS | unix.CLONE_NEWIPC | unix.CLONE_NEWUSER | unix.CLONE_NEWPID | unix.CLONE_NEWNET,
ValueTwo: 0,
Op: OpMaskedEqual,
},
},
Excludes: Filter{
Caps: []string{"CAP_SYS_ADMIN"},
Arches: []string{"s390", "s390x"},
},
},
{
Names: []string{
"clone",
},
Action: ActAllow,
Args: []*Arg{
{
Index: 1,
Value: unix.CLONE_NEWNS | unix.CLONE_NEWUTS | unix.CLONE_NEWIPC | unix.CLONE_NEWUSER | unix.CLONE_NEWPID | unix.CLONE_NEWNET,
ValueTwo: 0,
Op: OpMaskedEqual,
},
},
Comment: "s390 parameter ordering for clone is different",
Includes: Filter{
Arches: []string{"s390", "s390x"},
},
Excludes: Filter{
Caps: []string{"CAP_SYS_ADMIN"},
},
},
{
Names: []string{
"reboot",
},
Action: ActAllow,
Args: []*Arg{},
Includes: Filter{
Caps: []string{"CAP_SYS_BOOT"},
},
},
{
Names: []string{
"chroot",
},
Action: ActAllow,
Args: []*Arg{},
Includes: Filter{
Caps: []string{"CAP_SYS_CHROOT"},
},
},
{
Names: []string{
"delete_module",
"init_module",
"finit_module",
"query_module",
},
Action: ActAllow,
Args: []*Arg{},
Includes: Filter{
Caps: []string{"CAP_SYS_MODULE"},
},
},
{
Names: []string{
"get_mempolicy",
"mbind",
"name_to_handle_at",
"set_mempolicy",
},
Action: ActAllow,
Args: []*Arg{},
Includes: Filter{
Caps: []string{"CAP_SYS_NICE"},
},
},
{
Names: []string{
"acct",
},
Action: ActAllow,
Args: []*Arg{},
Includes: Filter{
Caps: []string{"CAP_SYS_PACCT"},
},
},
{
Names: []string{
"kcmp",
"process_vm_readv",
"process_vm_writev",
"ptrace",
},
Action: ActAllow,
Args: []*Arg{},
Includes: Filter{
Caps: []string{"CAP_SYS_PTRACE"},
},
},
{
Names: []string{
"iopl",
"ioperm",
},
Action: ActAllow,
Args: []*Arg{},
Includes: Filter{
Caps: []string{"CAP_SYS_RAWIO"},
},
},
{
Names: []string{
"settimeofday",
"stime",
"clock_settime",
},
Action: ActAllow,
Args: []*Arg{},
Includes: Filter{
Caps: []string{"CAP_SYS_TIME"},
},
},
{
Names: []string{
"vhangup",
},
Action: ActAllow,
Args: []*Arg{},
Includes: Filter{
Caps: []string{"CAP_SYS_TTY_CONFIG"},
},
},
{
Names: []string{
"socket",
},
Action: ActErrno,
ErrnoRet: &einval,
Args: []*Arg{
{
Index: 0,
Value: syscall.AF_NETLINK,
Op: OpEqualTo,
},
{
Index: 2,
Value: syscall.NETLINK_AUDIT,
Op: OpEqualTo,
},
},
Excludes: Filter{
Caps: []string{"CAP_AUDIT_WRITE"},
},
},
{
Names: []string{
"socket",
},
Action: ActAllow,
Args: []*Arg{
{
Index: 2,
Value: syscall.NETLINK_AUDIT,
Op: OpNotEqual,
},
},
Excludes: Filter{
Caps: []string{"CAP_AUDIT_WRITE"},
},
},
{
Names: []string{
"socket",
},
Action: ActAllow,
Args: []*Arg{
{
Index: 0,
Value: syscall.AF_NETLINK,
Op: OpNotEqual,
},
},
Excludes: Filter{
Caps: []string{"CAP_AUDIT_WRITE"},
},
},
{
Names: []string{
"socket",
},
Action: ActAllow,
Args: []*Arg{
{
Index: 2,
Value: syscall.NETLINK_AUDIT,
Op: OpNotEqual,
},
},
Excludes: Filter{
Caps: []string{"CAP_AUDIT_WRITE"},
},
},
{
Names: []string{
"socket",
},
Action: ActAllow,
Includes: Filter{
Caps: []string{"CAP_AUDIT_WRITE"},
},
},
}
return &Seccomp{
DefaultAction: ActErrno,
ArchMap: arches(),
Syscalls: syscalls,
}
}

View File

@ -0,0 +1,183 @@
// +build seccomp
// SPDX-License-Identifier: Apache-2.0
// Copyright 2013-2018 Docker, Inc.
package seccomp
import (
"encoding/json"
"errors"
"fmt"
"github.com/opencontainers/runtime-spec/specs-go"
libseccomp "github.com/seccomp/libseccomp-golang"
)
//go:generate go run -tags 'seccomp' generate.go
// GetDefaultProfile returns the default seccomp profile.
func GetDefaultProfile(rs *specs.Spec) (*specs.LinuxSeccomp, error) {
return setupSeccomp(DefaultProfile(), rs)
}
// LoadProfile takes a json string and decodes the seccomp profile.
func LoadProfile(body string, rs *specs.Spec) (*specs.LinuxSeccomp, error) {
var config Seccomp
if err := json.Unmarshal([]byte(body), &config); err != nil {
return nil, fmt.Errorf("decoding seccomp profile failed: %v", err)
}
return setupSeccomp(&config, rs)
}
// LoadProfileFromBytes takes a byte slice and decodes the seccomp profile.
func LoadProfileFromBytes(body []byte, rs *specs.Spec) (*specs.LinuxSeccomp, error) {
config := &Seccomp{}
if err := json.Unmarshal(body, config); err != nil {
return nil, fmt.Errorf("decoding seccomp profile failed: %v", err)
}
return setupSeccomp(config, rs)
}
// LoadProfileFromConfig takes a Seccomp struct and a spec to retrieve a LinuxSeccomp
func LoadProfileFromConfig(config *Seccomp, specgen *specs.Spec) (*specs.LinuxSeccomp, error) {
return setupSeccomp(config, specgen)
}
var nativeToSeccomp = map[string]Arch{
"amd64": ArchX86_64,
"arm64": ArchAARCH64,
"mips64": ArchMIPS64,
"mips64n32": ArchMIPS64N32,
"mipsel64": ArchMIPSEL64,
"mipsel64n32": ArchMIPSEL64N32,
"s390x": ArchS390X,
}
// inSlice tests whether a string is contained in a slice of strings or not.
// Comparison is case sensitive
func inSlice(slice []string, s string) bool {
for _, ss := range slice {
if s == ss {
return true
}
}
return false
}
func setupSeccomp(config *Seccomp, rs *specs.Spec) (*specs.LinuxSeccomp, error) {
if config == nil {
return nil, nil
}
// No default action specified, no syscalls listed, assume seccomp disabled
if config.DefaultAction == "" && len(config.Syscalls) == 0 {
return nil, nil
}
newConfig := &specs.LinuxSeccomp{}
var arch string
var native, err = libseccomp.GetNativeArch()
if err == nil {
arch = native.String()
}
if len(config.Architectures) != 0 && len(config.ArchMap) != 0 {
return nil, errors.New("'architectures' and 'archMap' were specified in the seccomp profile, use either 'architectures' or 'archMap'")
}
// if config.Architectures == 0 then libseccomp will figure out the architecture to use
if len(config.Architectures) != 0 {
for _, a := range config.Architectures {
newConfig.Architectures = append(newConfig.Architectures, specs.Arch(a))
}
}
if len(config.ArchMap) != 0 {
for _, a := range config.ArchMap {
seccompArch, ok := nativeToSeccomp[arch]
if ok {
if a.Arch == seccompArch {
newConfig.Architectures = append(newConfig.Architectures, specs.Arch(a.Arch))
for _, sa := range a.SubArches {
newConfig.Architectures = append(newConfig.Architectures, specs.Arch(sa))
}
break
}
}
}
}
newConfig.DefaultAction = specs.LinuxSeccompAction(config.DefaultAction)
Loop:
// Loop through all syscall blocks and convert them to libcontainer format after filtering them
for _, call := range config.Syscalls {
if len(call.Excludes.Arches) > 0 {
if inSlice(call.Excludes.Arches, arch) {
continue Loop
}
}
if len(call.Excludes.Caps) > 0 {
for _, c := range call.Excludes.Caps {
if inSlice(rs.Process.Capabilities.Bounding, c) {
continue Loop
}
}
}
if len(call.Includes.Arches) > 0 {
if !inSlice(call.Includes.Arches, arch) {
continue Loop
}
}
if len(call.Includes.Caps) > 0 {
for _, c := range call.Includes.Caps {
if !inSlice(rs.Process.Capabilities.Bounding, c) {
continue Loop
}
}
}
if call.Name != "" && len(call.Names) != 0 {
return nil, errors.New("'name' and 'names' were specified in the seccomp profile, use either 'name' or 'names'")
}
if call.Name != "" {
newConfig.Syscalls = append(newConfig.Syscalls, createSpecsSyscall([]string{call.Name}, call.Action, call.Args, call.ErrnoRet))
}
if len(call.Names) > 0 {
newConfig.Syscalls = append(newConfig.Syscalls, createSpecsSyscall(call.Names, call.Action, call.Args, call.ErrnoRet))
}
}
return newConfig, nil
}
func createSpecsSyscall(names []string, action Action, args []*Arg, errnoRet *uint) specs.LinuxSyscall {
newCall := specs.LinuxSyscall{
Names: names,
Action: specs.LinuxSeccompAction(action),
ErrnoRet: errnoRet,
}
// Loop through all the arguments of the syscall and convert them
for _, arg := range args {
newArg := specs.LinuxSeccompArg{
Index: arg.Index,
Value: arg.Value,
ValueTwo: arg.ValueTwo,
Op: specs.LinuxSeccompOperator(arg.Op),
}
newCall.Args = append(newCall.Args, newArg)
}
return newCall
}
// IsEnabled returns true if seccomp is enabled for the host.
func IsEnabled() bool {
return IsSupported()
}

View File

@ -0,0 +1,40 @@
// +build !seccomp
// SPDX-License-Identifier: Apache-2.0
// Copyright 2013-2018 Docker, Inc.
package seccomp
import (
"errors"
"github.com/opencontainers/runtime-spec/specs-go"
)
var errNotSupported = errors.New("seccomp not enabled in this build")
// LoadProfile returns an error on unsuppored systems
func LoadProfile(body string, rs *specs.Spec) (*specs.LinuxSeccomp, error) {
return nil, errNotSupported
}
// GetDefaultProfile returns an error on unsuppored systems
func GetDefaultProfile(rs *specs.Spec) (*specs.LinuxSeccomp, error) {
return nil, errNotSupported
}
// LoadProfileFromBytes takes a byte slice and decodes the seccomp profile.
func LoadProfileFromBytes(body []byte, rs *specs.Spec) (*specs.LinuxSeccomp, error) {
return nil, errNotSupported
}
// LoadProfileFromConfig takes a Seccomp struct and a spec to retrieve a LinuxSeccomp
func LoadProfileFromConfig(config *Seccomp, specgen *specs.Spec) (*specs.LinuxSeccomp, error) {
return nil, errNotSupported
}
// IsEnabled returns true if seccomp is enabled for the host.
func IsEnabled() bool {
return false
}

View File

@ -0,0 +1,72 @@
package seccomp
import (
"bufio"
"errors"
"os"
"strings"
perrors "github.com/pkg/errors"
"golang.org/x/sys/unix"
)
const statusFilePath = "/proc/self/status"
// IsSupported returns true if the system has been configured to support
// seccomp.
func IsSupported() bool {
// Since Linux 3.8, the Seccomp field of the /proc/[pid]/status file
// provides a method of obtaining the same information, without the risk
// that the process is killed; see proc(5).
status, err := parseStatusFile(statusFilePath)
if err == nil {
_, ok := status["Seccomp"]
return ok
}
// PR_GET_SECCOMP (since Linux 2.6.23)
// Return (as the function result) the secure computing mode of the calling
// thread. If the caller is not in secure computing mode, this operation
// returns 0; if the caller is in strict secure computing mode, then the
// prctl() call will cause a SIGKILL signal to be sent to the process. If
// the caller is in filter mode, and this system call is allowed by the
// seccomp filters, it returns 2; otherwise, the process is killed with a
// SIGKILL signal. This operation is available only if the kernel is
// configured with CONFIG_SECCOMP enabled.
if err := unix.Prctl(unix.PR_GET_SECCOMP, 0, 0, 0, 0); !errors.Is(err, unix.EINVAL) {
// Make sure the kernel has CONFIG_SECCOMP_FILTER.
if err := unix.Prctl(unix.PR_SET_SECCOMP, unix.SECCOMP_MODE_FILTER, 0, 0, 0); !errors.Is(err, unix.EINVAL) {
return true
}
}
return false
}
// parseStatusFile reads the provided `file` into a map of strings.
func parseStatusFile(file string) (map[string]string, error) {
f, err := os.Open(file)
if err != nil {
return nil, perrors.Wrapf(err, "open status file %s", file)
}
defer f.Close()
status := make(map[string]string)
scanner := bufio.NewScanner(f)
for scanner.Scan() {
text := scanner.Text()
parts := strings.SplitN(text, ":", 2)
if len(parts) <= 1 {
continue
}
status[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
}
if err := scanner.Err(); err != nil {
return nil, perrors.Wrapf(err, "scan status file %s", file)
}
return status, nil
}

View File

@ -0,0 +1,110 @@
package seccomp
// SPDX-License-Identifier: Apache-2.0
// Copyright 2013-2018 Docker, Inc.
// Seccomp represents the config for a seccomp profile for syscall restriction.
type Seccomp struct {
DefaultAction Action `json:"defaultAction"`
// Architectures is kept to maintain backward compatibility with the old
// seccomp profile.
Architectures []Arch `json:"architectures,omitempty"`
ArchMap []Architecture `json:"archMap,omitempty"`
Syscalls []*Syscall `json:"syscalls"`
}
// Architecture is used to represent a specific architecture
// and its sub-architectures
type Architecture struct {
Arch Arch `json:"architecture"`
SubArches []Arch `json:"subArchitectures"`
}
// Arch used for architectures
type Arch string
// Additional architectures permitted to be used for system calls
// By default only the native architecture of the kernel is permitted
const (
ArchNative Arch = "SCMP_ARCH_NATIVE"
ArchX86 Arch = "SCMP_ARCH_X86"
ArchX86_64 Arch = "SCMP_ARCH_X86_64"
ArchX32 Arch = "SCMP_ARCH_X32"
ArchARM Arch = "SCMP_ARCH_ARM"
ArchAARCH64 Arch = "SCMP_ARCH_AARCH64"
ArchMIPS Arch = "SCMP_ARCH_MIPS"
ArchMIPS64 Arch = "SCMP_ARCH_MIPS64"
ArchMIPS64N32 Arch = "SCMP_ARCH_MIPS64N32"
ArchMIPSEL Arch = "SCMP_ARCH_MIPSEL"
ArchMIPSEL64 Arch = "SCMP_ARCH_MIPSEL64"
ArchMIPSEL64N32 Arch = "SCMP_ARCH_MIPSEL64N32"
ArchPPC Arch = "SCMP_ARCH_PPC"
ArchPPC64 Arch = "SCMP_ARCH_PPC64"
ArchPPC64LE Arch = "SCMP_ARCH_PPC64LE"
ArchS390 Arch = "SCMP_ARCH_S390"
ArchS390X Arch = "SCMP_ARCH_S390X"
ArchPARISC Arch = "SCMP_ARCH_PARISC"
ArchPARISC64 Arch = "SCMP_ARCH_PARISC64"
ArchRISCV64 Arch = "SCMP_ARCH_RISCV64"
)
// Action taken upon Seccomp rule match
type Action string
// Define actions for Seccomp rules
const (
// ActKill results in termination of the thread that made the system call.
ActKill Action = "SCMP_ACT_KILL"
// ActKillProcess results in termination of the entire process.
ActKillProcess Action = "SCMP_ACT_KILL_PROCESS"
// 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 Action = "SCMP_ACT_KILL_THREAD"
ActTrap Action = "SCMP_ACT_TRAP"
ActErrno Action = "SCMP_ACT_ERRNO"
ActTrace Action = "SCMP_ACT_TRACE"
ActAllow Action = "SCMP_ACT_ALLOW"
ActLog Action = "SCMP_ACT_LOG"
)
// Operator used to match syscall arguments in Seccomp
type Operator string
// Define operators for syscall arguments in Seccomp
const (
OpNotEqual Operator = "SCMP_CMP_NE"
OpLessThan Operator = "SCMP_CMP_LT"
OpLessEqual Operator = "SCMP_CMP_LE"
OpEqualTo Operator = "SCMP_CMP_EQ"
OpGreaterEqual Operator = "SCMP_CMP_GE"
OpGreaterThan Operator = "SCMP_CMP_GT"
OpMaskedEqual Operator = "SCMP_CMP_MASKED_EQ"
)
// Arg used for matching specific syscall arguments in Seccomp
type Arg struct {
Index uint `json:"index"`
Value uint64 `json:"value"`
ValueTwo uint64 `json:"valueTwo"`
Op Operator `json:"op"`
}
// Filter is used to conditionally apply Seccomp rules
type Filter struct {
Caps []string `json:"caps,omitempty"`
Arches []string `json:"arches,omitempty"`
}
// Syscall is used to match a group of syscalls in Seccomp
type Syscall struct {
Name string `json:"name,omitempty"`
Names []string `json:"names,omitempty"`
Action Action `json:"action"`
Args []*Arg `json:"args"`
Comment string `json:"comment"`
Includes Filter `json:"includes"`
Excludes Filter `json:"excludes"`
ErrnoRet *uint `json:"errnoRet,omitempty"`
}

View File

@ -1,7 +1,6 @@
package sysinfo package sysinfo
import ( import (
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"path" "path"
@ -9,6 +8,7 @@ import (
"github.com/containers/common/pkg/cgroupv2" "github.com/containers/common/pkg/cgroupv2"
"github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
@ -16,7 +16,7 @@ import (
func findCgroupMountpoints() (map[string]string, error) { func findCgroupMountpoints() (map[string]string, error) {
cgMounts, err := cgroups.GetCgroupMounts(false) cgMounts, err := cgroups.GetCgroupMounts(false)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to parse cgroup information: %v", err) return nil, errors.Wrap(err, "parse cgroup information")
} }
mps := make(map[string]string) mps := make(map[string]string)
for _, m := range cgMounts { for _, m := range cgMounts {
@ -253,8 +253,8 @@ func cgroupEnabled(mountPoint, name string) bool {
return err == nil return err == nil
} }
func readProcBool(path string) bool { func readProcBool(file string) bool {
val, err := ioutil.ReadFile(path) val, err := ioutil.ReadFile(file)
if err != nil { if err != nil {
return false return false
} }

View File

@ -1,4 +1,4 @@
package version package version
// Version is the version of the build. // Version is the version of the build.
const Version = "0.20.3" const Version = "0.20.4-dev"

View File

@ -106,7 +106,7 @@ lint_task:
env: env:
CIRRUS_WORKING_DIR: "/go/src/github.com/containers/storage" CIRRUS_WORKING_DIR: "/go/src/github.com/containers/storage"
container: container:
image: golang:1.13 image: golang:1.15
modules_cache: modules_cache:
fingerprint_script: cat go.sum fingerprint_script: cat go.sum
folder: $GOPATH/pkg/mod folder: $GOPATH/pkg/mod
@ -142,7 +142,7 @@ meta_task:
vendor_task: vendor_task:
container: container:
image: golang:1.14 image: golang:1.15
modules_cache: modules_cache:
fingerprint_script: cat go.sum fingerprint_script: cat go.sum
folder: $GOPATH/pkg/mod folder: $GOPATH/pkg/mod
@ -157,6 +157,6 @@ success_task:
- meta - meta
- vendor - vendor
container: container:
image: golang:1.14 image: golang:1.15
clone_script: 'mkdir -p "$CIRRUS_WORKING_DIR"' # Source code not needed clone_script: 'mkdir -p "$CIRRUS_WORKING_DIR"' # Source code not needed
script: /bin/true script: /bin/true

View File

@ -1 +1 @@
1.23.1-dev 1.23.2

View File

@ -143,10 +143,6 @@ func DirCopy(srcDir, dstDir string, copyMode Mode, copyXattrs bool) error {
} }
dstPath := filepath.Join(dstDir, relPath) dstPath := filepath.Join(dstDir, relPath)
if err != nil {
return err
}
stat, ok := f.Sys().(*syscall.Stat_t) stat, ok := f.Sys().(*syscall.Stat_t)
if !ok { if !ok {
return fmt.Errorf("Unable to get raw syscall.Stat_t data for %s", srcPath) return fmt.Errorf("Unable to get raw syscall.Stat_t data for %s", srcPath)

View File

@ -51,6 +51,10 @@ func (c *RefCounter) incdec(path string, infoOp func(minfo *minfo)) int {
if c.checker.IsMounted(path) { if c.checker.IsMounted(path) {
m.count++ m.count++
} }
} else if !c.checker.IsMounted(path) {
// if the unmount was performed outside of this process (e.g. conmon cleanup)
//the ref counter would lose track of it. Check if it is still mounted.
m.count = 0
} }
infoOp(m) infoOp(m)
count := m.count count := m.count

View File

@ -274,22 +274,28 @@ func parseOptions(options []string) (*overlayOptions, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
key = strings.ToLower(key) trimkey := strings.ToLower(key)
switch key { trimkey = strings.TrimPrefix(trimkey, "overlay.")
case ".override_kernel_check", "overlay.override_kernel_check", "overlay2.override_kernel_check": trimkey = strings.TrimPrefix(trimkey, "overlay2.")
trimkey = strings.TrimPrefix(trimkey, ".")
switch trimkey {
case "override_kernel_check":
logrus.Warnf("overlay: override_kernel_check option was specified, but is no longer necessary") logrus.Warnf("overlay: override_kernel_check option was specified, but is no longer necessary")
case ".mountopt", "overlay.mountopt", "overlay2.mountopt": case "mountopt":
o.mountOptions = val o.mountOptions = val
case ".size", "overlay.size", "overlay2.size": case "size":
logrus.Debugf("overlay: size=%s", val) logrus.Debugf("overlay: size=%s", val)
size, err := units.RAMInBytes(val) size, err := units.RAMInBytes(val)
if err != nil { if err != nil {
return nil, err return nil, err
} }
o.quota.Size = uint64(size) o.quota.Size = uint64(size)
case ".imagestore", "overlay.imagestore", "overlay2.imagestore": case "imagestore", "additionalimagestore":
logrus.Debugf("overlay: imagestore=%s", val) logrus.Debugf("overlay: imagestore=%s", val)
// Additional read only image stores to use for lower paths // Additional read only image stores to use for lower paths
if val == "" {
continue
}
for _, store := range strings.Split(val, ",") { for _, store := range strings.Split(val, ",") {
store = filepath.Clean(store) store = filepath.Clean(store)
if !filepath.IsAbs(store) { if !filepath.IsAbs(store) {
@ -304,17 +310,17 @@ func parseOptions(options []string) (*overlayOptions, error) {
} }
o.imageStores = append(o.imageStores, store) o.imageStores = append(o.imageStores, store)
} }
case ".mount_program", "overlay.mount_program", "overlay2.mount_program": case "mount_program":
logrus.Debugf("overlay: mount_program=%s", val) logrus.Debugf("overlay: mount_program=%s", val)
_, err := os.Stat(val) _, err := os.Stat(val)
if err != nil { if err != nil {
return nil, fmt.Errorf("overlay: can't stat program %s: %v", val, err) return nil, fmt.Errorf("overlay: can't stat program %s: %v", val, err)
} }
o.mountProgram = val o.mountProgram = val
case "overlay2.skip_mount_home", "overlay.skip_mount_home", ".skip_mount_home": case "skip_mount_home":
logrus.Debugf("overlay: skip_mount_home=%s", val) logrus.Debugf("overlay: skip_mount_home=%s", val)
o.skipMountHome, err = strconv.ParseBool(val) o.skipMountHome, err = strconv.ParseBool(val)
case ".ignore_chown_errors", "overlay2.ignore_chown_errors", "overlay.ignore_chown_errors": case "ignore_chown_errors":
logrus.Debugf("overlay: ignore_chown_errors=%s", val) logrus.Debugf("overlay: ignore_chown_errors=%s", val)
o.ignoreChownErrors, err = strconv.ParseBool(val) o.ignoreChownErrors, err = strconv.ParseBool(val)
if err != nil { if err != nil {

View File

@ -1,3 +1,5 @@
go 1.15
module github.com/containers/storage module github.com/containers/storage
require ( require (
@ -6,7 +8,7 @@ require (
github.com/Microsoft/hcsshim v0.8.9 github.com/Microsoft/hcsshim v0.8.9
github.com/docker/go-units v0.4.0 github.com/docker/go-units v0.4.0
github.com/hashicorp/go-multierror v1.1.0 github.com/hashicorp/go-multierror v1.1.0
github.com/klauspost/compress v1.10.10 github.com/klauspost/compress v1.10.11
github.com/klauspost/pgzip v1.2.4 github.com/klauspost/pgzip v1.2.4
github.com/mattn/go-shellwords v1.0.10 github.com/mattn/go-shellwords v1.0.10
github.com/mistifyio/go-zfs v2.1.1+incompatible github.com/mistifyio/go-zfs v2.1.1+incompatible
@ -25,5 +27,3 @@ require (
golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775 golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775
gotest.tools v2.2.0+incompatible gotest.tools v2.2.0+incompatible
) )
go 1.13

View File

@ -62,8 +62,8 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.10.10 h1:a/y8CglcM7gLGYmlbP/stPE5sR3hbhFRUjCBfd/0B3I= github.com/klauspost/compress v1.10.11 h1:K9z59aO18Aywg2b/WSgBaUX99mHy2BES18Cr5lBKZHk=
github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.10.11/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/pgzip v1.2.4 h1:TQ7CNpYKovDOmqzRHKxJh0BeaBI7UdQZYc6p7pMQh1A= github.com/klauspost/pgzip v1.2.4 h1:TQ7CNpYKovDOmqzRHKxJh0BeaBI7UdQZYc6p7pMQh1A=
github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=

View File

@ -2630,6 +2630,9 @@ func (s *store) mount(id string, options drivers.MountOpts) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
s.graphLock.Lock()
defer s.graphLock.Unlock()
rlstore.Lock() rlstore.Lock()
defer rlstore.Unlock() defer rlstore.Unlock()
if modified, err := rlstore.Modified(); modified || err != nil { if modified, err := rlstore.Modified(); modified || err != nil {

View File

@ -43,6 +43,11 @@ func (b *bitWriter) addBits16Clean(value uint16, bits uint8) {
func (b *bitWriter) encSymbol(ct cTable, symbol byte) { func (b *bitWriter) encSymbol(ct cTable, symbol byte) {
enc := ct[symbol] enc := ct[symbol]
b.bitContainer |= uint64(enc.val) << (b.nBits & 63) b.bitContainer |= uint64(enc.val) << (b.nBits & 63)
if false {
if enc.nBits == 0 {
panic("nbits 0")
}
}
b.nBits += enc.nBits b.nBits += enc.nBits
} }
@ -54,6 +59,14 @@ func (b *bitWriter) encTwoSymbols(ct cTable, av, bv byte) {
sh := b.nBits & 63 sh := b.nBits & 63
combined := uint64(encA.val) | (uint64(encB.val) << (encA.nBits & 63)) combined := uint64(encA.val) | (uint64(encB.val) << (encA.nBits & 63))
b.bitContainer |= combined << sh b.bitContainer |= combined << sh
if false {
if encA.nBits == 0 {
panic("nbitsA 0")
}
if encB.nBits == 0 {
panic("nbitsB 0")
}
}
b.nBits += encA.nBits + encB.nBits b.nBits += encA.nBits + encB.nBits
} }

View File

@ -77,8 +77,11 @@ func compress(in []byte, s *Scratch, compressor func(src []byte) ([]byte, error)
// Each symbol present maximum once or too well distributed. // Each symbol present maximum once or too well distributed.
return nil, false, ErrIncompressible return nil, false, ErrIncompressible
} }
if s.Reuse == ReusePolicyMust && !canReuse {
if s.Reuse == ReusePolicyPrefer && canReuse { // We must reuse, but we can't.
return nil, false, ErrIncompressible
}
if (s.Reuse == ReusePolicyPrefer || s.Reuse == ReusePolicyMust) && canReuse {
keepTable := s.cTable keepTable := s.cTable
keepTL := s.actualTableLog keepTL := s.actualTableLog
s.cTable = s.prevTable s.cTable = s.prevTable
@ -90,6 +93,9 @@ func compress(in []byte, s *Scratch, compressor func(src []byte) ([]byte, error)
s.OutData = s.Out s.OutData = s.Out
return s.Out, true, nil return s.Out, true, nil
} }
if s.Reuse == ReusePolicyMust {
return nil, false, ErrIncompressible
}
// Do not attempt to re-use later. // Do not attempt to re-use later.
s.prevTable = s.prevTable[:0] s.prevTable = s.prevTable[:0]
} }

View File

@ -32,7 +32,7 @@ const use8BitTables = true
// The size of the input may be larger than the table definition. // The size of the input may be larger than the table definition.
// Any content remaining after the table definition will be returned. // Any content remaining after the table definition will be returned.
// If no Scratch is provided a new one is allocated. // If no Scratch is provided a new one is allocated.
// The returned Scratch can be used for decoding input using this table. // The returned Scratch can be used for encoding or decoding input using this table.
func ReadTable(in []byte, s *Scratch) (s2 *Scratch, remain []byte, err error) { func ReadTable(in []byte, s *Scratch) (s2 *Scratch, remain []byte, err error) {
s, err = s.prepare(in) s, err = s.prepare(in)
if err != nil { if err != nil {
@ -58,8 +58,8 @@ func ReadTable(in []byte, s *Scratch) (s2 *Scratch, remain []byte, err error) {
s.symbolLen = uint16(oSize) s.symbolLen = uint16(oSize)
in = in[iSize:] in = in[iSize:]
} else { } else {
if len(in) <= int(iSize) { if len(in) < int(iSize) {
return s, nil, errors.New("input too small for table") return s, nil, fmt.Errorf("input too small for table, want %d bytes, have %d", iSize, len(in))
} }
// FSE compressed weights // FSE compressed weights
s.fse.DecompressLimit = 255 s.fse.DecompressLimit = 255
@ -138,15 +138,33 @@ func ReadTable(in []byte, s *Scratch) (s2 *Scratch, remain []byte, err error) {
if len(s.dt.single) != tSize { if len(s.dt.single) != tSize {
s.dt.single = make([]dEntrySingle, tSize) s.dt.single = make([]dEntrySingle, tSize)
} }
cTable := s.prevTable
if cap(cTable) < maxSymbolValue+1 {
cTable = make([]cTableEntry, 0, maxSymbolValue+1)
}
cTable = cTable[:maxSymbolValue+1]
s.prevTable = cTable[:s.symbolLen]
s.prevTableLog = s.actualTableLog
for n, w := range s.huffWeight[:s.symbolLen] { for n, w := range s.huffWeight[:s.symbolLen] {
if w == 0 { if w == 0 {
cTable[n] = cTableEntry{
val: 0,
nBits: 0,
}
continue continue
} }
length := (uint32(1) << w) >> 1 length := (uint32(1) << w) >> 1
d := dEntrySingle{ d := dEntrySingle{
entry: uint16(s.actualTableLog+1-w) | (uint16(n) << 8), entry: uint16(s.actualTableLog+1-w) | (uint16(n) << 8),
} }
rank := &rankStats[w] rank := &rankStats[w]
cTable[n] = cTableEntry{
val: uint16(*rank >> (w - 1)),
nBits: uint8(d.entry),
}
single := s.dt.single[*rank : *rank+length] single := s.dt.single[*rank : *rank+length]
for i := range single { for i := range single {
single[i] = d single[i] = d

View File

@ -55,6 +55,9 @@ const (
// ReusePolicyNone will disable re-use of tables. // ReusePolicyNone will disable re-use of tables.
// This is slightly faster than ReusePolicyAllow but may produce larger output. // This is slightly faster than ReusePolicyAllow but may produce larger output.
ReusePolicyNone ReusePolicyNone
// ReusePolicyMust must allow reuse and produce smaller output.
ReusePolicyMust
) )
type Scratch struct { type Scratch struct {

View File

@ -295,7 +295,7 @@ func (b *blockEnc) encodeRaw(a []byte) {
b.output = bh.appendTo(b.output[:0]) b.output = bh.appendTo(b.output[:0])
b.output = append(b.output, a...) b.output = append(b.output, a...)
if debug { if debug {
println("Adding RAW block, length", len(a)) println("Adding RAW block, length", len(a), "last:", b.last)
} }
} }
@ -308,7 +308,7 @@ func (b *blockEnc) encodeRawTo(dst, src []byte) []byte {
dst = bh.appendTo(dst) dst = bh.appendTo(dst)
dst = append(dst, src...) dst = append(dst, src...)
if debug { if debug {
println("Adding RAW block, length", len(src)) println("Adding RAW block, length", len(src), "last:", b.last)
} }
return dst return dst
} }
@ -322,7 +322,7 @@ func (b *blockEnc) encodeLits(raw bool) error {
// Don't compress extremely small blocks // Don't compress extremely small blocks
if len(b.literals) < 32 || raw { if len(b.literals) < 32 || raw {
if debug { if debug {
println("Adding RAW block, length", len(b.literals)) println("Adding RAW block, length", len(b.literals), "last:", b.last)
} }
bh.setType(blockTypeRaw) bh.setType(blockTypeRaw)
b.output = bh.appendTo(b.output) b.output = bh.appendTo(b.output)
@ -349,7 +349,7 @@ func (b *blockEnc) encodeLits(raw bool) error {
switch err { switch err {
case huff0.ErrIncompressible: case huff0.ErrIncompressible:
if debug { if debug {
println("Adding RAW block, length", len(b.literals)) println("Adding RAW block, length", len(b.literals), "last:", b.last)
} }
bh.setType(blockTypeRaw) bh.setType(blockTypeRaw)
b.output = bh.appendTo(b.output) b.output = bh.appendTo(b.output)

View File

@ -190,6 +190,7 @@ func (e *Encoder) nextBlock(final bool) error {
s.filling = s.filling[:0] s.filling = s.filling[:0]
s.headerWritten = true s.headerWritten = true
s.fullFrameWritten = true s.fullFrameWritten = true
s.eofWritten = true
return nil return nil
} }

View File

@ -0,0 +1,37 @@
# 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
addons:
apt:
packages:
- build-essential
# TODO: use the main libseccomp git repo instead of a distro package
- libseccomp2
- libseccomp-dev
install:
- go get -u golang.org/x/lint/golint
# run all of the tests independently, fail if any of the tests error
script:
- make check-syntax
- make lint
- make check

View File

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

View File

@ -1,7 +1,8 @@
libseccomp-golang: Go Language Bindings for the libseccomp Project ![libseccomp Golang Bindings](https://github.com/seccomp/libseccomp-artwork/blob/main/logo/libseccomp-color_text.png)
=============================================================================== ===============================================================================
https://github.com/seccomp/libseccomp-golang https://github.com/seccomp/libseccomp-golang
https://github.com/seccomp/libseccomp
[![Build Status](https://img.shields.io/travis/seccomp/libseccomp-golang/master.svg)](https://travis-ci.org/seccomp/libseccomp-golang)
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
@ -12,40 +13,39 @@ be familiar to, and easily adopted by, application developers.
The libseccomp-golang library provides a Go based interface to the libseccomp The libseccomp-golang library provides a Go based interface to the libseccomp
library. library.
* Online Resources ## Online Resources
The library source repository currently lives on GitHub at the following URLs: The library source repository currently lives on GitHub at the following URLs:
-> https://github.com/seccomp/libseccomp-golang * https://github.com/seccomp/libseccomp-golang
-> https://github.com/seccomp/libseccomp * https://github.com/seccomp/libseccomp
The project mailing list is currently hosted on Google Groups at the URL below, The project mailing list is currently hosted on Google Groups at the URL below,
please note that a Google account is not required to subscribe to the mailing please note that a Google account is not required to subscribe to the mailing
list. list.
-> https://groups.google.com/d/forum/libseccomp * https://groups.google.com/d/forum/libseccomp
Documentation is also available at: Documentation is also available at:
-> https://godoc.org/github.com/seccomp/libseccomp-golang * https://godoc.org/github.com/seccomp/libseccomp-golang
* Installing the package ## Installing the package
The libseccomp-golang bindings require at least Go v1.2.1 and GCC v4.8.4; 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 earlier versions may yield unpredictable results. If you meet these
requirements you can install this package using the command below: requirements you can install this package using the command below:
$ go get github.com/seccomp/libseccomp-golang # go get github.com/seccomp/libseccomp-golang
* Testing the Library ## Testing the Library
A number of tests and lint related recipes are provided in the Makefile, if A number of tests and lint related recipes are provided in the Makefile, if
you want to run the standard regression tests, you can excute the following: you want to run the standard regression tests, you can excute the following:
$ make check # make check
In order to execute the 'make lint' recipe the 'golint' tool is needed, it In order to execute the 'make lint' recipe the 'golint' tool is needed, it
can be found at: can be found at:
-> https://github.com/golang/lint * https://github.com/golang/lint

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

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

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

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

View File

@ -125,7 +125,8 @@ 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 process // ActKill kills the thread that violated the rule. It is the same as ActKillThread.
// All other threads from the same thread group will continue to execute.
ActKill ScmpAction = iota ActKill ScmpAction = iota
// ActTrap throws SIGSYS // ActTrap throws SIGSYS
ActTrap ScmpAction = iota ActTrap ScmpAction = iota
@ -141,6 +142,14 @@ const (
// 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 ScmpAction = iota
// ActKillThread kills the thread that violated the rule. It is the same as ActKill.
// All other threads from the same thread group will continue to execute.
ActKillThread ScmpAction = iota
// ActKillProcess kills the process that violated the rule.
// All threads in the thread group are also terminated.
// This action is only usable when libseccomp API level 3 or higher is
// supported.
ActKillProcess ScmpAction = iota
) )
const ( const (
@ -290,8 +299,10 @@ 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: case ActKill, ActKillThread:
return "Action: Kill Process" return "Action: Kill thread"
case ActKillProcess:
return "Action: Kill process"
case ActTrap: case ActTrap:
return "Action: Send SIGSYS" return "Action: Send SIGSYS"
case ActErrno: case ActErrno:
@ -334,23 +345,23 @@ func GetLibraryVersion() (major, minor, micro uint) {
return verMajor, verMinor, verMicro return verMajor, verMinor, verMicro
} }
// GetApi returns the API level supported by the system. // GetAPI returns the API level supported by the system.
// Returns a positive int containing the API level, or 0 with an error if the // Returns a positive int containing the API level, or 0 with an error if the
// API level could not be detected due to the library being older than v2.4.0. // API level could not be detected due to the library being older than v2.4.0.
// See the seccomp_api_get(3) man page for details on available API levels: // See the seccomp_api_get(3) man page for details on available API levels:
// https://github.com/seccomp/libseccomp/blob/master/doc/man/man3/seccomp_api_get.3 // https://github.com/seccomp/libseccomp/blob/master/doc/man/man3/seccomp_api_get.3
func GetApi() (uint, error) { func GetAPI() (uint, error) {
return getApi() return getAPI()
} }
// SetApi forcibly sets the API level. General use of this function is strongly // SetAPI forcibly sets the API level. General use of this function is strongly
// discouraged. // discouraged.
// Returns an error if the API level could not be set. An error is always // Returns an error if the API level could not be set. An error is always
// returned if the library is older than v2.4.0 // returned if the library is older than v2.4.0
// See the seccomp_api_get(3) man page for details on available API levels: // See the seccomp_api_get(3) man page for details on available API levels:
// https://github.com/seccomp/libseccomp/blob/master/doc/man/man3/seccomp_api_get.3 // https://github.com/seccomp/libseccomp/blob/master/doc/man/man3/seccomp_api_get.3
func SetApi(api uint) error { func SetAPI(api uint) error {
return setApi(api) return setAPI(api)
} }
// Syscall functions // Syscall functions
@ -552,9 +563,8 @@ func (f *ScmpFilter) Reset(defaultAction ScmpAction) error {
return errBadFilter return errBadFilter
} }
retCode := C.seccomp_reset(f.filterCtx, defaultAction.toNative()) if retCode := C.seccomp_reset(f.filterCtx, defaultAction.toNative()); retCode != 0 {
if retCode != 0 { return errRc(retCode)
return syscall.Errno(-1 * retCode)
} }
return nil return nil
@ -600,11 +610,12 @@ func (f *ScmpFilter) Merge(src *ScmpFilter) error {
} }
// Merge the filters // Merge the filters
retCode := C.seccomp_merge(f.filterCtx, src.filterCtx) if retCode := C.seccomp_merge(f.filterCtx, src.filterCtx); retCode != 0 {
if syscall.Errno(-1*retCode) == syscall.EINVAL { e := errRc(retCode)
if e == syscall.EINVAL {
return fmt.Errorf("filters could not be merged due to a mismatch in attributes or invalid filter") return fmt.Errorf("filters could not be merged due to a mismatch in attributes or invalid filter")
} else if retCode != 0 { }
return syscall.Errno(-1 * retCode) return e
} }
src.valid = false src.valid = false
@ -633,12 +644,13 @@ func (f *ScmpFilter) IsArchPresent(arch ScmpArch) (bool, error) {
return false, errBadFilter return false, errBadFilter
} }
retCode := C.seccomp_arch_exist(f.filterCtx, arch.toNative()) if retCode := C.seccomp_arch_exist(f.filterCtx, arch.toNative()); retCode != 0 {
if syscall.Errno(-1*retCode) == syscall.EEXIST { e := errRc(retCode)
if e == syscall.EEXIST {
// -EEXIST is "arch not present" // -EEXIST is "arch not present"
return false, nil return false, nil
} else if retCode != 0 { }
return false, syscall.Errno(-1 * retCode) return false, e
} }
return true, nil return true, nil
@ -661,9 +673,10 @@ func (f *ScmpFilter) AddArch(arch ScmpArch) error {
// Libseccomp returns -EEXIST if the specified architecture is already // Libseccomp returns -EEXIST if the specified architecture is already
// present. Succeed silently in this case, as it's not fatal, and the // present. Succeed silently in this case, as it's not fatal, and the
// architecture is present already. // architecture is present already.
retCode := C.seccomp_arch_add(f.filterCtx, arch.toNative()) if retCode := C.seccomp_arch_add(f.filterCtx, arch.toNative()); retCode != 0 {
if retCode != 0 && syscall.Errno(-1*retCode) != syscall.EEXIST { if e := errRc(retCode); e != syscall.EEXIST {
return syscall.Errno(-1 * retCode) return e
}
} }
return nil return nil
@ -686,9 +699,10 @@ func (f *ScmpFilter) RemoveArch(arch ScmpArch) error {
// Similar to AddArch, -EEXIST is returned if the arch is not present // Similar to AddArch, -EEXIST is returned if the arch is not present
// Succeed silently in that case, this is not fatal and the architecture // Succeed silently in that case, this is not fatal and the architecture
// is not present in the filter after RemoveArch // is not present in the filter after RemoveArch
retCode := C.seccomp_arch_remove(f.filterCtx, arch.toNative()) if retCode := C.seccomp_arch_remove(f.filterCtx, arch.toNative()); retCode != 0 {
if retCode != 0 && syscall.Errno(-1*retCode) != syscall.EEXIST { if e := errRc(retCode); e != syscall.EEXIST {
return syscall.Errno(-1 * retCode) return e
}
} }
return nil return nil
@ -705,7 +719,7 @@ func (f *ScmpFilter) Load() error {
} }
if retCode := C.seccomp_load(f.filterCtx); retCode != 0 { if retCode := C.seccomp_load(f.filterCtx); retCode != 0 {
return syscall.Errno(-1 * retCode) return errRc(retCode)
} }
return nil return nil
@ -764,7 +778,7 @@ 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 {
api, apiErr := getApi() api, apiErr := getAPI()
if (apiErr != nil && api == 0) || (apiErr == nil && api < 3) { if (apiErr != nil && api == 0) || (apiErr == nil && api < 3) {
return false, fmt.Errorf("getting the log bit is only supported in libseccomp 2.4.0 and newer with API level 3 or higher") return false, fmt.Errorf("getting the log bit is only supported in libseccomp 2.4.0 and newer with API level 3 or higher")
} }
@ -818,7 +832,7 @@ func (f *ScmpFilter) SetLogBit(state bool) error {
err := f.setFilterAttr(filterAttrLog, toSet) err := f.setFilterAttr(filterAttrLog, toSet)
if err != nil { if err != nil {
api, apiErr := getApi() api, apiErr := getAPI()
if (apiErr != nil && api == 0) || (apiErr == nil && api < 3) { if (apiErr != nil && api == 0) || (apiErr == nil && api < 3) {
return fmt.Errorf("setting the log bit is only supported in libseccomp 2.4.0 and newer with API level 3 or higher") return fmt.Errorf("setting the log bit is only supported in libseccomp 2.4.0 and newer with API level 3 or higher")
} }
@ -842,7 +856,7 @@ func (f *ScmpFilter) SetSyscallPriority(call ScmpSyscall, priority uint8) error
if retCode := C.seccomp_syscall_priority(f.filterCtx, C.int(call), if retCode := C.seccomp_syscall_priority(f.filterCtx, C.int(call),
C.uint8_t(priority)); retCode != 0 { C.uint8_t(priority)); retCode != 0 {
return syscall.Errno(-1 * retCode) return errRc(retCode)
} }
return nil return nil
@ -907,7 +921,7 @@ func (f *ScmpFilter) ExportPFC(file *os.File) error {
} }
if retCode := C.seccomp_export_pfc(f.filterCtx, C.int(fd)); retCode != 0 { if retCode := C.seccomp_export_pfc(f.filterCtx, C.int(fd)); retCode != 0 {
return syscall.Errno(-1 * retCode) return errRc(retCode)
} }
return nil return nil
@ -928,7 +942,7 @@ func (f *ScmpFilter) ExportBPF(file *os.File) error {
} }
if retCode := C.seccomp_export_bpf(f.filterCtx, C.int(fd)); retCode != 0 { if retCode := C.seccomp_export_bpf(f.filterCtx, C.int(fd)); retCode != 0 {
return syscall.Errno(-1 * retCode) return errRc(retCode)
} }
return nil return nil

View File

@ -72,7 +72,17 @@ const uint32_t C_ARCH_S390X = SCMP_ARCH_S390X;
#define SCMP_ACT_LOG 0x7ffc0000U #define SCMP_ACT_LOG 0x7ffc0000U
#endif #endif
#ifndef SCMP_ACT_KILL_PROCESS
#define SCMP_ACT_KILL_PROCESS 0x80000000U
#endif
#ifndef SCMP_ACT_KILL_THREAD
#define SCMP_ACT_KILL_THREAD 0x00000000U
#endif
const uint32_t C_ACT_KILL = SCMP_ACT_KILL; const uint32_t C_ACT_KILL = SCMP_ACT_KILL;
const uint32_t C_ACT_KILL_PROCESS = SCMP_ACT_KILL_PROCESS;
const uint32_t C_ACT_KILL_THREAD = SCMP_ACT_KILL_THREAD;
const uint32_t C_ACT_TRAP = SCMP_ACT_TRAP; const uint32_t C_ACT_TRAP = SCMP_ACT_TRAP;
const uint32_t C_ACT_ERRNO = SCMP_ACT_ERRNO(0); const uint32_t C_ACT_ERRNO = SCMP_ACT_ERRNO(0);
const uint32_t C_ACT_TRACE = SCMP_ACT_TRACE(0); const uint32_t C_ACT_TRACE = SCMP_ACT_TRACE(0);
@ -203,7 +213,7 @@ const (
archEnd ScmpArch = ArchS390X archEnd ScmpArch = ArchS390X
// Comparison boundaries to check for action validity // Comparison boundaries to check for action validity
actionStart ScmpAction = ActKill actionStart ScmpAction = ActKill
actionEnd ScmpAction = ActLog 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
compareOpEnd ScmpCompareOp = CompareMaskedEqual compareOpEnd ScmpCompareOp = CompareMaskedEqual
@ -236,7 +246,7 @@ func ensureSupportedVersion() error {
} }
// Get the API level // Get the API level
func getApi() (uint, error) { func getAPI() (uint, error) {
api := C.seccomp_api_get() api := C.seccomp_api_get()
if api == 0 { if api == 0 {
return 0, fmt.Errorf("API level operations are not supported") return 0, fmt.Errorf("API level operations are not supported")
@ -246,9 +256,9 @@ func getApi() (uint, error) {
} }
// Set the API level // Set the API level
func setApi(api uint) error { func setAPI(api uint) error {
if retCode := C.seccomp_api_set(C.uint(api)); retCode != 0 { if retCode := C.seccomp_api_set(C.uint(api)); retCode != 0 {
if syscall.Errno(-1*retCode) == syscall.EOPNOTSUPP { if errRc(retCode) == syscall.EOPNOTSUPP {
return fmt.Errorf("API level operations are not supported") return fmt.Errorf("API level operations are not supported")
} }
@ -265,6 +275,10 @@ func filterFinalizer(f *ScmpFilter) {
f.Release() f.Release()
} }
func errRc(rc C.int) error {
return syscall.Errno(-1 * rc)
}
// Get a raw filter attribute // Get a raw filter attribute
func (f *ScmpFilter) getFilterAttr(attr scmpFilterAttr) (C.uint32_t, error) { func (f *ScmpFilter) getFilterAttr(attr scmpFilterAttr) (C.uint32_t, error) {
f.lock.Lock() f.lock.Lock()
@ -278,7 +292,7 @@ func (f *ScmpFilter) getFilterAttr(attr scmpFilterAttr) (C.uint32_t, error) {
retCode := C.seccomp_attr_get(f.filterCtx, attr.toNative(), &attribute) retCode := C.seccomp_attr_get(f.filterCtx, attr.toNative(), &attribute)
if retCode != 0 { if retCode != 0 {
return 0x0, syscall.Errno(-1 * retCode) return 0x0, errRc(retCode)
} }
return attribute, nil return attribute, nil
@ -295,7 +309,7 @@ func (f *ScmpFilter) setFilterAttr(attr scmpFilterAttr, value C.uint32_t) error
retCode := C.seccomp_attr_set(f.filterCtx, attr.toNative(), value) retCode := C.seccomp_attr_set(f.filterCtx, attr.toNative(), value)
if retCode != 0 { if retCode != 0 {
return syscall.Errno(-1 * retCode) return errRc(retCode)
} }
return nil return nil
@ -316,14 +330,17 @@ func (f *ScmpFilter) addRuleWrapper(call ScmpSyscall, action ScmpAction, exact b
retCode = C.seccomp_rule_add_array(f.filterCtx, action.toNative(), C.int(call), length, cond) retCode = C.seccomp_rule_add_array(f.filterCtx, action.toNative(), C.int(call), length, cond)
} }
if syscall.Errno(-1*retCode) == syscall.EFAULT { if retCode != 0 {
switch e := errRc(retCode); e {
case syscall.EFAULT:
return fmt.Errorf("unrecognized syscall %#x", int32(call)) return fmt.Errorf("unrecognized syscall %#x", int32(call))
} else if syscall.Errno(-1*retCode) == syscall.EPERM { case syscall.EPERM:
return fmt.Errorf("requested action matches default action of filter") return fmt.Errorf("requested action matches default action of filter")
} else if syscall.Errno(-1*retCode) == syscall.EINVAL { case syscall.EINVAL:
return fmt.Errorf("two checks on same syscall argument") return fmt.Errorf("two checks on same syscall argument")
} else if retCode != 0 { default:
return syscall.Errno(-1 * retCode) return e
}
} }
return nil return nil
@ -517,6 +534,10 @@ func actionFromNative(a C.uint32_t) (ScmpAction, error) {
switch a & 0xFFFF0000 { switch a & 0xFFFF0000 {
case C.C_ACT_KILL: case C.C_ACT_KILL:
return ActKill, nil return ActKill, nil
case C.C_ACT_KILL_PROCESS:
return ActKillProcess, nil
case C.C_ACT_KILL_THREAD:
return ActKillThread, nil
case C.C_ACT_TRAP: case C.C_ACT_TRAP:
return ActTrap, nil return ActTrap, nil
case C.C_ACT_ERRNO: case C.C_ACT_ERRNO:
@ -537,6 +558,10 @@ func (a ScmpAction) toNative() C.uint32_t {
switch a & 0xFFFF { switch a & 0xFFFF {
case ActKill: case ActKill:
return C.C_ACT_KILL return C.C_ACT_KILL
case ActKillProcess:
return C.C_ACT_KILL_PROCESS
case ActKillThread:
return C.C_ACT_KILL_THREAD
case ActTrap: case ActTrap:
return C.C_ACT_TRAP return C.C_ACT_TRAP
case ActErrno: case ActErrno:

10
vendor/modules.txt vendored
View File

@ -84,13 +84,15 @@ github.com/containers/buildah/pkg/secrets
github.com/containers/buildah/pkg/supplemented github.com/containers/buildah/pkg/supplemented
github.com/containers/buildah/pkg/umask github.com/containers/buildah/pkg/umask
github.com/containers/buildah/util github.com/containers/buildah/util
# github.com/containers/common v0.20.3 # github.com/containers/common v0.20.3-0.20200827091701-a550d6a98aa3
github.com/containers/common/pkg/apparmor github.com/containers/common/pkg/apparmor
github.com/containers/common/pkg/apparmor/internal/supported
github.com/containers/common/pkg/auth github.com/containers/common/pkg/auth
github.com/containers/common/pkg/capabilities github.com/containers/common/pkg/capabilities
github.com/containers/common/pkg/cgroupv2 github.com/containers/common/pkg/cgroupv2
github.com/containers/common/pkg/config github.com/containers/common/pkg/config
github.com/containers/common/pkg/retry github.com/containers/common/pkg/retry
github.com/containers/common/pkg/seccomp
github.com/containers/common/pkg/sysinfo github.com/containers/common/pkg/sysinfo
github.com/containers/common/version github.com/containers/common/version
# github.com/containers/conmon v2.0.19+incompatible # github.com/containers/conmon v2.0.19+incompatible
@ -156,7 +158,7 @@ github.com/containers/psgo/internal/dev
github.com/containers/psgo/internal/host github.com/containers/psgo/internal/host
github.com/containers/psgo/internal/proc github.com/containers/psgo/internal/proc
github.com/containers/psgo/internal/process github.com/containers/psgo/internal/process
# github.com/containers/storage v1.23.0 # github.com/containers/storage v1.23.2
github.com/containers/storage github.com/containers/storage
github.com/containers/storage/drivers github.com/containers/storage/drivers
github.com/containers/storage/drivers/aufs github.com/containers/storage/drivers/aufs
@ -325,7 +327,7 @@ github.com/inconshreveable/mousetrap
github.com/ishidawataru/sctp github.com/ishidawataru/sctp
# github.com/json-iterator/go v1.1.10 # github.com/json-iterator/go v1.1.10
github.com/json-iterator/go github.com/json-iterator/go
# github.com/klauspost/compress v1.10.10 # github.com/klauspost/compress v1.10.11
github.com/klauspost/compress/flate github.com/klauspost/compress/flate
github.com/klauspost/compress/fse github.com/klauspost/compress/fse
github.com/klauspost/compress/huff0 github.com/klauspost/compress/huff0
@ -483,7 +485,7 @@ github.com/rootless-containers/rootlesskit/pkg/port/portutil
github.com/safchain/ethtool github.com/safchain/ethtool
# github.com/seccomp/containers-golang v0.6.0 # github.com/seccomp/containers-golang v0.6.0
github.com/seccomp/containers-golang github.com/seccomp/containers-golang
# github.com/seccomp/libseccomp-golang v0.9.1 # github.com/seccomp/libseccomp-golang v0.9.2-0.20200616122406-847368b35ebf
github.com/seccomp/libseccomp-golang github.com/seccomp/libseccomp-golang
# github.com/sirupsen/logrus v1.6.0 # github.com/sirupsen/logrus v1.6.0
github.com/sirupsen/logrus github.com/sirupsen/logrus