diff --git a/go.mod b/go.mod index 6024f48b4..bcd6c9a8a 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.15 require ( github.com/BurntSushi/toml v0.4.1 + github.com/blang/semver v3.5.1+incompatible github.com/containers/image/v5 v5.16.1 github.com/containers/ocicrypt v1.1.2 github.com/containers/storage v1.37.0 @@ -25,7 +26,6 @@ require ( github.com/opencontainers/image-spec v1.0.2-0.20210819154149-5ad6f50d6283 github.com/opencontainers/runc v1.0.2 github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 - github.com/opencontainers/runtime-tools v0.9.0 github.com/opencontainers/selinux v1.9.1 github.com/pkg/errors v0.9.1 github.com/seccomp/libseccomp-golang v0.9.2-0.20200616122406-847368b35ebf @@ -34,6 +34,7 @@ require ( github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.7.0 github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 + github.com/xeipuuv/gojsonschema v1.2.0 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 diff --git a/go.sum b/go.sum index c584f0aed..dbf822de4 100644 --- a/go.sum +++ b/go.sum @@ -637,8 +637,6 @@ github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.m github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= -github.com/opencontainers/runtime-tools v0.9.0 h1:FYgwVsKRI/H9hU32MJ/4MLOzXWodKK5zsQavY8NPMkU= -github.com/opencontainers/runtime-tools v0.9.0/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= diff --git a/vendor/github.com/opencontainers/runtime-tools/error/error.go b/pkg/runtime-tools/error/error.go similarity index 88% rename from vendor/github.com/opencontainers/runtime-tools/error/error.go rename to pkg/runtime-tools/error/error.go index f7eac6639..40ecd845b 100644 --- a/vendor/github.com/opencontainers/runtime-tools/error/error.go +++ b/pkg/runtime-tools/error/error.go @@ -58,27 +58,11 @@ type Error struct { // ParseLevel takes a string level and returns the RFC 2119 compliance level constant. func ParseLevel(level string) (Level, error) { switch strings.ToUpper(level) { - case "MAY": - fallthrough - case "OPTIONAL": + case "MAY", "OPTIONAL": return May, nil - case "SHOULD": - fallthrough - case "SHOULDNOT": - fallthrough - case "RECOMMENDED": - fallthrough - case "NOTRECOMMENDED": + case "SHOULD", "SHOULDNOT", "RECOMMENDED", "NOTRECOMMENDED": //nolint return Should, nil - case "MUST": - fallthrough - case "MUSTNOT": - fallthrough - case "SHALL": - fallthrough - case "SHALLNOT": - fallthrough - case "REQUIRED": + case "MUST", "MUSTNOT", "SHALL", "SHALLNOT", "REQUIRED": return Must, nil } diff --git a/vendor/github.com/opencontainers/runtime-tools/filepath/abs.go b/pkg/runtime-tools/filepath/abs.go similarity index 100% rename from vendor/github.com/opencontainers/runtime-tools/filepath/abs.go rename to pkg/runtime-tools/filepath/abs.go diff --git a/pkg/runtime-tools/filepath/abs_test.go b/pkg/runtime-tools/filepath/abs_test.go new file mode 100644 index 000000000..143e80d3b --- /dev/null +++ b/pkg/runtime-tools/filepath/abs_test.go @@ -0,0 +1,237 @@ +package filepath + +import ( + "fmt" + "path/filepath" + "runtime" + "testing" +) + +func TestAbs(t *testing.T) { + for _, test := range []struct { + os string + path string + cwd string + expected string + }{ + { + os: "linux", + path: "/", + cwd: "/cwd", + expected: "/", + }, + { + os: "linux", + path: "/a", + cwd: "/cwd", + expected: "/a", + }, + { + os: "linux", + path: "/a/", + cwd: "/cwd", + expected: "/a", + }, + { + os: "linux", + path: "//a", + cwd: "/cwd", + expected: "/a", + }, + { + os: "linux", + path: ".", + cwd: "/cwd", + expected: "/cwd", + }, + { + os: "linux", + path: "./c", + cwd: "/a/b", + expected: "/a/b/c", + }, + { + os: "linux", + path: ".//c", + cwd: "/a/b", + expected: "/a/b/c", + }, + { + os: "linux", + path: "../a", + cwd: "/cwd", + expected: "/a", + }, + { + os: "linux", + path: "../../b", + cwd: "/cwd", + expected: "/b", + }, + { + os: "windows", + path: "c:\\", + cwd: "/cwd", + expected: "c:\\", + }, + { + os: "windows", + path: "c:\\a", + cwd: "c:\\cwd", + expected: "c:\\a", + }, + { + os: "windows", + path: "c:\\a\\", + cwd: "c:\\cwd", + expected: "c:\\a", + }, + { + os: "windows", + path: "c:\\\\a", + cwd: "c:\\cwd", + expected: "c:\\a", + }, + { + os: "windows", + path: ".", + cwd: "c:\\cwd", + expected: "c:\\cwd", + }, + { + os: "windows", + path: ".\\c", + cwd: "c:\\a\\b", + expected: "c:\\a\\b\\c", + }, + { + os: "windows", + path: ".\\\\c", + cwd: "c:\\a\\b", + expected: "c:\\a\\b\\c", + }, + { + os: "windows", + path: "..\\a", + cwd: "c:\\cwd", + expected: "c:\\a", + }, + { + os: "windows", + path: "..\\..\\b", + cwd: "c:\\cwd", + expected: "c:\\b", + }, + } { + t.Run( + fmt.Sprintf("Abs(%q,%q,%q)", test.os, test.path, test.cwd), + func(t *testing.T) { + os := test.os //nolint + path := test.path //nolint + cwd := test.cwd //nolint + expected := test.expected //nolint + abs, err := Abs(os, path, cwd) + if err != nil { + t.Error(err) + } else if abs != expected { + t.Errorf("unexpected result: %q (expected %q)", abs, expected) + } + }, + ) + } +} + +func TestIsAbs(t *testing.T) { + for _, test := range []struct { + os string + path string + expected bool + }{ + { + os: "linux", + path: "/", + expected: true, + }, + { + os: "linux", + path: "/a", + expected: true, + }, + { + os: "linux", + path: "//", + expected: true, + }, + { + os: "linux", + path: "//a", + expected: true, + }, + { + os: "linux", + path: ".", + expected: false, + }, + { + os: "linux", + path: "./a", + expected: false, + }, + { + os: "linux", + path: ".//a", + expected: false, + }, + { + os: "linux", + path: "../a", + expected: false, + }, + { + os: "linux", + path: "../../a", + expected: false, + }, + { + os: "windows", + path: "c:\\", + expected: true, + }, + { + os: "windows", + path: "c:\\a", + expected: true, + }, + { + os: "windows", + path: ".", + expected: false, + }, + { + os: "windows", + path: ".\\a", + expected: false, + }, + { + os: "windows", + path: "..\\a", + expected: false, + }, + } { + t.Run( + fmt.Sprintf("IsAbs(%q,%q)", test.os, test.path), + func(t *testing.T) { + abs := IsAbs(test.os, test.path) //nolint + if abs != test.expected { //nolint + t.Errorf("unexpected result: %t (expected %t)", abs, test.expected) //nolint + } + if runtime.GOOS == test.os { //nolint + stdAbs := filepath.IsAbs(test.path) //nolint + if abs != stdAbs { + t.Errorf("non-standard result: %t (%t is standard)", abs, stdAbs) + } + } + }, + ) + } +} diff --git a/vendor/github.com/opencontainers/runtime-tools/filepath/ancestor.go b/pkg/runtime-tools/filepath/ancestor.go similarity index 100% rename from vendor/github.com/opencontainers/runtime-tools/filepath/ancestor.go rename to pkg/runtime-tools/filepath/ancestor.go diff --git a/pkg/runtime-tools/filepath/ancestor_test.go b/pkg/runtime-tools/filepath/ancestor_test.go new file mode 100644 index 000000000..769525359 --- /dev/null +++ b/pkg/runtime-tools/filepath/ancestor_test.go @@ -0,0 +1,211 @@ +package filepath + +import ( + "fmt" + "testing" +) + +func TestIsAncestor(t *testing.T) { + for _, test := range []struct { + os string + pathA string + pathB string + cwd string + expected bool + }{ + { + os: "linux", + pathA: "/", + pathB: "/a", + cwd: "/cwd", + expected: true, + }, + { + os: "linux", + pathA: "/a", + pathB: "/a", + cwd: "/cwd", + expected: false, + }, + { + os: "linux", + pathA: "/a", + pathB: "/", + cwd: "/cwd", + expected: false, + }, + { + os: "linux", + pathA: "/a", + pathB: "/ab", + cwd: "/cwd", + expected: false, + }, + { + os: "linux", + pathA: "/a/", + pathB: "/a", + cwd: "/cwd", + expected: false, + }, + { + os: "linux", + pathA: "//a", + pathB: "/a", + cwd: "/cwd", + expected: false, + }, + { + os: "linux", + pathA: "//a", + pathB: "/a/b", + cwd: "/cwd", + expected: true, + }, + { + os: "linux", + pathA: "/a", + pathB: "/a/", + cwd: "/cwd", + expected: false, + }, + { + os: "linux", + pathA: "/a", + pathB: ".", + cwd: "/cwd", + expected: false, + }, + { + os: "linux", + pathA: "/a", + pathB: "b", + cwd: "/a", + expected: true, + }, + { + os: "linux", + pathA: "/a", + pathB: "../a", + cwd: "/cwd", + expected: false, + }, + { + os: "linux", + pathA: "/a", + pathB: "../a/b", + cwd: "/cwd", + expected: true, + }, + { + os: "windows", + pathA: "c:\\", + pathB: "c:\\a", + cwd: "c:\\cwd", + expected: true, + }, + { + os: "windows", + pathA: "c:\\", + pathB: "d:\\a", + cwd: "c:\\cwd", + expected: false, + }, + { + os: "windows", + pathA: "c:\\", + pathB: ".", + cwd: "d:\\cwd", + expected: false, + }, + { + os: "windows", + pathA: "c:\\a", + pathB: "c:\\a", + cwd: "c:\\cwd", + expected: false, + }, + { + os: "windows", + pathA: "c:\\a", + pathB: "c:\\", + cwd: "c:\\cwd", + expected: false, + }, + { + os: "windows", + pathA: "c:\\a", + pathB: "c:\\ab", + cwd: "c:\\cwd", + expected: false, + }, + { + os: "windows", + pathA: "c:\\a\\", + pathB: "c:\\a", + cwd: "c:\\cwd", + expected: false, + }, + { + os: "windows", + pathA: "c:\\\\a", + pathB: "c:\\a", + cwd: "c:\\cwd", + expected: false, + }, + { + os: "windows", + pathA: "c:\\\\a", + pathB: "c:\\a\\b", + cwd: "c:\\cwd", + expected: true, + }, + { + os: "windows", + pathA: "c:\\a", + pathB: "c:\\a\\", + cwd: "c:\\cwd", + expected: false, + }, + { + os: "windows", + pathA: "c:\\a", + pathB: ".", + cwd: "c:\\cwd", + expected: false, + }, + { + os: "windows", + pathA: "c:\\a", + pathB: "b", + cwd: "c:\\a", + expected: true, + }, + { + os: "windows", + pathA: "c:\\a", + pathB: "..\\a", + cwd: "c:\\cwd", + expected: false, + }, + { + os: "windows", + pathA: "c:\\a", + pathB: "..\\a\\b", + cwd: "c:\\cwd", + expected: true, + }, + } { + t.Run( + fmt.Sprintf("IsAncestor(%q,%q,%q,%q)", test.os, test.pathA, test.pathB, test.cwd), + func(t *testing.T) { + ancestor, err := IsAncestor(test.os, test.pathA, test.pathB, test.cwd) //nolint + if err != nil { + t.Error(err) + } else if ancestor != test.expected { //nolint + t.Errorf("unexpected result: %t", ancestor) + } + }, + ) + } +} diff --git a/vendor/github.com/opencontainers/runtime-tools/filepath/clean.go b/pkg/runtime-tools/filepath/clean.go similarity index 96% rename from vendor/github.com/opencontainers/runtime-tools/filepath/clean.go rename to pkg/runtime-tools/filepath/clean.go index d5dd65ae1..76353fc6c 100644 --- a/vendor/github.com/opencontainers/runtime-tools/filepath/clean.go +++ b/pkg/runtime-tools/filepath/clean.go @@ -13,7 +13,7 @@ func Clean(os, path string) string { // Replace multiple Separator elements with a single one. for i := 0; i < len(elements); i++ { - if len(elements[i]) == 0 { + if elements[i] == "" { elements = append(elements[:i], elements[i+1:]...) i-- } @@ -63,7 +63,7 @@ func Clean(os, path string) string { // If the result of this process is an empty string, Clean returns // the string ".". - if len(cleaned) == 0 { + if cleaned == "" { cleaned = "." } diff --git a/pkg/runtime-tools/filepath/clean_test.go b/pkg/runtime-tools/filepath/clean_test.go new file mode 100644 index 000000000..8186f38e6 --- /dev/null +++ b/pkg/runtime-tools/filepath/clean_test.go @@ -0,0 +1,153 @@ +package filepath + +import ( + "fmt" + "path/filepath" + "runtime" + "testing" +) + +func TestClean(t *testing.T) { + for _, test := range []struct { + os string + path string + expected string + }{ + { + os: "linux", + path: "/", + expected: "/", + }, + { + os: "linux", + path: "//", + expected: "/", + }, + { + os: "linux", + path: "/a", + expected: "/a", + }, + { + os: "linux", + path: "/a/", + expected: "/a", + }, + { + os: "linux", + path: "//a", + expected: "/a", + }, + { + os: "linux", + path: "/..", + expected: "/", + }, + { + os: "linux", + path: "/../a", + expected: "/a", + }, + { + os: "linux", + path: ".", + expected: ".", + }, + { + os: "linux", + path: "./c", + expected: "c", + }, + { + os: "linux", + path: ".././a", + expected: "../a", + }, + { + os: "linux", + path: "a/../b", + expected: "b", + }, + { + os: "linux", + path: "a/..", + expected: ".", + }, + { + os: "windows", + path: "c:\\", + expected: "c:\\", + }, + { + os: "windows", + path: "c:\\\\", + expected: "c:\\", + }, + { + os: "windows", + path: "c:\\a", + expected: "c:\\a", + }, + { + os: "windows", + path: "c:\\a\\", + expected: "c:\\a", + }, + { + os: "windows", + path: "c:\\\\a", + expected: "c:\\a", + }, + { + os: "windows", + path: "c:\\..", + expected: "c:\\", + }, + { + os: "windows", + path: "c:\\..\\a", + expected: "c:\\a", + }, + { + os: "windows", + path: ".", + expected: ".", + }, + { + os: "windows", + path: ".\\c", + expected: "c", + }, + { + os: "windows", + path: "..\\.\\a", + expected: "..\\a", + }, + { + os: "windows", + path: "a\\..\\b", + expected: "b", + }, + { + os: "windows", + path: "a\\..", + expected: ".", + }, + } { + t.Run( + fmt.Sprintf("Clean(%q,%q)", test.os, test.path), + func(t *testing.T) { + clean := Clean(test.os, test.path) //nolint + if clean != test.expected { //nolint + t.Errorf("unexpected result: %q (expected %q)", clean, test.expected) //nolint + } + if runtime.GOOS == test.os { //nolint + stdClean := filepath.Clean(test.path) //nolint + if clean != stdClean { + t.Errorf("non-standard result: %q (%q is standard)", clean, stdClean) + } + } + }, + ) + } +} diff --git a/vendor/github.com/opencontainers/runtime-tools/filepath/doc.go b/pkg/runtime-tools/filepath/doc.go similarity index 100% rename from vendor/github.com/opencontainers/runtime-tools/filepath/doc.go rename to pkg/runtime-tools/filepath/doc.go diff --git a/vendor/github.com/opencontainers/runtime-tools/filepath/join.go b/pkg/runtime-tools/filepath/join.go similarity index 100% rename from vendor/github.com/opencontainers/runtime-tools/filepath/join.go rename to pkg/runtime-tools/filepath/join.go diff --git a/vendor/github.com/opencontainers/runtime-tools/filepath/separator.go b/pkg/runtime-tools/filepath/separator.go similarity index 100% rename from vendor/github.com/opencontainers/runtime-tools/filepath/separator.go rename to pkg/runtime-tools/filepath/separator.go diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/config.go b/pkg/runtime-tools/generate/config.go similarity index 95% rename from vendor/github.com/opencontainers/runtime-tools/generate/config.go rename to pkg/runtime-tools/generate/config.go index f68bdde37..7dbbf20f2 100644 --- a/vendor/github.com/opencontainers/runtime-tools/generate/config.go +++ b/pkg/runtime-tools/generate/config.go @@ -188,21 +188,15 @@ func (g *Generator) initConfigVM() { func (g *Generator) initConfigVMHypervisor() { g.initConfigVM() - if &g.Config.VM.Hypervisor == nil { - g.Config.VM.Hypervisor = rspec.VMHypervisor{} - } + g.Config.VM.Hypervisor = rspec.VMHypervisor{} } func (g *Generator) initConfigVMKernel() { g.initConfigVM() - if &g.Config.VM.Kernel == nil { - g.Config.VM.Kernel = rspec.VMKernel{} - } + g.Config.VM.Kernel = rspec.VMKernel{} } func (g *Generator) initConfigVMImage() { g.initConfigVM() - if &g.Config.VM.Image == nil { - g.Config.VM.Image = rspec.VMImage{} - } + g.Config.VM.Image = rspec.VMImage{} } diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/generate.go b/pkg/runtime-tools/generate/generate.go similarity index 91% rename from vendor/github.com/opencontainers/runtime-tools/generate/generate.go rename to pkg/runtime-tools/generate/generate.go index 6d3268902..28679c60a 100644 --- a/vendor/github.com/opencontainers/runtime-tools/generate/generate.go +++ b/pkg/runtime-tools/generate/generate.go @@ -8,9 +8,9 @@ import ( "os" "strings" + "github.com/containers/common/pkg/runtime-tools/generate/seccomp" + "github.com/containers/common/pkg/runtime-tools/validate" rspec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/opencontainers/runtime-tools/generate/seccomp" - "github.com/opencontainers/runtime-tools/validate" "github.com/syndtr/gocapability/capability" ) @@ -29,6 +29,9 @@ var ( type Generator struct { Config *rspec.Spec HostSpecific bool + // This is used to keep a cache of the ENVs added to improve + // performance when adding a huge number of ENV variables + envMap map[string]int } // ExportOptions have toggles for exporting only certain parts of the specification @@ -38,9 +41,9 @@ type ExportOptions struct { // New creates a configuration Generator with the default // configuration for the target operating system. -func New(os string) (generator Generator, err error) { - if os != "linux" && os != "solaris" && os != "windows" { - return generator, fmt.Errorf("no defaults configured for %s", os) +func New(platform string) (generator Generator, err error) { + if platform != "linux" && platform != "solaris" && platform != "windows" { + return generator, fmt.Errorf("no defaults configured for %s", platform) } config := rspec.Spec{ @@ -48,7 +51,7 @@ func New(os string) (generator Generator, err error) { Hostname: "mrsdalloway", } - if os == "windows" { + if platform == "windows" { config.Process = &rspec.Process{ Args: []string{ "cmd", @@ -69,7 +72,7 @@ func New(os string) (generator Generator, err error) { } } - if os == "linux" || os == "solaris" { + if platform == "linux" || platform == "solaris" { config.Process.User = rspec.User{} config.Process.Env = []string{ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", @@ -85,7 +88,7 @@ func New(os string) (generator Generator, err error) { } } - if os == "linux" { + if platform == "linux" { config.Process.Capabilities = &rspec.LinuxCapabilities{ Bounding: []string{ "CAP_CHOWN", @@ -179,7 +182,7 @@ func New(os string) (generator Generator, err error) { Destination: "/dev", Type: "tmpfs", Source: "tmpfs", - Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"}, + Options: []string{"nosuid", "noexec", "strictatime", "mode=755", "size=65536k"}, }, { Destination: "/dev/pts", @@ -236,7 +239,12 @@ func New(os string) (generator Generator, err error) { } } - return Generator{Config: &config}, nil + envCache := map[string]int{} + if config.Process != nil { + envCache = createEnvCacheMap(config.Process.Env) + } + + return Generator{Config: &config, envMap: envCache}, nil } // NewFromSpec creates a configuration Generator from a given @@ -246,8 +254,14 @@ func New(os string) (generator Generator, err error) { // // generator := Generator{Config: config} func NewFromSpec(config *rspec.Spec) Generator { + envCache := map[string]int{} + if config != nil && config.Process != nil { + envCache = createEnvCacheMap(config.Process.Env) + } + return Generator{ Config: config, + envMap: envCache, } } @@ -273,11 +287,27 @@ func NewFromTemplate(r io.Reader) (Generator, error) { if err := json.NewDecoder(r).Decode(&config); err != nil { return Generator{}, err } + + envCache := map[string]int{} + if config.Process != nil { + envCache = createEnvCacheMap(config.Process.Env) + } + return Generator{ Config: &config, + envMap: envCache, }, nil } +// createEnvCacheMap creates a hash map with the ENV variables given by the config +func createEnvCacheMap(env []string) map[string]int { + envMap := make(map[string]int, len(env)) + for i, val := range env { + envMap[val] = i + } + return envMap +} + // SetSpec sets the configuration in the Generator g. // // Deprecated: Replace with: @@ -414,6 +444,13 @@ func (g *Generator) SetProcessUsername(username string) { g.Config.Process.User.Username = username } +// SetProcessUmask sets g.Config.Process.User.Umask. +func (g *Generator) SetProcessUmask(umask uint32) { + g.initConfigProcess() + u := umask + g.Config.Process.User.Umask = &u +} + // SetProcessGID sets g.Config.Process.User.GID. func (g *Generator) SetProcessGID(gid uint32) { g.initConfigProcess() @@ -456,25 +493,48 @@ func (g *Generator) ClearProcessEnv() { return } g.Config.Process.Env = []string{} + // Clear out the env cache map as well + g.envMap = map[string]int{} } // AddProcessEnv adds name=value into g.Config.Process.Env, or replaces an // existing entry with the given name. func (g *Generator) AddProcessEnv(name, value string) { + if name == "" { + return + } + g.initConfigProcess() + g.addEnv(fmt.Sprintf("%s=%s", name, value), name) +} - env := fmt.Sprintf("%s=%s", name, value) - for idx := range g.Config.Process.Env { - if strings.HasPrefix(g.Config.Process.Env[idx], name+"=") { - g.Config.Process.Env[idx] = env - return - } +// AddMultipleProcessEnv adds multiple name=value into g.Config.Process.Env, or replaces +// existing entries with the given name. +func (g *Generator) AddMultipleProcessEnv(envs []string) { + g.initConfigProcess() + + for _, val := range envs { + split := strings.SplitN(val, "=", 2) + g.addEnv(val, split[0]) + } +} + +// addEnv looks through adds ENV to the Process and checks envMap for +// any duplicates +// This is called by both AddMultipleProcessEnv and AddProcessEnv +func (g *Generator) addEnv(env, key string) { + if idx, ok := g.envMap[key]; ok { + // The ENV exists in the cache, so change its value in g.Config.Process.Env + g.Config.Process.Env[idx] = env + } else { + // else the env doesn't exist, so add it and add it's index to g.envMap + g.Config.Process.Env = append(g.Config.Process.Env, env) + g.envMap[key] = len(g.Config.Process.Env) - 1 } - g.Config.Process.Env = append(g.Config.Process.Env, env) } // AddProcessRlimits adds rlimit into g.Config.Process.Rlimits. -func (g *Generator) AddProcessRlimits(rType string, rHard uint64, rSoft uint64) { +func (g *Generator) AddProcessRlimits(rType string, rHard, rSoft uint64) { g.initConfigProcess() for i, rlimit := range g.Config.Process.Rlimits { if rlimit.Type == rType { @@ -569,7 +629,7 @@ func (g *Generator) SetLinuxResourcesBlockIOLeafWeight(weight uint16) { } // AddLinuxResourcesBlockIOLeafWeightDevice adds or sets g.Config.Linux.Resources.BlockIO.WeightDevice.LeafWeight. -func (g *Generator) AddLinuxResourcesBlockIOLeafWeightDevice(major int64, minor int64, weight uint16) { +func (g *Generator) AddLinuxResourcesBlockIOLeafWeightDevice(major, minor int64, weight uint16) { g.initConfigLinuxResourcesBlockIO() for i, weightDevice := range g.Config.Linux.Resources.BlockIO.WeightDevice { if weightDevice.Major == major && weightDevice.Minor == minor { @@ -584,28 +644,6 @@ func (g *Generator) AddLinuxResourcesBlockIOLeafWeightDevice(major int64, minor g.Config.Linux.Resources.BlockIO.WeightDevice = append(g.Config.Linux.Resources.BlockIO.WeightDevice, *weightDevice) } -// DropLinuxResourcesBlockIOLeafWeightDevice drops a item form g.Config.Linux.Resources.BlockIO.WeightDevice.LeafWeight -func (g *Generator) DropLinuxResourcesBlockIOLeafWeightDevice(major int64, minor int64) { - if g.Config == nil || g.Config.Linux == nil || g.Config.Linux.Resources == nil || g.Config.Linux.Resources.BlockIO == nil { - return - } - - for i, weightDevice := range g.Config.Linux.Resources.BlockIO.WeightDevice { - if weightDevice.Major == major && weightDevice.Minor == minor { - if weightDevice.Weight != nil { - newWeightDevice := new(rspec.LinuxWeightDevice) - newWeightDevice.Major = major - newWeightDevice.Minor = minor - newWeightDevice.Weight = weightDevice.Weight - g.Config.Linux.Resources.BlockIO.WeightDevice[i] = *newWeightDevice - } else { - g.Config.Linux.Resources.BlockIO.WeightDevice = append(g.Config.Linux.Resources.BlockIO.WeightDevice[:i], g.Config.Linux.Resources.BlockIO.WeightDevice[i+1:]...) - } - return - } - } -} - // SetLinuxResourcesBlockIOWeight sets g.Config.Linux.Resources.BlockIO.Weight. func (g *Generator) SetLinuxResourcesBlockIOWeight(weight uint16) { g.initConfigLinuxResourcesBlockIO() @@ -613,7 +651,7 @@ func (g *Generator) SetLinuxResourcesBlockIOWeight(weight uint16) { } // AddLinuxResourcesBlockIOWeightDevice adds or sets g.Config.Linux.Resources.BlockIO.WeightDevice.Weight. -func (g *Generator) AddLinuxResourcesBlockIOWeightDevice(major int64, minor int64, weight uint16) { +func (g *Generator) AddLinuxResourcesBlockIOWeightDevice(major, minor int64, weight uint16) { g.initConfigLinuxResourcesBlockIO() for i, weightDevice := range g.Config.Linux.Resources.BlockIO.WeightDevice { if weightDevice.Major == major && weightDevice.Minor == minor { @@ -628,37 +666,15 @@ func (g *Generator) AddLinuxResourcesBlockIOWeightDevice(major int64, minor int6 g.Config.Linux.Resources.BlockIO.WeightDevice = append(g.Config.Linux.Resources.BlockIO.WeightDevice, *weightDevice) } -// DropLinuxResourcesBlockIOWeightDevice drops a item form g.Config.Linux.Resources.BlockIO.WeightDevice.Weight -func (g *Generator) DropLinuxResourcesBlockIOWeightDevice(major int64, minor int64) { - if g.Config == nil || g.Config.Linux == nil || g.Config.Linux.Resources == nil || g.Config.Linux.Resources.BlockIO == nil { - return - } - - for i, weightDevice := range g.Config.Linux.Resources.BlockIO.WeightDevice { - if weightDevice.Major == major && weightDevice.Minor == minor { - if weightDevice.LeafWeight != nil { - newWeightDevice := new(rspec.LinuxWeightDevice) - newWeightDevice.Major = major - newWeightDevice.Minor = minor - newWeightDevice.LeafWeight = weightDevice.LeafWeight - g.Config.Linux.Resources.BlockIO.WeightDevice[i] = *newWeightDevice - } else { - g.Config.Linux.Resources.BlockIO.WeightDevice = append(g.Config.Linux.Resources.BlockIO.WeightDevice[:i], g.Config.Linux.Resources.BlockIO.WeightDevice[i+1:]...) - } - return - } - } -} - // AddLinuxResourcesBlockIOThrottleReadBpsDevice adds or sets g.Config.Linux.Resources.BlockIO.ThrottleReadBpsDevice. -func (g *Generator) AddLinuxResourcesBlockIOThrottleReadBpsDevice(major int64, minor int64, rate uint64) { +func (g *Generator) AddLinuxResourcesBlockIOThrottleReadBpsDevice(major, minor int64, rate uint64) { g.initConfigLinuxResourcesBlockIO() throttleDevices := addOrReplaceBlockIOThrottleDevice(g.Config.Linux.Resources.BlockIO.ThrottleReadBpsDevice, major, minor, rate) g.Config.Linux.Resources.BlockIO.ThrottleReadBpsDevice = throttleDevices } // DropLinuxResourcesBlockIOThrottleReadBpsDevice drops a item from g.Config.Linux.Resources.BlockIO.ThrottleReadBpsDevice. -func (g *Generator) DropLinuxResourcesBlockIOThrottleReadBpsDevice(major int64, minor int64) { +func (g *Generator) DropLinuxResourcesBlockIOThrottleReadBpsDevice(major, minor int64) { if g.Config == nil || g.Config.Linux == nil || g.Config.Linux.Resources == nil || g.Config.Linux.Resources.BlockIO == nil { return } @@ -668,14 +684,14 @@ func (g *Generator) DropLinuxResourcesBlockIOThrottleReadBpsDevice(major int64, } // AddLinuxResourcesBlockIOThrottleReadIOPSDevice adds or sets g.Config.Linux.Resources.BlockIO.ThrottleReadIOPSDevice. -func (g *Generator) AddLinuxResourcesBlockIOThrottleReadIOPSDevice(major int64, minor int64, rate uint64) { +func (g *Generator) AddLinuxResourcesBlockIOThrottleReadIOPSDevice(major, minor int64, rate uint64) { g.initConfigLinuxResourcesBlockIO() throttleDevices := addOrReplaceBlockIOThrottleDevice(g.Config.Linux.Resources.BlockIO.ThrottleReadIOPSDevice, major, minor, rate) g.Config.Linux.Resources.BlockIO.ThrottleReadIOPSDevice = throttleDevices } // DropLinuxResourcesBlockIOThrottleReadIOPSDevice drops a item from g.Config.Linux.Resources.BlockIO.ThrottleReadIOPSDevice. -func (g *Generator) DropLinuxResourcesBlockIOThrottleReadIOPSDevice(major int64, minor int64) { +func (g *Generator) DropLinuxResourcesBlockIOThrottleReadIOPSDevice(major, minor int64) { if g.Config == nil || g.Config.Linux == nil || g.Config.Linux.Resources == nil || g.Config.Linux.Resources.BlockIO == nil { return } @@ -685,14 +701,14 @@ func (g *Generator) DropLinuxResourcesBlockIOThrottleReadIOPSDevice(major int64, } // AddLinuxResourcesBlockIOThrottleWriteBpsDevice adds or sets g.Config.Linux.Resources.BlockIO.ThrottleWriteBpsDevice. -func (g *Generator) AddLinuxResourcesBlockIOThrottleWriteBpsDevice(major int64, minor int64, rate uint64) { +func (g *Generator) AddLinuxResourcesBlockIOThrottleWriteBpsDevice(major, minor int64, rate uint64) { g.initConfigLinuxResourcesBlockIO() throttleDevices := addOrReplaceBlockIOThrottleDevice(g.Config.Linux.Resources.BlockIO.ThrottleWriteBpsDevice, major, minor, rate) g.Config.Linux.Resources.BlockIO.ThrottleWriteBpsDevice = throttleDevices } // DropLinuxResourcesBlockIOThrottleWriteBpsDevice drops a item from g.Config.Linux.Resources.BlockIO.ThrottleWriteBpsDevice. -func (g *Generator) DropLinuxResourcesBlockIOThrottleWriteBpsDevice(major int64, minor int64) { +func (g *Generator) DropLinuxResourcesBlockIOThrottleWriteBpsDevice(major, minor int64) { if g.Config == nil || g.Config.Linux == nil || g.Config.Linux.Resources == nil || g.Config.Linux.Resources.BlockIO == nil { return } @@ -702,14 +718,14 @@ func (g *Generator) DropLinuxResourcesBlockIOThrottleWriteBpsDevice(major int64, } // AddLinuxResourcesBlockIOThrottleWriteIOPSDevice adds or sets g.Config.Linux.Resources.BlockIO.ThrottleWriteIOPSDevice. -func (g *Generator) AddLinuxResourcesBlockIOThrottleWriteIOPSDevice(major int64, minor int64, rate uint64) { +func (g *Generator) AddLinuxResourcesBlockIOThrottleWriteIOPSDevice(major, minor int64, rate uint64) { g.initConfigLinuxResourcesBlockIO() throttleDevices := addOrReplaceBlockIOThrottleDevice(g.Config.Linux.Resources.BlockIO.ThrottleWriteIOPSDevice, major, minor, rate) g.Config.Linux.Resources.BlockIO.ThrottleWriteIOPSDevice = throttleDevices } // DropLinuxResourcesBlockIOThrottleWriteIOPSDevice drops a item from g.Config.Linux.Resources.BlockIO.ThrottleWriteIOPSDevice. -func (g *Generator) DropLinuxResourcesBlockIOThrottleWriteIOPSDevice(major int64, minor int64) { +func (g *Generator) DropLinuxResourcesBlockIOThrottleWriteIOPSDevice(major, minor int64) { if g.Config == nil || g.Config.Linux == nil || g.Config.Linux.Resources == nil || g.Config.Linux.Resources.BlockIO == nil { return } @@ -1082,7 +1098,7 @@ func (g *Generator) AddProcessCapability(c string) error { var foundAmbient, foundBounding, foundEffective, foundInheritable, foundPermitted bool for _, cap := range g.Config.Process.Capabilities.Ambient { - if strings.ToUpper(cap) == cp { + if strings.EqualFold(cap, cp) { foundAmbient = true break } @@ -1092,7 +1108,7 @@ func (g *Generator) AddProcessCapability(c string) error { } for _, cap := range g.Config.Process.Capabilities.Bounding { - if strings.ToUpper(cap) == cp { + if strings.EqualFold(cap, cp) { foundBounding = true break } @@ -1102,7 +1118,7 @@ func (g *Generator) AddProcessCapability(c string) error { } for _, cap := range g.Config.Process.Capabilities.Effective { - if strings.ToUpper(cap) == cp { + if strings.EqualFold(cap, cp) { foundEffective = true break } @@ -1112,7 +1128,7 @@ func (g *Generator) AddProcessCapability(c string) error { } for _, cap := range g.Config.Process.Capabilities.Inheritable { - if strings.ToUpper(cap) == cp { + if strings.EqualFold(cap, cp) { foundInheritable = true break } @@ -1122,7 +1138,7 @@ func (g *Generator) AddProcessCapability(c string) error { } for _, cap := range g.Config.Process.Capabilities.Permitted { - if strings.ToUpper(cap) == cp { + if strings.EqualFold(cap, cp) { foundPermitted = true break } @@ -1145,7 +1161,7 @@ func (g *Generator) AddProcessCapabilityAmbient(c string) error { var foundAmbient bool for _, cap := range g.Config.Process.Capabilities.Ambient { - if strings.ToUpper(cap) == cp { + if strings.EqualFold(cap, cp) { foundAmbient = true break } @@ -1169,7 +1185,7 @@ func (g *Generator) AddProcessCapabilityBounding(c string) error { var foundBounding bool for _, cap := range g.Config.Process.Capabilities.Bounding { - if strings.ToUpper(cap) == cp { + if strings.EqualFold(cap, cp) { foundBounding = true break } @@ -1192,7 +1208,7 @@ func (g *Generator) AddProcessCapabilityEffective(c string) error { var foundEffective bool for _, cap := range g.Config.Process.Capabilities.Effective { - if strings.ToUpper(cap) == cp { + if strings.EqualFold(cap, cp) { foundEffective = true break } @@ -1215,7 +1231,7 @@ func (g *Generator) AddProcessCapabilityInheritable(c string) error { var foundInheritable bool for _, cap := range g.Config.Process.Capabilities.Inheritable { - if strings.ToUpper(cap) == cp { + if strings.EqualFold(cap, cp) { foundInheritable = true break } @@ -1238,7 +1254,7 @@ func (g *Generator) AddProcessCapabilityPermitted(c string) error { var foundPermitted bool for _, cap := range g.Config.Process.Capabilities.Permitted { - if strings.ToUpper(cap) == cp { + if strings.EqualFold(cap, cp) { foundPermitted = true break } @@ -1258,27 +1274,27 @@ func (g *Generator) DropProcessCapability(c string) error { cp := strings.ToUpper(c) for i, cap := range g.Config.Process.Capabilities.Ambient { - if strings.ToUpper(cap) == cp { + if strings.EqualFold(cap, cp) { g.Config.Process.Capabilities.Ambient = removeFunc(g.Config.Process.Capabilities.Ambient, i) } } for i, cap := range g.Config.Process.Capabilities.Bounding { - if strings.ToUpper(cap) == cp { + if strings.EqualFold(cap, cp) { g.Config.Process.Capabilities.Bounding = removeFunc(g.Config.Process.Capabilities.Bounding, i) } } for i, cap := range g.Config.Process.Capabilities.Effective { - if strings.ToUpper(cap) == cp { + if strings.EqualFold(cap, cp) { g.Config.Process.Capabilities.Effective = removeFunc(g.Config.Process.Capabilities.Effective, i) } } for i, cap := range g.Config.Process.Capabilities.Inheritable { - if strings.ToUpper(cap) == cp { + if strings.EqualFold(cap, cp) { g.Config.Process.Capabilities.Inheritable = removeFunc(g.Config.Process.Capabilities.Inheritable, i) } } for i, cap := range g.Config.Process.Capabilities.Permitted { - if strings.ToUpper(cap) == cp { + if strings.EqualFold(cap, cp) { g.Config.Process.Capabilities.Permitted = removeFunc(g.Config.Process.Capabilities.Permitted, i) } } @@ -1294,7 +1310,7 @@ func (g *Generator) DropProcessCapabilityAmbient(c string) error { cp := strings.ToUpper(c) for i, cap := range g.Config.Process.Capabilities.Ambient { - if strings.ToUpper(cap) == cp { + if strings.EqualFold(cap, cp) { g.Config.Process.Capabilities.Ambient = removeFunc(g.Config.Process.Capabilities.Ambient, i) } } @@ -1310,7 +1326,7 @@ func (g *Generator) DropProcessCapabilityBounding(c string) error { cp := strings.ToUpper(c) for i, cap := range g.Config.Process.Capabilities.Bounding { - if strings.ToUpper(cap) == cp { + if strings.EqualFold(cap, cp) { g.Config.Process.Capabilities.Bounding = removeFunc(g.Config.Process.Capabilities.Bounding, i) } } @@ -1326,7 +1342,7 @@ func (g *Generator) DropProcessCapabilityEffective(c string) error { cp := strings.ToUpper(c) for i, cap := range g.Config.Process.Capabilities.Effective { - if strings.ToUpper(cap) == cp { + if strings.EqualFold(cap, cp) { g.Config.Process.Capabilities.Effective = removeFunc(g.Config.Process.Capabilities.Effective, i) } } @@ -1342,7 +1358,7 @@ func (g *Generator) DropProcessCapabilityInheritable(c string) error { cp := strings.ToUpper(c) for i, cap := range g.Config.Process.Capabilities.Inheritable { - if strings.ToUpper(cap) == cp { + if strings.EqualFold(cap, cp) { g.Config.Process.Capabilities.Inheritable = removeFunc(g.Config.Process.Capabilities.Inheritable, i) } } @@ -1358,7 +1374,7 @@ func (g *Generator) DropProcessCapabilityPermitted(c string) error { cp := strings.ToUpper(c) for i, cap := range g.Config.Process.Capabilities.Permitted { - if strings.ToUpper(cap) == cp { + if strings.EqualFold(cap, cp) { g.Config.Process.Capabilities.Permitted = removeFunc(g.Config.Process.Capabilities.Permitted, i) } } @@ -1366,7 +1382,7 @@ func (g *Generator) DropProcessCapabilityPermitted(c string) error { return validate.CapValid(cp, false) } -func mapStrToNamespace(ns string, path string) (rspec.LinuxNamespace, error) { +func mapStrToNamespace(ns, path string) (rspec.LinuxNamespace, error) { switch ns { case "network": return rspec.LinuxNamespace{Type: rspec.NetworkNamespace, Path: path}, nil @@ -1397,7 +1413,7 @@ func (g *Generator) ClearLinuxNamespaces() { // AddOrReplaceLinuxNamespace adds or replaces a namespace inside // g.Config.Linux.Namespaces. -func (g *Generator) AddOrReplaceLinuxNamespace(ns string, path string) error { +func (g *Generator) AddOrReplaceLinuxNamespace(ns, path string) error { namespace, err := mapStrToNamespace(ns, path) if err != nil { return err @@ -1442,9 +1458,6 @@ func (g *Generator) AddDevice(device rspec.LinuxDevice) { g.Config.Linux.Devices[i] = device return } - if dev.Type == device.Type && dev.Major == device.Major && dev.Minor == device.Minor { - fmt.Fprintln(os.Stderr, "WARNING: The same type, major and minor should not be used for multiple devices.") - } } g.Config.Linux.Devices = append(g.Config.Linux.Devices, device) @@ -1503,16 +1516,12 @@ func (g *Generator) RemoveLinuxResourcesDevice(allow bool, devType string, major return } } - return } -// strPtr returns the pointer pointing to the string s. -func strPtr(s string) *string { return &s } - // SetSyscallAction adds rules for syscalls with the specified action -func (g *Generator) SetSyscallAction(arguments seccomp.SyscallOpts) error { +func (g *Generator) SetSyscallAction(arguments seccomp.SyscallOpts) error { //nolint g.initConfigLinuxSeccomp() - return seccomp.ParseSyscallFlag(arguments, g.Config.Linux.Seccomp) + return seccomp.ParseSyscallFlag(&arguments, g.Config.Linux.Seccomp) } // SetDefaultSeccompAction sets the default action for all syscalls not defined @@ -1558,7 +1567,7 @@ func (g *Generator) AddLinuxReadonlyPaths(path string) { g.Config.Linux.ReadonlyPaths = append(g.Config.Linux.ReadonlyPaths, path) } -func addOrReplaceBlockIOThrottleDevice(tmpList []rspec.LinuxThrottleDevice, major int64, minor int64, rate uint64) []rspec.LinuxThrottleDevice { +func addOrReplaceBlockIOThrottleDevice(tmpList []rspec.LinuxThrottleDevice, major, minor int64, rate uint64) []rspec.LinuxThrottleDevice { throttleDevices := tmpList for i, throttleDevice := range throttleDevices { if throttleDevice.Major == major && throttleDevice.Minor == minor { @@ -1575,7 +1584,7 @@ func addOrReplaceBlockIOThrottleDevice(tmpList []rspec.LinuxThrottleDevice, majo return throttleDevices } -func dropBlockIOThrottleDevice(tmpList []rspec.LinuxThrottleDevice, major int64, minor int64) []rspec.LinuxThrottleDevice { +func dropBlockIOThrottleDevice(tmpList []rspec.LinuxThrottleDevice, major, minor int64) []rspec.LinuxThrottleDevice { throttleDevices := tmpList for i, throttleDevice := range throttleDevices { if throttleDevice.Major == major && throttleDevice.Minor == minor { @@ -1588,7 +1597,7 @@ func dropBlockIOThrottleDevice(tmpList []rspec.LinuxThrottleDevice, major int64, } // AddSolarisAnet adds network into g.Config.Solaris.Anet -func (g *Generator) AddSolarisAnet(anet rspec.SolarisAnet) { +func (g *Generator) AddSolarisAnet(anet rspec.SolarisAnet) { //nolint g.initConfigSolaris() g.Config.Solaris.Anet = append(g.Config.Solaris.Anet, anet) } @@ -1737,7 +1746,7 @@ func (g *Generator) AddWindowsDevices(id, idType string) error { } // SetWindowsNetwork sets g.Config.Windows.Network. -func (g *Generator) SetWindowsNetwork(network rspec.WindowsNetwork) { +func (g *Generator) SetWindowsNetwork(network rspec.WindowsNetwork) { //nolint g.initConfigWindows() g.Config.Windows.Network = &network } diff --git a/pkg/runtime-tools/generate/generate_test.go b/pkg/runtime-tools/generate/generate_test.go new file mode 100644 index 000000000..ebd510389 --- /dev/null +++ b/pkg/runtime-tools/generate/generate_test.go @@ -0,0 +1,158 @@ +package generate_test + +import ( + "io/ioutil" + "os" + "path/filepath" + "runtime" + "testing" + + rfc2119 "github.com/containers/common/pkg/runtime-tools/error" + "github.com/containers/common/pkg/runtime-tools/generate" + "github.com/containers/common/pkg/runtime-tools/specerror" + "github.com/containers/common/pkg/runtime-tools/validate" + "github.com/stretchr/testify/assert" +) + +// Smoke test to ensure that _at the very least_ our default configuration +// passes the validation tests. If this test fails, something is _very_ wrong +// and needs to be fixed immediately (as it will break downstreams that depend +// on us for a "sane default" and do compliance testing -- such as umoci). +func TestGenerateValid(t *testing.T) { + plat := "linux" + if runtime.GOOS == "windows" { + plat = "windows" + } + + isolations := []string{"process", "hyperv"} + for _, isolation := range isolations { + if plat == "linux" && isolation == "hyperv" { + // Combination doesn't make sense. + continue + } + + bundle, err := ioutil.TempDir("", "TestGenerateValid_bundle") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(bundle) + + // Create our toy bundle. + rootfsPath := filepath.Join(bundle, "rootfs") + if err := os.Mkdir(rootfsPath, 0755); err != nil { + t.Fatal(err) + } + configPath := filepath.Join(bundle, "config.json") + g, err := generate.New(plat) + if err != nil { + t.Fatal(err) + } + if runtime.GOOS == "windows" { + g.AddWindowsLayerFolders("C:\\fakelayer") + g.AddWindowsLayerFolders("C:\\fakescratch") + if isolation == "process" { + // Add the Rootfs section (note: fake volume guid) + g.SetRootPath("\\\\?\\Volume{ec84d99e-3f02-11e7-ac6c-00155d7682cf}\\") + } else { + // Add the Hyper-V section + g.SetWindowsHypervUntilityVMPath("") + } + } + if err := (&g).SaveToFile(configPath, generate.ExportOptions{Seccomp: false}); err != nil { + t.Fatal(err) + } + + // Validate the bundle. + v, err := validate.NewValidatorFromPath(bundle, true, runtime.GOOS) + if err != nil { + t.Errorf("unexpected NewValidatorFromPath error: %+v", err) + } + if err := v.CheckAll(); err != nil { + levelErrors, err := specerror.SplitLevel(err, rfc2119.Must) + if err != nil { + t.Errorf("unexpected non-multierror: %+v", err) + return + } + for _, e := range levelErrors.Warnings { + t.Logf("unexpected warning: %v", e) + } + if err := levelErrors.Error; err != nil { + t.Errorf("unexpected MUST error(s): %+v", err) + } + } + } +} + +func TestRemoveMount(t *testing.T) { + g, err := generate.New("linux") + if err != nil { + t.Fatal(err) + } + size := len(g.Mounts()) + g.RemoveMount("/dev/shm") + if size-1 != len(g.Mounts()) { + t.Errorf("Unable to remove /dev/shm from mounts") + } +} + +func TestEnvCaching(t *testing.T) { + // Start with empty ENV and add a few + g, err := generate.New("windows") + if err != nil { + t.Fatal(err) + } + expected := []string{"k1=v1", "k2=v2"} + g.AddProcessEnv("k1", "v1") + g.AddProcessEnv("k2", "v2") + assert.Equal(t, expected, g.Config.Process.Env) + + // Test override and existing ENV + g, err = generate.New("linux") + if err != nil { + t.Fatal(err) + } + expected = []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "TERM=xterm", "k1=v1", "k2=v4", "k3=v3"} + g.AddProcessEnv("k1", "v1") + g.AddProcessEnv("k2", "v2") + g.AddProcessEnv("k3", "v3") + g.AddProcessEnv("k2", "v4") + assert.Equal(t, expected, g.Config.Process.Env) + + // Test empty ENV + g, err = generate.New("windows") + if err != nil { + t.Fatal(err) + } + g.AddProcessEnv("", "") + assert.Equal(t, []string(nil), g.Config.Process.Env) +} + +func TestMultipleEnvCaching(t *testing.T) { + // Start with empty ENV and add a few + g, err := generate.New("windows") + if err != nil { + t.Fatal(err) + } + newEnvs := []string{"k1=v1", "k2=v2"} + expected := []string{"k1=v1", "k2=v2"} + g.AddMultipleProcessEnv(newEnvs) + assert.Equal(t, expected, g.Config.Process.Env) + + // Test override and existing ENV + g, err = generate.New("linux") + if err != nil { + t.Fatal(err) + } + newEnvs = []string{"k1=v1", "k2=v2", "k3=v3", "k2=v4"} + expected = []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "TERM=xterm", "k1=v1", "k2=v4", "k3=v3"} + g.AddMultipleProcessEnv(newEnvs) + assert.Equal(t, expected, g.Config.Process.Env) + + // Test empty ENV + g, err = generate.New("windows") + if err != nil { + t.Fatal(err) + } + g.AddMultipleProcessEnv([]string{}) + assert.Equal(t, []string(nil), g.Config.Process.Env) +} diff --git a/pkg/runtime-tools/generate/seccomp/consts.go b/pkg/runtime-tools/generate/seccomp/consts.go new file mode 100644 index 000000000..f28d8f587 --- /dev/null +++ b/pkg/runtime-tools/generate/seccomp/consts.go @@ -0,0 +1,7 @@ +package seccomp + +const ( + seccompOverwrite = "overwrite" + seccompAppend = "append" + nothing = "nothing" +) diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_action.go b/pkg/runtime-tools/generate/seccomp/parse_action.go similarity index 96% rename from vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_action.go rename to pkg/runtime-tools/generate/seccomp/parse_action.go index 25daf0752..e323f29e8 100644 --- a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_action.go +++ b/pkg/runtime-tools/generate/seccomp/parse_action.go @@ -20,7 +20,7 @@ type SyscallOpts struct { // ParseSyscallFlag takes a SyscallOpts struct and the seccomp configuration // and sets the new syscall rule accordingly -func ParseSyscallFlag(args SyscallOpts, config *rspec.LinuxSeccomp) error { +func ParseSyscallFlag(args *SyscallOpts, config *rspec.LinuxSeccomp) error { var arguments []string if args.Index != "" && args.Value != "" && args.ValueTwo != "" && args.Operator != "" { arguments = []string{args.Action, args.Syscall, args.Index, args.Value, @@ -127,7 +127,7 @@ func newSyscallStruct(name string, action rspec.LinuxSeccompAction, args []rspec return syscallStruct } -func (s SyscallOpts) argsAreEmpty() bool { +func (s *SyscallOpts) argsAreEmpty() bool { return (s.Index == "" && s.Value == "" && s.ValueTwo == "" && diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_architecture.go b/pkg/runtime-tools/generate/seccomp/parse_architecture.go similarity index 100% rename from vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_architecture.go rename to pkg/runtime-tools/generate/seccomp/parse_architecture.go diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_arguments.go b/pkg/runtime-tools/generate/seccomp/parse_arguments.go similarity index 100% rename from vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_arguments.go rename to pkg/runtime-tools/generate/seccomp/parse_arguments.go diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_remove.go b/pkg/runtime-tools/generate/seccomp/parse_remove.go similarity index 100% rename from vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_remove.go rename to pkg/runtime-tools/generate/seccomp/parse_remove.go diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default.go b/pkg/runtime-tools/generate/seccomp/seccomp_default.go similarity index 96% rename from vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default.go rename to pkg/runtime-tools/generate/seccomp/seccomp_default.go index 5fee5a3b2..1a59235ec 100644 --- a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default.go +++ b/pkg/runtime-tools/generate/seccomp/seccomp_default.go @@ -3,7 +3,6 @@ package seccomp import ( "runtime" - "github.com/opencontainers/runtime-spec/specs-go" rspec "github.com/opencontainers/runtime-spec/specs-go" ) @@ -31,7 +30,7 @@ func arches() []rspec.Arch { } // DefaultProfile defines the whitelist for the default seccomp profile. -func DefaultProfile(rs *specs.Spec) *rspec.LinuxSeccomp { +func DefaultProfile(rs *rspec.Spec) *rspec.LinuxSeccomp { syscalls := []rspec.LinuxSyscall{ { @@ -566,6 +565,20 @@ func DefaultProfile(rs *specs.Spec) *rspec.LinuxSeccomp { }, }...) /* Flags parameter of the clone syscall is the 2nd on s390 */ + syscalls = append(syscalls, []rspec.LinuxSyscall{ + { + Names: []string{"clone"}, + Action: rspec.ActAllow, + Args: []rspec.LinuxSeccompArg{ + { + Index: 1, + Value: 2080505856, + ValueTwo: 0, + Op: rspec.OpMaskedEqual, + }, + }, + }, + }...) } return &rspec.LinuxSeccomp{ diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go b/pkg/runtime-tools/generate/seccomp/seccomp_default_linux.go similarity index 100% rename from vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go rename to pkg/runtime-tools/generate/seccomp/seccomp_default_linux.go diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_unsupported.go b/pkg/runtime-tools/generate/seccomp/seccomp_default_unsupported.go similarity index 100% rename from vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_unsupported.go rename to pkg/runtime-tools/generate/seccomp/seccomp_default_unsupported.go diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go b/pkg/runtime-tools/generate/seccomp/syscall_compare.go similarity index 87% rename from vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go rename to pkg/runtime-tools/generate/seccomp/syscall_compare.go index dbf2aec1c..d725cac30 100644 --- a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go +++ b/pkg/runtime-tools/generate/seccomp/syscall_compare.go @@ -15,7 +15,8 @@ func decideCourseOfAction(newSyscall *rspec.LinuxSyscall, syscalls []rspec.Linux ruleForSyscallAlreadyExists := false var sliceOfDeterminedActions []string - for i, syscall := range syscalls { + for i, s := range syscalls { + syscall := s if sameName(&syscall, newSyscall) { ruleForSyscallAlreadyExists = true @@ -92,22 +93,6 @@ func identical(config1, config2 *rspec.LinuxSyscall) bool { return reflect.DeepEqual(config1, config2) } -func identicalExceptAction(config1, config2 *rspec.LinuxSyscall) bool { - samename := sameName(config1, config2) - sameAction := sameAction(config1, config2) - sameArgs := sameArgs(config1, config2) - - return samename && !sameAction && sameArgs -} - -func identicalExceptArgs(config1, config2 *rspec.LinuxSyscall) bool { - samename := sameName(config1, config2) - sameAction := sameAction(config1, config2) - sameArgs := sameArgs(config1, config2) - - return samename && sameAction && !sameArgs -} - func sameName(config1, config2 *rspec.LinuxSyscall) bool { return reflect.DeepEqual(config1.Names, config2.Names) } diff --git a/vendor/github.com/opencontainers/runtime-tools/specerror/bundle.go b/pkg/runtime-tools/specerror/bundle.go similarity index 93% rename from vendor/github.com/opencontainers/runtime-tools/specerror/bundle.go rename to pkg/runtime-tools/specerror/bundle.go index dbe32af3d..45e5ba6dc 100644 --- a/vendor/github.com/opencontainers/runtime-tools/specerror/bundle.go +++ b/pkg/runtime-tools/specerror/bundle.go @@ -3,7 +3,7 @@ package specerror import ( "fmt" - rfc2119 "github.com/opencontainers/runtime-tools/error" + rfc2119 "github.com/containers/common/pkg/runtime-tools/error" ) // define error codes diff --git a/vendor/github.com/opencontainers/runtime-tools/specerror/config-linux.go b/pkg/runtime-tools/specerror/config-linux.go similarity index 99% rename from vendor/github.com/opencontainers/runtime-tools/specerror/config-linux.go rename to pkg/runtime-tools/specerror/config-linux.go index aa2a284ce..c5dcd5cc1 100644 --- a/vendor/github.com/opencontainers/runtime-tools/specerror/config-linux.go +++ b/pkg/runtime-tools/specerror/config-linux.go @@ -3,7 +3,7 @@ package specerror import ( "fmt" - rfc2119 "github.com/opencontainers/runtime-tools/error" + rfc2119 "github.com/containers/common/pkg/runtime-tools/error" ) // define error codes diff --git a/vendor/github.com/opencontainers/runtime-tools/specerror/config-windows.go b/pkg/runtime-tools/specerror/config-windows.go similarity index 93% rename from vendor/github.com/opencontainers/runtime-tools/specerror/config-windows.go rename to pkg/runtime-tools/specerror/config-windows.go index c8134867d..4d82c5c83 100644 --- a/vendor/github.com/opencontainers/runtime-tools/specerror/config-windows.go +++ b/pkg/runtime-tools/specerror/config-windows.go @@ -3,7 +3,7 @@ package specerror import ( "fmt" - rfc2119 "github.com/opencontainers/runtime-tools/error" + rfc2119 "github.com/containers/common/pkg/runtime-tools/error" ) // define error codes diff --git a/vendor/github.com/opencontainers/runtime-tools/specerror/config.go b/pkg/runtime-tools/specerror/config.go similarity index 75% rename from vendor/github.com/opencontainers/runtime-tools/specerror/config.go rename to pkg/runtime-tools/specerror/config.go index 5357ab59f..1cd5cce4d 100644 --- a/vendor/github.com/opencontainers/runtime-tools/specerror/config.go +++ b/pkg/runtime-tools/specerror/config.go @@ -2,8 +2,6 @@ package specerror import ( "fmt" - - rfc2119 "github.com/opencontainers/runtime-tools/error" ) // define error codes @@ -140,49 +138,3 @@ var ( return fmt.Sprintf(referenceTemplate, version, "config.md#valid-values"), nil } ) - -func init() { - register(SpecVersionInSemVer, rfc2119.Must, specificationVersionRef) - register(RootOnWindowsRequired, rfc2119.Required, rootRef) - register(RootOnHyperVNotSet, rfc2119.Must, rootRef) - register(RootOnNonWindowsRequired, rfc2119.Required, rootRef) - register(RootPathOnWindowsGUID, rfc2119.Must, rootRef) - register(RootPathOnPosixConvention, rfc2119.Should, rootRef) - register(RootPathExist, rfc2119.Must, rootRef) - register(RootReadonlyImplement, rfc2119.Must, rootRef) - register(RootReadonlyOnWindowsFalse, rfc2119.Must, rootRef) - register(MountsInOrder, rfc2119.Must, mountsRef) - register(MountsDestAbs, rfc2119.Must, mountsRef) - register(MountsDestOnWindowsNotNested, rfc2119.Must, mountsRef) - register(MountsOptionsOnWindowsROSupport, rfc2119.Must, mountsRef) - register(ProcRequiredAtStart, rfc2119.Required, processRef) - register(ProcConsoleSizeIgnore, rfc2119.Must, processRef) - register(ProcCwdAbs, rfc2119.Must, processRef) - register(ProcArgsOneEntryRequired, rfc2119.Required, processRef) - register(PosixProcRlimitsTypeGenError, rfc2119.Must, posixProcessRef) - register(PosixProcRlimitsTypeGet, rfc2119.Must, posixProcessRef) - register(PosixProcRlimitsTypeValueError, rfc2119.Should, posixProcessRef) - register(PosixProcRlimitsSoftMatchCur, rfc2119.Must, posixProcessRef) - register(PosixProcRlimitsHardMatchMax, rfc2119.Must, posixProcessRef) - register(PosixProcRlimitsErrorOnDup, rfc2119.Must, posixProcessRef) - register(LinuxProcCapError, rfc2119.Must, linuxProcessRef) - register(LinuxProcOomScoreAdjSet, rfc2119.Must, linuxProcessRef) - register(LinuxProcOomScoreAdjNotSet, rfc2119.Must, linuxProcessRef) - register(PlatformSpecConfOnWindowsSet, rfc2119.Must, platformSpecificConfigurationRef) - register(PosixHooksPathAbs, rfc2119.Must, posixPlatformHooksRef) - register(PosixHooksTimeoutPositive, rfc2119.Must, posixPlatformHooksRef) - register(PosixHooksCalledInOrder, rfc2119.Must, posixPlatformHooksRef) - register(PosixHooksStateToStdin, rfc2119.Must, posixPlatformHooksRef) - register(PrestartTiming, rfc2119.Must, prestartRef) - register(PoststartTiming, rfc2119.Must, poststartRef) - register(PoststopTiming, rfc2119.Must, poststopRef) - register(AnnotationsKeyValueMap, rfc2119.Must, annotationsRef) - register(AnnotationsKeyString, rfc2119.Must, annotationsRef) - register(AnnotationsKeyRequired, rfc2119.Must, annotationsRef) - register(AnnotationsKeyReversedDomain, rfc2119.Should, annotationsRef) - register(AnnotationsKeyReservedNS, rfc2119.Must, annotationsRef) - register(AnnotationsKeyIgnoreUnknown, rfc2119.Must, annotationsRef) - register(AnnotationsValueString, rfc2119.Must, annotationsRef) - register(ExtensibilityIgnoreUnknownProp, rfc2119.Must, extensibilityRef) - register(ValidValues, rfc2119.Must, validValuesRef) -} diff --git a/vendor/github.com/opencontainers/runtime-tools/specerror/error.go b/pkg/runtime-tools/specerror/error.go similarity index 98% rename from vendor/github.com/opencontainers/runtime-tools/specerror/error.go rename to pkg/runtime-tools/specerror/error.go index 5de9492d9..15d8900b7 100644 --- a/vendor/github.com/opencontainers/runtime-tools/specerror/error.go +++ b/pkg/runtime-tools/specerror/error.go @@ -5,8 +5,8 @@ package specerror import ( "fmt" + rfc2119 "github.com/containers/common/pkg/runtime-tools/error" "github.com/hashicorp/go-multierror" - rfc2119 "github.com/opencontainers/runtime-tools/error" ) const referenceTemplate = "https://github.com/opencontainers/runtime-spec/blob/v%s/%s" diff --git a/vendor/github.com/opencontainers/runtime-tools/specerror/runtime-linux.go b/pkg/runtime-tools/specerror/runtime-linux.go similarity index 90% rename from vendor/github.com/opencontainers/runtime-tools/specerror/runtime-linux.go rename to pkg/runtime-tools/specerror/runtime-linux.go index 8eb259ba1..bfc0e3d6d 100644 --- a/vendor/github.com/opencontainers/runtime-tools/specerror/runtime-linux.go +++ b/pkg/runtime-tools/specerror/runtime-linux.go @@ -3,7 +3,7 @@ package specerror import ( "fmt" - rfc2119 "github.com/opencontainers/runtime-tools/error" + rfc2119 "github.com/containers/common/pkg/runtime-tools/error" ) // define error codes diff --git a/vendor/github.com/opencontainers/runtime-tools/specerror/runtime.go b/pkg/runtime-tools/specerror/runtime.go similarity index 80% rename from vendor/github.com/opencontainers/runtime-tools/specerror/runtime.go rename to pkg/runtime-tools/specerror/runtime.go index 383aea63c..abaa1f8ff 100644 --- a/vendor/github.com/opencontainers/runtime-tools/specerror/runtime.go +++ b/pkg/runtime-tools/specerror/runtime.go @@ -3,7 +3,7 @@ package specerror import ( "fmt" - rfc2119 "github.com/opencontainers/runtime-tools/error" + rfc2119 "github.com/containers/common/pkg/runtime-tools/error" ) // define error codes @@ -133,47 +133,90 @@ var ( ) func init() { - register(EntityOperSameContainer, rfc2119.Must, scopeOfAContainerRef) - register(StateIDUniq, rfc2119.Must, stateRef) - register(StateNewStatus, rfc2119.Must, stateRef) + register(AnnotationsKeyIgnoreUnknown, rfc2119.Must, annotationsRef) + register(AnnotationsKeyRequired, rfc2119.Must, annotationsRef) + register(AnnotationsKeyReservedNS, rfc2119.Must, annotationsRef) + register(AnnotationsKeyReversedDomain, rfc2119.Should, annotationsRef) + register(AnnotationsKeyString, rfc2119.Must, annotationsRef) + register(AnnotationsKeyValueMap, rfc2119.Must, annotationsRef) + register(AnnotationsValueString, rfc2119.Must, annotationsRef) + register(ConfigUpdatesWithoutAffect, rfc2119.Must, lifecycleRef) + register(CreateNewContainer, rfc2119.Must, createRef) + register(CreateWithBundlePathAndID, rfc2119.Must, createRef) + register(CreateWithUniqueID, rfc2119.Must, createRef) + register(DefaultOperations, rfc2119.Must, operationsRef) register(DefaultStateJSONPattern, rfc2119.Must, stateRef) - register(EnvCreateImplement, rfc2119.Must, lifecycleRef) + register(DeleteNonStopGenError, rfc2119.Must, deleteRef) + register(DeleteNonStopHaveNoEffect, rfc2119.Must, deleteRef) + register(DeleteOnlyCreatedRes, rfc2119.Must, deleteRef) + register(DeleteResImplement, rfc2119.Must, deleteRef) + register(DeleteWithoutIDGenError, rfc2119.Must, deleteRef) + register(EntityOperSameContainer, rfc2119.Must, scopeOfAContainerRef) register(EnvCreateError, rfc2119.Must, lifecycleRef) - register(ProcNotRunAtResRequest, rfc2119.Must, lifecycleRef) - register(ConfigUpdatesWithoutAffect, rfc2119.Must, lifecycleRef) - register(PrestartHooksInvoke, rfc2119.Must, lifecycleRef) - register(PrestartHookFailGenError, rfc2119.Must, lifecycleRef) - register(ProcImplement, rfc2119.Must, lifecycleRef) - register(PoststartHooksInvoke, rfc2119.Must, lifecycleRef) + register(EnvCreateImplement, rfc2119.Must, lifecycleRef) + register(ErrorsLeaveStateUnchange, rfc2119.Must, errorsRef) + register(ExtensibilityIgnoreUnknownProp, rfc2119.Must, extensibilityRef) + register(KillNonCreateRunGenError, rfc2119.Must, killRef) + register(KillNonCreateRunHaveNoEffect, rfc2119.Must, killRef) + register(KillSignalImplement, rfc2119.Must, killRef) + register(KillWithoutIDGenError, rfc2119.Must, killRef) + register(LinuxProcCapError, rfc2119.Must, linuxProcessRef) + register(LinuxProcOomScoreAdjNotSet, rfc2119.Must, linuxProcessRef) + register(LinuxProcOomScoreAdjSet, rfc2119.Must, linuxProcessRef) + register(MountsDestAbs, rfc2119.Must, mountsRef) + register(MountsDestOnWindowsNotNested, rfc2119.Must, mountsRef) + register(MountsInOrder, rfc2119.Must, mountsRef) + register(MountsOptionsOnWindowsROSupport, rfc2119.Must, mountsRef) + register(PlatformSpecConfOnWindowsSet, rfc2119.Must, platformSpecificConfigurationRef) + register(PosixHooksCalledInOrder, rfc2119.Must, posixPlatformHooksRef) + register(PosixHooksPathAbs, rfc2119.Must, posixPlatformHooksRef) + register(PosixHooksStateToStdin, rfc2119.Must, posixPlatformHooksRef) + register(PosixHooksTimeoutPositive, rfc2119.Must, posixPlatformHooksRef) + register(PosixProcRlimitsErrorOnDup, rfc2119.Must, posixProcessRef) + register(PosixProcRlimitsHardMatchMax, rfc2119.Must, posixProcessRef) + register(PosixProcRlimitsSoftMatchCur, rfc2119.Must, posixProcessRef) + register(PosixProcRlimitsTypeGenError, rfc2119.Must, posixProcessRef) + register(PosixProcRlimitsTypeGet, rfc2119.Must, posixProcessRef) + register(PosixProcRlimitsTypeValueError, rfc2119.Should, posixProcessRef) register(PoststartHookFailGenWarn, rfc2119.Must, lifecycleRef) - register(UndoCreateSteps, rfc2119.Must, lifecycleRef) - register(PoststopHooksInvoke, rfc2119.Must, lifecycleRef) + register(PoststartHooksInvoke, rfc2119.Must, lifecycleRef) + register(PoststartTiming, rfc2119.Must, poststartRef) register(PoststopHookFailGenWarn, rfc2119.Must, lifecycleRef) - register(ErrorsLeaveStateUnchange, rfc2119.Must, errorsRef) - register(WarnsLeaveFlowUnchange, rfc2119.Must, warningsRef) - register(DefaultOperations, rfc2119.Must, operationsRef) - register(QueryWithoutIDGenError, rfc2119.Must, queryStateRef) - register(QueryNonExistGenError, rfc2119.Must, queryStateRef) - register(QueryStateImplement, rfc2119.Must, queryStateRef) - register(CreateWithBundlePathAndID, rfc2119.Must, createRef) - register(CreateWithUniqueID, rfc2119.Must, createRef) - register(CreateNewContainer, rfc2119.Must, createRef) - register(PropsApplyExceptProcOnCreate, rfc2119.Must, createRef) + register(PoststopHooksInvoke, rfc2119.Must, lifecycleRef) + register(PoststopTiming, rfc2119.Must, poststopRef) + register(PrestartHookFailGenError, rfc2119.Must, lifecycleRef) + register(PrestartHooksInvoke, rfc2119.Must, lifecycleRef) + register(PrestartTiming, rfc2119.Must, prestartRef) register(ProcArgsApplyUntilStart, rfc2119.Must, createRef) + register(ProcArgsOneEntryRequired, rfc2119.Required, processRef) + register(ProcConsoleSizeIgnore, rfc2119.Must, processRef) + register(ProcCwdAbs, rfc2119.Must, processRef) + register(ProcImplement, rfc2119.Must, lifecycleRef) + register(ProcNotRunAtResRequest, rfc2119.Must, lifecycleRef) + register(ProcRequiredAtStart, rfc2119.Required, processRef) register(PropApplyFailGenError, rfc2119.Must, createRef) register(PropApplyFailNotCreate, rfc2119.Must, createRef) - register(StartWithoutIDGenError, rfc2119.Must, startRef) - register(StartNotCreatedHaveNoEffect, rfc2119.Must, startRef) + register(PropsApplyExceptProcOnCreate, rfc2119.Must, createRef) + register(QueryNonExistGenError, rfc2119.Must, queryStateRef) + register(QueryStateImplement, rfc2119.Must, queryStateRef) + register(QueryWithoutIDGenError, rfc2119.Must, queryStateRef) + register(RootOnHyperVNotSet, rfc2119.Must, rootRef) + register(RootOnNonWindowsRequired, rfc2119.Required, rootRef) + register(RootOnWindowsRequired, rfc2119.Required, rootRef) + register(RootPathExist, rfc2119.Must, rootRef) + register(RootPathOnPosixConvention, rfc2119.Should, rootRef) + register(RootPathOnWindowsGUID, rfc2119.Must, rootRef) + register(RootReadonlyImplement, rfc2119.Must, rootRef) + register(RootReadonlyOnWindowsFalse, rfc2119.Must, rootRef) + register(SpecVersionInSemVer, rfc2119.Must, specificationVersionRef) register(StartNotCreatedGenError, rfc2119.Must, startRef) + register(StartNotCreatedHaveNoEffect, rfc2119.Must, startRef) register(StartProcImplement, rfc2119.Must, startRef) register(StartWithProcUnsetGenError, rfc2119.Must, startRef) - register(KillWithoutIDGenError, rfc2119.Must, killRef) - register(KillNonCreateRunHaveNoEffect, rfc2119.Must, killRef) - register(KillNonCreateRunGenError, rfc2119.Must, killRef) - register(KillSignalImplement, rfc2119.Must, killRef) - register(DeleteWithoutIDGenError, rfc2119.Must, deleteRef) - register(DeleteNonStopHaveNoEffect, rfc2119.Must, deleteRef) - register(DeleteNonStopGenError, rfc2119.Must, deleteRef) - register(DeleteResImplement, rfc2119.Must, deleteRef) - register(DeleteOnlyCreatedRes, rfc2119.Must, deleteRef) + register(StartWithoutIDGenError, rfc2119.Must, startRef) + register(StateIDUniq, rfc2119.Must, stateRef) + register(StateNewStatus, rfc2119.Must, stateRef) + register(UndoCreateSteps, rfc2119.Must, lifecycleRef) + register(ValidValues, rfc2119.Must, validValuesRef) + register(WarnsLeaveFlowUnchange, rfc2119.Must, warningsRef) } diff --git a/vendor/github.com/opencontainers/runtime-tools/validate/validate.go b/pkg/runtime-tools/validate/validate.go similarity index 90% rename from vendor/github.com/opencontainers/runtime-tools/validate/validate.go rename to pkg/runtime-tools/validate/validate.go index e2e820979..26cfc940f 100644 --- a/vendor/github.com/opencontainers/runtime-tools/validate/validate.go +++ b/pkg/runtime-tools/validate/validate.go @@ -17,13 +17,12 @@ import ( "unicode/utf8" "github.com/blang/semver" + osFilepath "github.com/containers/common/pkg/runtime-tools/filepath" + "github.com/containers/common/pkg/runtime-tools/specerror" "github.com/hashicorp/go-multierror" rspec "github.com/opencontainers/runtime-spec/specs-go" - osFilepath "github.com/opencontainers/runtime-tools/filepath" "github.com/sirupsen/logrus" "github.com/syndtr/gocapability/capability" - - "github.com/opencontainers/runtime-tools/specerror" "github.com/xeipuuv/gojsonschema" ) @@ -96,7 +95,7 @@ func NewValidatorFromPath(bundlePath string, hostSpecific bool, platform string) return Validator{}, fmt.Errorf("%q is not encoded in UTF-8", configPath) } var spec rspec.Spec - if err = json.Unmarshal(content, &spec); err != nil { + if err := json.Unmarshal(content, &spec); err != nil { return Validator{}, err } @@ -132,6 +131,9 @@ func JSONSchemaURL(version string) (url string, err error) { return "", specerror.NewError(specerror.SpecVersionInSemVer, err, rspec.Version) } configRenamedToConfigSchemaVersion, err := semver.Parse("1.0.0-rc2") // config.json became config-schema.json in 1.0.0-rc2 + if err != nil { + return "", err + } if ver.Compare(configRenamedToConfigSchemaVersion) == -1 { return "", fmt.Errorf("unsupported configuration version (older than %s)", configRenamedToConfigSchemaVersion) } @@ -144,18 +146,16 @@ func JSONSchemaURL(version string) (url string, err error) { func (v *Validator) CheckJSONSchema() (errs error) { logrus.Debugf("check JSON schema") - url, err := JSONSchemaURL(v.spec.Version) + url, err := JSONSchemaURL(strings.TrimSuffix(v.spec.Version, "-dev")) if err != nil { - errs = multierror.Append(errs, err) - return errs + return multierror.Append(errs, err) } schemaLoader := gojsonschema.NewReferenceLoader(url) documentLoader := gojsonschema.NewGoLoader(v.spec) result, err := gojsonschema.Validate(schemaLoader, documentLoader) if err != nil { - errs = multierror.Append(errs, err) - return errs + return multierror.Append(errs, err) } if !result.Valid() { @@ -177,16 +177,16 @@ func (v *Validator) CheckRoot() (errs error) { errs = multierror.Append(errs, specerror.NewError(specerror.RootOnHyperVNotSet, fmt.Errorf("for Hyper-V containers, Root must not be set"), rspec.Version)) } - return + return errs } else if v.spec.Root == nil { errs = multierror.Append(errs, specerror.NewError(specerror.RootOnWindowsRequired, fmt.Errorf("on Windows, for Windows Server Containers, this field is REQUIRED"), rspec.Version)) - return + return errs } } else if v.platform != "windows" && v.spec.Root == nil { errs = multierror.Append(errs, specerror.NewError(specerror.RootOnNonWindowsRequired, fmt.Errorf("on all other platforms, this field is REQUIRED"), rspec.Version)) - return + return errs } if v.platform == "windows" { @@ -203,13 +203,12 @@ func (v *Validator) CheckRoot() (errs error) { specerror.NewError(specerror.RootReadonlyOnWindowsFalse, fmt.Errorf("root.readonly field MUST be omitted or false when target platform is windows"), rspec.Version)) } - return + return errs } absBundlePath, err := filepath.Abs(v.bundlePath) if err != nil { - errs = multierror.Append(errs, fmt.Errorf("unable to convert %q to an absolute path", v.bundlePath)) - return + return multierror.Append(errs, fmt.Errorf("unable to convert %q to an absolute path", v.bundlePath)) } if filepath.Base(v.spec.Root.Path) != "rootfs" { @@ -227,8 +226,7 @@ func (v *Validator) CheckRoot() (errs error) { rootfsPath = filepath.Join(v.bundlePath, v.spec.Root.Path) absRootPath, err = filepath.Abs(rootfsPath) if err != nil { - errs = multierror.Append(errs, fmt.Errorf("unable to convert %q to an absolute path", rootfsPath)) - return + return multierror.Append(errs, fmt.Errorf("unable to convert %q to an absolute path", rootfsPath)) } } @@ -246,7 +244,7 @@ func (v *Validator) CheckRoot() (errs error) { specerror.NewError(specerror.ArtifactsInSingleDir, fmt.Errorf("root.path is %q, but it MUST be a child of %q", v.spec.Root.Path, absBundlePath), rspec.Version)) } - return + return errs } // CheckSemVer checks v.spec.Version @@ -263,7 +261,7 @@ func (v *Validator) CheckSemVer() (errs error) { errs = multierror.Append(errs, fmt.Errorf("validate currently only handles version %s, but the supplied configuration targets %s", rspec.Version, version)) } - return + return errs } // CheckHooks check v.spec.Hooks @@ -271,8 +269,7 @@ func (v *Validator) CheckHooks() (errs error) { logrus.Debugf("check hooks") if v.platform != "linux" && v.platform != "solaris" { - errs = multierror.Append(errs, fmt.Errorf("For %q platform, the configuration structure does not support hooks", v.platform)) - return + return multierror.Append(errs, fmt.Errorf("For %q platform, the configuration structure does not support hooks", v.platform)) } if v.spec.Hooks != nil { @@ -281,7 +278,7 @@ func (v *Validator) CheckHooks() (errs error) { errs = multierror.Append(errs, v.checkEventHooks("poststop", v.spec.Hooks.Poststop, v.HostSpecific)) } - return + return errs } func (v *Validator) checkEventHooks(hookType string, hooks []rspec.Hook, hostSpecific bool) (errs error) { @@ -312,7 +309,7 @@ func (v *Validator) checkEventHooks(hookType string, hooks []rspec.Hook, hostSpe } } - return + return errs } // CheckProcess checks v.spec.Process @@ -320,7 +317,7 @@ func (v *Validator) CheckProcess() (errs error) { logrus.Debugf("check process") if v.spec.Process == nil { - return + return nil } process := v.spec.Process @@ -344,25 +341,24 @@ func (v *Validator) CheckProcess() (errs error) { specerror.ProcArgsOneEntryRequired, fmt.Errorf("args must not be empty"), rspec.Version)) - } else { - if filepath.IsAbs(process.Args[0]) && v.spec.Root != nil { - var rootfsPath string - if filepath.IsAbs(v.spec.Root.Path) { - rootfsPath = v.spec.Root.Path - } else { - rootfsPath = filepath.Join(v.bundlePath, v.spec.Root.Path) - } - absPath := filepath.Join(rootfsPath, process.Args[0]) - fileinfo, err := os.Stat(absPath) - if os.IsNotExist(err) { - logrus.Warnf("executable %q is not available in rootfs currently", process.Args[0]) - } else if err != nil { - errs = multierror.Append(errs, err) - } else { - m := fileinfo.Mode() - if m.IsDir() || m&0111 == 0 { - errs = multierror.Append(errs, fmt.Errorf("arg %q is not executable", process.Args[0])) - } + } else if filepath.IsAbs(process.Args[0]) && v.spec.Root != nil { + var rootfsPath string + if filepath.IsAbs(v.spec.Root.Path) { + rootfsPath = v.spec.Root.Path + } else { + rootfsPath = filepath.Join(v.bundlePath, v.spec.Root.Path) + } + absPath := filepath.Join(rootfsPath, process.Args[0]) + fileinfo, err := os.Stat(absPath) + switch { + case os.IsNotExist(err): + logrus.Warnf("executable %q is not available in rootfs currently", process.Args[0]) + case err != nil: + errs = multierror.Append(errs, err) + default: + m := fileinfo.Mode() + if m.IsDir() || m&0111 == 0 { + errs = multierror.Append(errs, fmt.Errorf("arg %q is not executable", process.Args[0])) } } } @@ -385,14 +381,13 @@ func (v *Validator) CheckProcess() (errs error) { } } - return + return errs } // CheckCapabilities checks v.spec.Process.Capabilities func (v *Validator) CheckCapabilities() (errs error) { if v.platform != "linux" { - errs = multierror.Append(errs, fmt.Errorf("For %q platform, the configuration structure does not support process.capabilities", v.platform)) - return + return multierror.Append(errs, fmt.Errorf("For %q platform, the configuration structure does not support process.capabilities", v.platform)) } process := v.spec.Process @@ -447,14 +442,13 @@ func (v *Validator) CheckCapabilities() (errs error) { } } - return + return errs } // CheckRlimits checks v.spec.Process.Rlimits func (v *Validator) CheckRlimits() (errs error) { if v.platform != "linux" && v.platform != "solaris" { - errs = multierror.Append(errs, fmt.Errorf("For %q platform, the configuration structure does not support process.rlimits", v.platform)) - return + return multierror.Append(errs, fmt.Errorf("For %q platform, the configuration structure does not support process.rlimits", v.platform)) } process := v.spec.Process @@ -472,16 +466,16 @@ func (v *Validator) CheckRlimits() (errs error) { errs = multierror.Append(errs, v.rlimitValid(rlimit)) } - return + return errs } -func supportedMountTypes(OS string, hostSpecific bool) (map[string]bool, error) { +func supportedMountTypes(platform string, hostSpecific bool) (map[string]bool, error) { supportedTypes := make(map[string]bool) - if OS != "linux" && OS != "windows" { - logrus.Warnf("%v is not supported to check mount type", OS) + if platform != "linux" && platform != "windows" { + logrus.Warnf("%v is not supported to check mount type", platform) return nil, nil - } else if OS == "windows" { + } else if platform == "windows" { supportedTypes["ntfs"] = true return supportedTypes, nil } @@ -522,8 +516,7 @@ func (v *Validator) CheckMounts() (errs error) { supportedTypes, err := supportedMountTypes(v.platform, v.HostSpecific) if err != nil { - errs = multierror.Append(errs, err) - return + return multierror.Append(errs, err) } for i, mountA := range v.spec.Mounts { @@ -565,7 +558,7 @@ func (v *Validator) CheckMounts() (errs error) { } } - return + return errs } // CheckPlatform checks v.platform @@ -573,8 +566,7 @@ func (v *Validator) CheckPlatform() (errs error) { logrus.Debugf("check platform") if v.platform != "linux" && v.platform != "solaris" && v.platform != "windows" { - errs = multierror.Append(errs, fmt.Errorf("platform %q is not supported", v.platform)) - return + return multierror.Append(errs, fmt.Errorf("platform %q is not supported", v.platform)) } if v.HostSpecific && v.platform != runtime.GOOS { @@ -592,7 +584,7 @@ func (v *Validator) CheckPlatform() (errs error) { } } - return + return errs } // CheckLinuxResources checks v.spec.Linux.Resources @@ -612,8 +604,7 @@ func (v *Validator) CheckLinuxResources() (errs error) { var exist bool interfaces, err := net.Interfaces() if err != nil { - errs = multierror.Append(errs, err) - return + return multierror.Append(errs, err) } for _, prio := range r.Network.Priorities { exist = false @@ -640,8 +631,7 @@ func (v *Validator) CheckLinuxResources() (errs error) { switch access[i] { case 'r', 'w', 'm': default: - errs = multierror.Append(errs, fmt.Errorf("access %s is invalid", r.Devices[index].Access)) - return + return multierror.Append(errs, fmt.Errorf("access %s is invalid", r.Devices[index].Access)) } } } @@ -658,7 +648,7 @@ func (v *Validator) CheckLinuxResources() (errs error) { } } - return + return errs } // CheckAnnotations checks v.spec.Annotations @@ -684,7 +674,7 @@ func (v *Validator) CheckAnnotations() (errs error) { } } - return + return errs } // CapValid checks whether a capability is valid @@ -731,25 +721,26 @@ func (v *Validator) rlimitValid(rlimit rspec.POSIXRlimit) (errs error) { errs = multierror.Append(errs, fmt.Errorf("hard limit of rlimit %s should not be less than soft limit", rlimit.Type)) } - if v.platform == "linux" { + switch v.platform { + case "linux": for _, val := range linuxRlimits { if val == rlimit.Type { - return + return errs } } errs = multierror.Append(errs, specerror.NewError(specerror.PosixProcRlimitsTypeValueError, fmt.Errorf("rlimit type %q may not be valid", rlimit.Type), v.spec.Version)) - } else if v.platform == "solaris" { + case "solaris": for _, val := range posixRlimits { if val == rlimit.Type { - return + return errs } } errs = multierror.Append(errs, specerror.NewError(specerror.PosixProcRlimitsTypeValueError, fmt.Errorf("rlimit type %q may not be valid", rlimit.Type), v.spec.Version)) - } else { + default: logrus.Warnf("process.rlimits validation not yet implemented for platform %q", v.platform) } - return + return errs } func isStruct(t reflect.Type) bool { @@ -760,7 +751,7 @@ func isStructPtr(t reflect.Type) bool { return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct } -func checkMandatoryUnit(field reflect.Value, tagField reflect.StructField, parent string) (errs error) { +func checkMandatoryUnit(field reflect.Value, tagField reflect.StructField, parent string) (errs error) { //nolint mandatory := !strings.Contains(tagField.Tag.Get("json"), "omitempty") switch field.Kind() { case reflect.Ptr: @@ -773,8 +764,7 @@ func checkMandatoryUnit(field reflect.Value, tagField reflect.StructField, paren } case reflect.Slice: if mandatory && (field.IsNil() || field.Len() == 0) { - errs = multierror.Append(errs, fmt.Errorf("'%s.%s' should not be empty", parent, tagField.Name)) - return + return multierror.Append(errs, fmt.Errorf("'%s.%s' should not be empty", parent, tagField.Name)) } for index := 0; index < field.Len(); index++ { mValue := field.Index(index) @@ -784,8 +774,7 @@ func checkMandatoryUnit(field reflect.Value, tagField reflect.StructField, paren } case reflect.Map: if mandatory && (field.IsNil() || field.Len() == 0) { - errs = multierror.Append(errs, fmt.Errorf("'%s.%s' should not be empty", parent, tagField.Name)) - return + return multierror.Append(errs, fmt.Errorf("'%s.%s' should not be empty", parent, tagField.Name)) } keys := field.MapKeys() for index := 0; index < len(keys); index++ { @@ -797,7 +786,7 @@ func checkMandatoryUnit(field reflect.Value, tagField reflect.StructField, paren default: } - return + return errs } func checkMandatory(obj interface{}) (errs error) { @@ -807,7 +796,7 @@ func checkMandatory(obj interface{}) (errs error) { objT = objT.Elem() objV = objV.Elem() } else if !isStruct(objT) { - return + return nil } for i := 0; i < objT.NumField(); i++ { @@ -816,14 +805,16 @@ func checkMandatory(obj interface{}) (errs error) { if !strings.Contains(objT.Field(i).Tag.Get("json"), "omitempty") { errs = multierror.Append(errs, fmt.Errorf("'%s.%s' should not be empty", objT.Name(), objT.Field(i).Name)) } - } else if (isStruct(t) || isStructPtr(t)) && objV.Field(i).CanInterface() { - errs = multierror.Append(errs, checkMandatory(objV.Field(i).Interface())) } else { - errs = multierror.Append(errs, checkMandatoryUnit(objV.Field(i), objT.Field(i), objT.Name())) + if (isStruct(t) || isStructPtr(t)) && objV.Field(i).CanInterface() { + errs = multierror.Append(errs, checkMandatory(objV.Field(i).Interface())) + } else { + errs = multierror.Append(errs, checkMandatoryUnit(objV.Field(i), objT.Field(i), objT.Name())) + } } } - return + return errs } // CheckMandatoryFields checks mandatory field of container's config file diff --git a/vendor/github.com/opencontainers/runtime-tools/validate/validate_linux.go b/pkg/runtime-tools/validate/validate_linux.go similarity index 95% rename from vendor/github.com/opencontainers/runtime-tools/validate/validate_linux.go rename to pkg/runtime-tools/validate/validate_linux.go index dcefafae7..35f38f894 100644 --- a/vendor/github.com/opencontainers/runtime-tools/validate/validate_linux.go +++ b/pkg/runtime-tools/validate/validate_linux.go @@ -10,14 +10,13 @@ import ( "strings" "syscall" - "github.com/syndtr/gocapability/capability" - + osFilepath "github.com/containers/common/pkg/runtime-tools/filepath" + "github.com/containers/common/pkg/runtime-tools/specerror" multierror "github.com/hashicorp/go-multierror" rspec "github.com/opencontainers/runtime-spec/specs-go" - osFilepath "github.com/opencontainers/runtime-tools/filepath" - "github.com/opencontainers/runtime-tools/specerror" "github.com/opencontainers/selinux/go-selinux/label" "github.com/sirupsen/logrus" + "github.com/syndtr/gocapability/capability" ) // LastCap return last cap of system @@ -48,11 +47,11 @@ func deviceValid(d rspec.LinuxDevice) bool { } // CheckLinux checks v.spec.Linux -func (v *Validator) CheckLinux() (errs error) { +func (v *Validator) CheckLinux() (errs error) { //nolint logrus.Debugf("check linux") if v.spec.Linux == nil { - return + return nil } var nsTypeList = map[rspec.LinuxNamespaceType]struct { @@ -75,12 +74,12 @@ func (v *Validator) CheckLinux() (errs error) { } tmpItem := nsTypeList[ns.Type] - tmpItem.num = tmpItem.num + 1 + tmpItem.num++ if tmpItem.num > 1 { errs = multierror.Append(errs, specerror.NewError(specerror.NSErrorOnDup, fmt.Errorf("duplicated namespace %q", ns.Type), rspec.Version)) } - if len(ns.Path) == 0 { + if ns.Path == "" { tmpItem.newExist = true } nsTypeList[ns.Type] = tmpItem @@ -125,11 +124,12 @@ func (v *Validator) CheckLinux() (errs error) { } absPath := filepath.Join(rootfsPath, device.Path) fi, err := os.Stat(absPath) - if os.IsNotExist(err) { + switch { + case os.IsNotExist(err): devList[device.Path] = true - } else if err != nil { + case err != nil: errs = multierror.Append(errs, err) - } else { + default: fStat, ok := fi.Sys().(*syscall.Stat_t) if !ok { errs = multierror.Append(errs, specerror.NewError(specerror.DevicesAvailable, @@ -233,5 +233,5 @@ func (v *Validator) CheckLinux() (errs error) { } } - return + return errs } diff --git a/pkg/runtime-tools/validate/validate_test.go b/pkg/runtime-tools/validate/validate_test.go new file mode 100644 index 000000000..1dcde00b6 --- /dev/null +++ b/pkg/runtime-tools/validate/validate_test.go @@ -0,0 +1,804 @@ +package validate + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "runtime" + "testing" + + "github.com/containers/common/pkg/runtime-tools/specerror" + "github.com/hashicorp/go-multierror" + rspec "github.com/opencontainers/runtime-spec/specs-go" + "github.com/stretchr/testify/assert" +) + +func TestNewValidator(t *testing.T) { + testSpec := &rspec.Spec{} + testBundle := "" + testPlatform := "not" + runtime.GOOS + cases := []struct { + val Validator + expected Validator + }{ + {Validator{testSpec, testBundle, true, runtime.GOOS}, Validator{testSpec, testBundle, true, runtime.GOOS}}, + {Validator{testSpec, testBundle, false, testPlatform}, Validator{testSpec, testBundle, false, testPlatform}}, + } + + for _, c := range cases { + v, err := NewValidator(c.val.spec, c.val.bundlePath, c.val.HostSpecific, c.val.platform) + if err != nil { + t.Errorf("unexpected NewValidator error: %+v", err) + } + assert.Equal(t, c.expected, v) + } +} + +func TestJSONSchema(t *testing.T) { + for _, tt := range []struct { + config *rspec.Spec + error string + }{ + { + config: &rspec.Spec{}, + error: fmt.Sprintf("1 error occurred:\n\t* Version string empty\nRefer to: https://github.com/opencontainers/runtime-spec/blob/v%s/config.md#specification-version\n\n", rspec.Version), + }, + { + config: &rspec.Spec{ + Version: "1.0.1-rc1", + }, + error: "Could not read schema from HTTP, response status is 404 Not Found", + }, + { + config: &rspec.Spec{ + Version: "1.0.0", + }, + error: "", + }, + { + config: &rspec.Spec{ + Version: "1.0.0", + Process: &rspec.Process{}, + }, + error: "1 error occurred:\n\t* args: args is required\n\n", + }, + { + config: &rspec.Spec{ + Version: "1.0.0", + Linux: &rspec.Linux{}, + }, + error: "", + }, + { + config: &rspec.Spec{ + Version: "1.0.0", + Linux: &rspec.Linux{ + RootfsPropagation: "", + }, + }, + error: "", + }, + { + config: &rspec.Spec{ + Version: "1.0.0", + Linux: &rspec.Linux{ + RootfsPropagation: "shared", + }, + }, + error: "", + }, + { + config: &rspec.Spec{ + Version: "1.0.0", + Linux: &rspec.Linux{ + RootfsPropagation: "rshared", + }, + }, + error: "linux.rootfsPropagation: linux.rootfsPropagation must be one of the following: \"private\", \"shared\", \"slave\", \"unbindable\"", + }, + { + config: &rspec.Spec{ + Version: "1.0.0-rc5", + }, + error: "process: process is required", + }, + { + config: &rspec.Spec{ + Version: "1.0.0", + Linux: &rspec.Linux{ + Namespaces: []rspec.LinuxNamespace{ + { + Type: "pid", + }, + }, + }, + }, + error: "", + }, + { + config: &rspec.Spec{ + Version: "1.0.0", + Linux: &rspec.Linux{ + Namespaces: []rspec.LinuxNamespace{ + { + Type: "test", + }, + }, + }, + }, + error: "2 errors occurred:\n\t* linux.namespaces.0: Must validate at least one schema (anyOf)\n\t* linux.namespaces.0.type: linux.namespaces.0.type must be one of the following: \"mount\", \"pid\", \"network\", \"uts\", \"ipc\", \"user\", \"cgroup\"\n\n", + }, + { + config: &rspec.Spec{ + Version: "1.0.0", + Linux: &rspec.Linux{ + Seccomp: &rspec.LinuxSeccomp{ + DefaultAction: "SCMP_ACT_ALLOW", + Architectures: []rspec.Arch{ + "SCMP_ARCH_X86", + "SCMP_ARCH_X32", + }, + }, + }, + }, + error: "", + }, + { + config: &rspec.Spec{ + Version: "1.0.0", + Linux: &rspec.Linux{ + Seccomp: &rspec.LinuxSeccomp{ + DefaultAction: "SCMP_ACT_ALLOW", + Architectures: []rspec.Arch{ + "SCMP_ARCH_X86", + "SCMP_ARCH", + }, + }, + }, + }, + error: "linux.seccomp.architectures.1: linux.seccomp.architectures.1 must be one of the following: \"SCMP_ARCH_X86\", \"SCMP_ARCH_X86_64\", \"SCMP_ARCH_X32\", \"SCMP_ARCH_ARM\", \"SCMP_ARCH_AARCH64\", \"SCMP_ARCH_MIPS\", \"SCMP_ARCH_MIPS64\", \"SCMP_ARCH_MIPS64N32\", \"SCMP_ARCH_MIPSEL\", \"SCMP_ARCH_MIPSEL64\", \"SCMP_ARCH_MIPSEL64N32\", \"SCMP_ARCH_PPC\", \"SCMP_ARCH_PPC64\", \"SCMP_ARCH_PPC64LE\", \"SCMP_ARCH_S390\", \"SCMP_ARCH_S390X\", \"SCMP_ARCH_PARISC\", \"SCMP_ARCH_PARISC64\"", + }, + { + config: &rspec.Spec{ + Version: "1.0.0", + Linux: &rspec.Linux{ + Seccomp: &rspec.LinuxSeccomp{ + DefaultAction: "SCMP_ACT_ALLOW", + Syscalls: []rspec.LinuxSyscall{ + { + Names: []string{"getcwd"}, + Action: "SCMP_ACT_KILL", + }, + }, + }, + }, + }, + error: "", + }, + { + config: &rspec.Spec{ + Version: "1.0.0", + Linux: &rspec.Linux{ + Seccomp: &rspec.LinuxSeccomp{ + DefaultAction: "SCMP_ACT_ALLOW", + Syscalls: []rspec.LinuxSyscall{ + { + Names: []string{"getcwd"}, + Action: "SCMP_ACT", + }, + }, + }, + }, + }, + error: "linux.seccomp.syscalls.0.action: linux.seccomp.syscalls.0.action must be one of the following: \"SCMP_ACT_KILL\", \"SCMP_ACT_TRAP\", \"SCMP_ACT_ERRNO\", \"SCMP_ACT_TRACE\", \"SCMP_ACT_ALLOW\"", + }, + { + config: &rspec.Spec{ + Version: "1.0.0", + Linux: &rspec.Linux{ + Seccomp: &rspec.LinuxSeccomp{ + DefaultAction: "SCMP_ACT_ALLOW", + Syscalls: []rspec.LinuxSyscall{ + { + Names: []string{"getcwd"}, + Action: "SCMP_ACT_KILL", + Args: []rspec.LinuxSeccompArg{ + { + Index: 0, + Value: 2080, + Op: "SCMP_CMP_NE", + }, + }, + }, + }, + }, + }, + }, + error: "", + }, + { + config: &rspec.Spec{ + Version: "1.0.0", + Linux: &rspec.Linux{ + Seccomp: &rspec.LinuxSeccomp{ + DefaultAction: "SCMP_ACT_ALLOW", + Syscalls: []rspec.LinuxSyscall{ + { + Names: []string{"getcwd"}, + Action: "SCMP_ACT_KILL", + Args: []rspec.LinuxSeccompArg{ + { + Index: 0, + Value: 2080, + Op: "SCMP_CMP", + }, + }, + }, + }, + }, + }, + }, + error: "linux.seccomp.syscalls.0.args.0.op: linux.seccomp.syscalls.0.args.0.op must be one of the following: \"SCMP_CMP_NE\", \"SCMP_CMP_LT\", \"SCMP_CMP_LE\", \"SCMP_CMP_EQ\", \"SCMP_CMP_GE\", \"SCMP_CMP_GT\", \"SCMP_CMP_MASKED_EQ\"", + }, + } { + t.Run(tt.error, func(t *testing.T) { + v := &Validator{spec: tt.config} //nolint + errs := v.CheckJSONSchema() + if tt.error == "" { //nolint + if errs == nil { + return + } + t.Fatalf("expected no error, but got: %s", errs.Error()) + } + if errs == nil { + t.Fatal("failed to raise the expected error") + } + merr, ok := errs.(*multierror.Error) + if !ok { + t.Fatalf("non-multierror returned by CheckJSONSchema: %s", errs.Error()) + } + for _, err := range merr.Errors { + if err.Error() == tt.error { //nolint + return + } + } + assert.Equal(t, tt.error, errs.Error()) //nolint + }) + } +} + +func TestCheckRoot(t *testing.T) { + tmpBundle, err := ioutil.TempDir("", "oci-check-rootfspath") + if err != nil { + t.Fatalf("Failed to create a TempDir in 'CheckRoot'") + } + defer os.RemoveAll(tmpBundle) + + rootfsDir := "rootfs/rootfs" + rootfsNonDir := "rootfsfile" + rootfsNonExists := "rootfsnil" + if err := os.MkdirAll(filepath.Join(tmpBundle, rootfsDir), 0700); err != nil { + t.Fatalf("Failed to create a rootfs directory in 'CheckRoot'") + } + if _, err := os.Create(filepath.Join(tmpBundle, rootfsNonDir)); err != nil { + t.Fatalf("Failed to create a non-directory rootfs in 'CheckRoot'") + } + + // Note: Abs error is not tested + cases := []struct { + val rspec.Spec + platform string + expected specerror.Code + }{ + {rspec.Spec{Windows: &rspec.Windows{HyperV: &rspec.WindowsHyperV{}}, Root: &rspec.Root{}}, "windows", specerror.RootOnHyperVNotSet}, + {rspec.Spec{Windows: &rspec.Windows{HyperV: &rspec.WindowsHyperV{}}, Root: nil}, "windows", specerror.NonError}, + {rspec.Spec{Windows: &rspec.Windows{}, Root: &rspec.Root{Path: filepath.Join(tmpBundle, "rootfs")}}, "windows", specerror.RootPathOnWindowsGUID}, + {rspec.Spec{Windows: &rspec.Windows{}, Root: &rspec.Root{Path: "\\\\?\\Volume{ec84d99e-3f02-11e7-ac6c-00155d7682cf}\\"}}, "windows", specerror.NonError}, + {rspec.Spec{Windows: &rspec.Windows{}, Root: nil}, "windows", specerror.RootOnWindowsRequired}, + {rspec.Spec{Root: nil}, "linux", specerror.RootOnNonWindowsRequired}, + {rspec.Spec{Root: &rspec.Root{Path: "maverick-rootfs"}}, "linux", specerror.RootPathOnPosixConvention}, + {rspec.Spec{Root: &rspec.Root{Path: "rootfs"}}, "linux", specerror.NonError}, + {rspec.Spec{Root: &rspec.Root{Path: filepath.Join(tmpBundle, rootfsNonExists)}}, "linux", specerror.RootPathExist}, + {rspec.Spec{Root: &rspec.Root{Path: filepath.Join(tmpBundle, rootfsNonDir)}}, "linux", specerror.RootPathExist}, + {rspec.Spec{Root: &rspec.Root{Path: filepath.Join(tmpBundle, "rootfs")}}, "linux", specerror.NonError}, + {rspec.Spec{Root: &rspec.Root{Path: "rootfs/rootfs"}}, "linux", specerror.ArtifactsInSingleDir}, + {rspec.Spec{Root: &rspec.Root{Readonly: true}}, "windows", specerror.RootReadonlyOnWindowsFalse}, + } + for _, c := range cases { + v, err := NewValidator(&c.val, tmpBundle, false, c.platform) + if err != nil { + t.Errorf("unexpected NewValidator error: %+v", err) + } + err = v.CheckRoot() + assert.Equal(t, c.expected, specerror.FindError(err, c.expected), fmt.Sprintf("Fail to check Root: %v %d", err, c.expected)) + } +} + +func TestCheckSemVer(t *testing.T) { + cases := []struct { + val string + expected specerror.Code + }{ + {rspec.Version, specerror.NonError}, + //FIXME: validate currently only handles rpsec.Version + {"0.0.1", specerror.NonRFCError}, + {"invalid", specerror.SpecVersionInSemVer}, + } + + for _, c := range cases { + v, err := NewValidator(&rspec.Spec{Version: c.val}, "", false, "linux") + if err != nil { + t.Errorf("unexpected NewValidator error: %+v", err) + } + err = v.CheckSemVer() + assert.Equal(t, c.expected, specerror.FindError(err, c.expected), "Fail to check SemVer "+c.val) + } +} + +func TestCheckProcess(t *testing.T) { + cases := []struct { + val rspec.Spec + platform string + expected specerror.Code + }{ + { + val: rspec.Spec{ + Version: "1.0.0", + Process: &rspec.Process{ + Args: []string{"sh"}, + Cwd: "/", + }, + }, + platform: "linux", + expected: specerror.NonError, + }, + { + val: rspec.Spec{ + Version: "1.0.0", + Process: &rspec.Process{ + Args: []string{"sh"}, + Cwd: "/", + }, + }, + platform: "windows", + expected: specerror.ProcCwdAbs, + }, + { + val: rspec.Spec{ + Version: "1.0.0", + Process: &rspec.Process{ + Args: []string{"sh"}, + Cwd: "c:\\foo", + }, + }, + platform: "linux", + expected: specerror.ProcCwdAbs, + }, + { + val: rspec.Spec{ + Version: "1.0.0", + Process: &rspec.Process{ + Args: []string{"sh"}, + Cwd: "c:\\foo", + }, + }, + platform: "windows", + expected: specerror.NonError, + }, + { + val: rspec.Spec{ + Version: "1.0.0", + Process: &rspec.Process{ + Cwd: "/", + }, + }, + platform: "linux", + expected: specerror.ProcArgsOneEntryRequired, + }, + { + val: rspec.Spec{ + Version: "1.0.0", + Process: &rspec.Process{ + Args: []string{"sh"}, + Cwd: "/", + Rlimits: []rspec.POSIXRlimit{ + { + Type: "RLIMIT_NOFILE", + Hard: 1024, + Soft: 1024, + }, + { + Type: "RLIMIT_NPROC", + Hard: 512, + Soft: 512, + }, + }, + }, + }, + platform: "linux", + expected: specerror.NonError, + }, + { + val: rspec.Spec{ + Version: "1.0.0", + Process: &rspec.Process{ + Args: []string{"sh"}, + Cwd: "/", + Rlimits: []rspec.POSIXRlimit{ + { + Type: "RLIMIT_NOFILE", + Hard: 1024, + Soft: 1024, + }, + }, + }, + }, + platform: "solaris", + expected: specerror.NonError, + }, + { + val: rspec.Spec{ + Version: "1.0.0", + Process: &rspec.Process{ + Args: []string{"sh"}, + Cwd: "/", + Rlimits: []rspec.POSIXRlimit{ + { + Type: "RLIMIT_DOES_NOT_EXIST", + Hard: 512, + Soft: 512, + }, + { + Type: "RLIMIT_DOES_NOT_EXIST", + Hard: 512, + Soft: 512, + }, + }, + }, + }, + platform: "linux", + expected: specerror.PosixProcRlimitsErrorOnDup, + }, + { + val: rspec.Spec{ + Version: "1.0.0", + Process: &rspec.Process{ + Args: []string{"sh"}, + Cwd: "/", + Rlimits: []rspec.POSIXRlimit{ + { + Type: "RLIMIT_DOES_NOT_EXIST", + Hard: 512, + Soft: 512, + }, + }, + }, + }, + platform: "linux", + expected: specerror.PosixProcRlimitsTypeValueError, + }, + { + val: rspec.Spec{ + Version: "1.0.0", + Process: &rspec.Process{ + Args: []string{"sh"}, + Cwd: "/", + Rlimits: []rspec.POSIXRlimit{ + { + Type: "RLIMIT_NPROC", + Hard: 512, + Soft: 512, + }, + }, + }, + }, + platform: "solaris", + expected: specerror.PosixProcRlimitsTypeValueError, + }, + } + for _, c := range cases { + v, err := NewValidator(&c.val, ".", false, c.platform) + if err != nil { + t.Errorf("unexpected NewValidator error: %+v", err) + } + err = v.CheckProcess() + assert.Equal(t, c.expected, specerror.FindError(err, c.expected), fmt.Sprintf("failed CheckProcess: %v %d", err, c.expected)) + } +} + +func TestCheckLinux(t *testing.T) { + weightDevices := []rspec.LinuxWeightDevice{ + {}, + } + weightDevices[0].Major = 5 + weightDevices[0].Minor = 0 + + cases := []struct { + val rspec.Spec + expected specerror.Code + }{ + { + val: rspec.Spec{ + Version: "1.0.0", + Linux: &rspec.Linux{ + Namespaces: []rspec.LinuxNamespace{ + { + Type: "pid", + Path: "/proc/test", + }, + { + Type: "network", + }, + }, + }, + }, + expected: specerror.NonError, + }, + { + val: rspec.Spec{ + Version: "1.0.0", + Linux: &rspec.Linux{ + Namespaces: []rspec.LinuxNamespace{ + { + Type: "pid", + Path: "proc", + }, + }, + }, + }, + expected: specerror.NSPathAbs, + }, + { + val: rspec.Spec{ + Version: "1.0.0", + Linux: &rspec.Linux{ + Namespaces: []rspec.LinuxNamespace{ + { + Type: "pid", + }, + { + Type: "pid", + }, + }, + }, + }, + expected: specerror.NSErrorOnDup, + }, + { + val: rspec.Spec{ + Version: "1.0.0", + Linux: &rspec.Linux{ + MaskedPaths: []string{"/proc/kcore"}, + }, + }, + expected: specerror.NonError, + }, + { + val: rspec.Spec{ + Version: "1.0.0", + Linux: &rspec.Linux{ + MaskedPaths: []string{"proc"}, + }, + }, + expected: specerror.MaskedPathsAbs, + }, + { + val: rspec.Spec{ + Version: "1.0.0", + Linux: &rspec.Linux{ + ReadonlyPaths: []string{"/proc/sys"}, + }, + }, + expected: specerror.NonError, + }, + { + val: rspec.Spec{ + Version: "1.0.0", + Linux: &rspec.Linux{ + ReadonlyPaths: []string{"proc"}, + }, + }, + expected: specerror.ReadonlyPathsAbs, + }, + { + val: rspec.Spec{ + Version: "1.0.0", + Linux: &rspec.Linux{ + Resources: &rspec.LinuxResources{ + BlockIO: &rspec.LinuxBlockIO{ + WeightDevice: weightDevices, + }, + }, + }, + }, + expected: specerror.BlkIOWeightOrLeafWeightExist, + }, + } + for _, c := range cases { + v, err := NewValidator(&c.val, ".", false, "linux") + if err != nil { + t.Errorf("unexpected NewValidator error: %+v", err) + } + err = v.CheckLinux() + assert.Equal(t, c.expected, specerror.FindError(err, c.expected), fmt.Sprintf("failed CheckLinux: %v %d", err, c.expected)) + } +} + +func TestCheckPlatform(t *testing.T) { + cases := []struct { + val rspec.Spec + platform string + expected specerror.Code + }{ + { + val: rspec.Spec{ + Version: "1.0.0", + }, + platform: "linux", + expected: specerror.NonError, + }, + { + val: rspec.Spec{ + Version: "1.0.0", + }, + platform: "windows", + expected: specerror.PlatformSpecConfOnWindowsSet, + }, + { + val: rspec.Spec{ + Version: "1.0.0", + Windows: &rspec.Windows{ + LayerFolders: []string{"C:\\Layers\\layer1"}, + }, + }, + platform: "windows", + expected: specerror.NonError, + }, + } + for _, c := range cases { + v, err := NewValidator(&c.val, ".", false, c.platform) + if err != nil { + t.Errorf("unexpected NewValidator error: %+v", err) + } + err = v.CheckPlatform() + assert.Equal(t, c.expected, specerror.FindError(err, c.expected), fmt.Sprintf("failed CheckPlatform: %v %d", err, c.expected)) + } +} + +func TestCheckHooks(t *testing.T) { + cases := []struct { + val rspec.Spec + expected specerror.Code + }{ + { + val: rspec.Spec{ + Version: "1.0.0", + Hooks: &rspec.Hooks{ + Prestart: []rspec.Hook{ + { + Path: "/usr/bin/fix-mounts", + }, + }, + }, + }, + expected: specerror.NonError, + }, + { + val: rspec.Spec{ + Version: "1.0.0", + Hooks: &rspec.Hooks{ + Prestart: []rspec.Hook{ + { + Path: "usr", + }, + }, + }, + }, + expected: specerror.PosixHooksPathAbs, + }, + } + for _, c := range cases { + v, err := NewValidator(&c.val, ".", false, "linux") + if err != nil { + t.Errorf("unexpected NewValidator error: %+v", err) + } + err = v.CheckHooks() + assert.Equal(t, c.expected, specerror.FindError(err, c.expected), fmt.Sprintf("failed CheckHooks: %v %d", err, c.expected)) + } +} + +func TestCheckMandatoryFields(t *testing.T) { + for _, tt := range []struct { + config *rspec.Spec + error string + }{ + { + config: &rspec.Spec{}, + error: "1 error occurred:\n\t* 'Spec.Version' should not be empty\n\n", + }, + { + config: nil, + error: "1 error occurred:\n\t* Spec can't be nil\n\n", + }, + { + config: &rspec.Spec{ + Version: "1.0.0", + }, + error: "", + }, + { + config: &rspec.Spec{ + Version: "1.0.0", + Root: &rspec.Root{}, + }, + error: "1 error occurred:\n\t* 'Root.Path' should not be empty\n\n", + }, + } { + t.Run(tt.error, func(t *testing.T) { + var errs *multierror.Error + v := &Validator{spec: tt.config} // nolint + errs = multierror.Append(errs, v.CheckMandatoryFields()) + if tt.error == "" { //nolint + if errs.ErrorOrNil() == nil { + return + } + t.Fatalf("expected no error, but got: %s", errs.Error()) + } + if errs.ErrorOrNil() == nil { + t.Fatal("failed to raise the expected error") + } + + for _, err := range errs.Errors { + if err.Error() == tt.error { //nolint + return + } + } + assert.Equal(t, tt.error, errs.Error()) //nolint + }) + } +} + +func TestCheckAnnotations(t *testing.T) { + cases := []struct { + val rspec.Spec + expected specerror.Code + }{ + { + val: rspec.Spec{}, + expected: specerror.NonError, + }, + { + val: rspec.Spec{ + Annotations: map[string]string{}, + }, + expected: specerror.NonError, + }, + { + val: rspec.Spec{ + Annotations: map[string]string{"invalid": ""}, + }, + expected: specerror.AnnotationsKeyReversedDomain, + }, + { + val: rspec.Spec{ + Annotations: map[string]string{"org.opencontainers.oci": ""}, + }, + expected: specerror.AnnotationsKeyReservedNS, + }, + { + val: rspec.Spec{ + Annotations: map[string]string{"com.example": ""}, + }, + expected: specerror.NonError, + }, + } + for _, c := range cases { + v, err := NewValidator(&c.val, ".", false, "") + if err != nil { + t.Errorf("unexpected NewValidator error: %+v", err) + } + err = v.CheckAnnotations() + assert.Equal(t, c.expected, specerror.FindError(err, c.expected), fmt.Sprintf("failed CheckAnnotations: %v %d", err, c.expected)) + } +} diff --git a/vendor/github.com/opencontainers/runtime-tools/validate/validate_unsupported.go b/pkg/runtime-tools/validate/validate_unsupported.go similarity index 100% rename from vendor/github.com/opencontainers/runtime-tools/validate/validate_unsupported.go rename to pkg/runtime-tools/validate/validate_unsupported.go diff --git a/pkg/seccomp/seccomp_test.go b/pkg/seccomp/seccomp_test.go index 5fff73396..bbb79954d 100644 --- a/pkg/seccomp/seccomp_test.go +++ b/pkg/seccomp/seccomp_test.go @@ -10,7 +10,7 @@ import ( "io/ioutil" "testing" - "github.com/opencontainers/runtime-tools/generate" + "github.com/containers/common/pkg/runtime-tools/generate" ) func TestLoadProfile(t *testing.T) { diff --git a/vendor/github.com/opencontainers/runtime-tools/LICENSE b/vendor/github.com/opencontainers/runtime-tools/LICENSE deleted file mode 100644 index bdc403653..000000000 --- a/vendor/github.com/opencontainers/runtime-tools/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2015 The Linux Foundation. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go deleted file mode 100644 index eade5718e..000000000 --- a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go +++ /dev/null @@ -1,12 +0,0 @@ -package seccomp - -const ( - seccompOverwrite = "overwrite" - seccompAppend = "append" - nothing = "nothing" - kill = "kill" - trap = "trap" - trace = "trace" - allow = "allow" - errno = "errno" -) diff --git a/vendor/modules.txt b/vendor/modules.txt index 8593d481d..175e17176 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -36,6 +36,7 @@ github.com/acarl005/stripansi # github.com/beorn7/perks v1.0.1 github.com/beorn7/perks/quantile # github.com/blang/semver v3.5.1+incompatible +## explicit github.com/blang/semver # github.com/cespare/xxhash/v2 v2.1.1 github.com/cespare/xxhash/v2 @@ -364,14 +365,6 @@ github.com/opencontainers/runc/libcontainer/utils # github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 ## explicit github.com/opencontainers/runtime-spec/specs-go -# github.com/opencontainers/runtime-tools v0.9.0 -## explicit -github.com/opencontainers/runtime-tools/error -github.com/opencontainers/runtime-tools/filepath -github.com/opencontainers/runtime-tools/generate -github.com/opencontainers/runtime-tools/generate/seccomp -github.com/opencontainers/runtime-tools/specerror -github.com/opencontainers/runtime-tools/validate # github.com/opencontainers/selinux v1.9.1 ## explicit github.com/opencontainers/selinux/go-selinux @@ -444,6 +437,7 @@ github.com/xeipuuv/gojsonpointer # github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 github.com/xeipuuv/gojsonreference # github.com/xeipuuv/gojsonschema v1.2.0 +## explicit github.com/xeipuuv/gojsonschema # go.etcd.io/bbolt v1.3.6 go.etcd.io/bbolt