diff --git a/vendor.conf b/vendor.conf index eb31d055..62b05efc 100644 --- a/vendor.conf +++ b/vendor.conf @@ -20,7 +20,7 @@ github.com/containernetworking/cni v0.4.0 google.golang.org/grpc v1.0.4 https://github.com/grpc/grpc-go github.com/opencontainers/selinux b29023b86e4a69d1b46b7e7b4e2b6fda03f0b9cd github.com/opencontainers/go-digest v1.0.0-rc0 -github.com/opencontainers/runtime-tools 263fad0457d4a42d08aea3fb2bc4da7d2f8c3af7 +github.com/opencontainers/runtime-tools fdbc3d6d9507f699bbfd557dce0640c02b5f60e4 github.com/opencontainers/runc ce80fa0a64803d52883955cb77b2708b438a0b28 github.com/mrunalp/fileutils master github.com/vishvananda/netlink master diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default.go b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default.go index 35b12cd6..5fee5a3b 100644 --- a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default.go +++ b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default.go @@ -2,7 +2,6 @@ package seccomp import ( "runtime" - "syscall" "github.com/opencontainers/runtime-spec/specs-go" rspec "github.com/opencontainers/runtime-spec/specs-go" @@ -513,7 +512,7 @@ func DefaultProfile(rs *specs.Spec) *rspec.LinuxSeccomp { Args: []rspec.LinuxSeccompArg{ { Index: sysCloneFlagsIndex, - Value: syscall.CLONE_NEWNS | syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC | syscall.CLONE_NEWUSER | syscall.CLONE_NEWPID | syscall.CLONE_NEWNET, + Value: CloneNewNS | CloneNewUTS | CloneNewIPC | CloneNewUser | CloneNewPID | CloneNewNet, ValueTwo: 0, Op: rspec.OpMaskedEqual, }, diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go new file mode 100644 index 00000000..31158743 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go @@ -0,0 +1,15 @@ +// +build linux + +package seccomp + +import "syscall" + +// System values passed through on linux +const ( + CloneNewIPC = syscall.CLONE_NEWIPC + CloneNewNet = syscall.CLONE_NEWNET + CloneNewNS = syscall.CLONE_NEWNS + CloneNewPID = syscall.CLONE_NEWPID + CloneNewUser = syscall.CLONE_NEWUSER + CloneNewUTS = syscall.CLONE_NEWUTS +) diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_unsupported.go b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_unsupported.go new file mode 100644 index 00000000..589b81c1 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_unsupported.go @@ -0,0 +1,15 @@ +// +build !linux + +package seccomp + +// These are copied from linux/amd64 syscall values, as a reference for other +// platforms to have access to +const ( + CloneNewIPC = 0x8000000 + CloneNewNet = 0x40000000 + CloneNewNS = 0x20000 + CloneNewPID = 0x20000000 + CloneNewUser = 0x10000000 + CloneNewUTS = 0x4000000 + CloneNewCgroup = 0x02000000 +) diff --git a/vendor/github.com/opencontainers/runtime-tools/specerror/config.go b/vendor/github.com/opencontainers/runtime-tools/specerror/config.go index 8a73f47f..5357ab59 100644 --- a/vendor/github.com/opencontainers/runtime-tools/specerror/config.go +++ b/vendor/github.com/opencontainers/runtime-tools/specerror/config.go @@ -14,8 +14,8 @@ const ( RootOnWindowsRequired // RootOnHyperVNotSet represents "For Hyper-V Containers, this field MUST NOT be set." RootOnHyperVNotSet - // RootOnNonHyperVRequired represents "On all other platforms, this field is REQUIRED." - RootOnNonHyperVRequired + // RootOnNonWindowsRequired represents "On all other platforms, this field is REQUIRED." + RootOnNonWindowsRequired // RootPathOnWindowsGUID represents "On Windows, `path` MUST be a volume GUID path." RootPathOnWindowsGUID // RootPathOnPosixConvention represents "The value SHOULD be the conventional `rootfs`." @@ -145,7 +145,7 @@ func init() { register(SpecVersionInSemVer, rfc2119.Must, specificationVersionRef) register(RootOnWindowsRequired, rfc2119.Required, rootRef) register(RootOnHyperVNotSet, rfc2119.Must, rootRef) - register(RootOnNonHyperVRequired, rfc2119.Required, rootRef) + register(RootOnNonWindowsRequired, rfc2119.Required, rootRef) register(RootPathOnWindowsGUID, rfc2119.Must, rootRef) register(RootPathOnPosixConvention, rfc2119.Should, rootRef) register(RootPathExist, rfc2119.Must, rootRef) diff --git a/vendor/github.com/opencontainers/runtime-tools/validate/validate.go b/vendor/github.com/opencontainers/runtime-tools/validate/validate.go index 1f4d96ce..8a4dcda4 100644 --- a/vendor/github.com/opencontainers/runtime-tools/validate/validate.go +++ b/vendor/github.com/opencontainers/runtime-tools/validate/validate.go @@ -13,7 +13,6 @@ import ( "regexp" "runtime" "strings" - "syscall" "unicode" "unicode/utf8" @@ -171,16 +170,21 @@ func (v *Validator) CheckJSONSchema() (errs error) { func (v *Validator) CheckRoot() (errs error) { logrus.Debugf("check root") - if v.platform == "windows" && v.spec.Windows != nil && v.spec.Windows.HyperV != nil { - if v.spec.Root != nil { + if v.platform == "windows" && v.spec.Windows != nil { + if v.spec.Windows.HyperV != nil { + if v.spec.Root != nil { + errs = multierror.Append(errs, + specerror.NewError(specerror.RootOnHyperVNotSet, fmt.Errorf("for Hyper-V containers, Root must not be set"), rspec.Version)) + } + return + } else if v.spec.Root == nil { errs = multierror.Append(errs, - specerror.NewError(specerror.RootOnHyperVNotSet, fmt.Errorf("for Hyper-V containers, Root must not be set"), rspec.Version)) + specerror.NewError(specerror.RootOnWindowsRequired, fmt.Errorf("on Windows, for Windows Server Containers, this field is REQUIRED"), rspec.Version)) return } - return - } else if v.spec.Root == nil { + } else if v.platform != "windows" && v.spec.Root == nil { errs = multierror.Append(errs, - specerror.NewError(specerror.RootOnNonHyperVRequired, fmt.Errorf("for non-Hyper-V containers, Root must be set"), rspec.Version)) + specerror.NewError(specerror.RootOnNonWindowsRequired, fmt.Errorf("on all other platforms, this field is REQUIRED"), rspec.Version)) return } @@ -585,189 +589,6 @@ func (v *Validator) CheckPlatform() (errs error) { return } -// CheckLinux checks v.spec.Linux -func (v *Validator) CheckLinux() (errs error) { - logrus.Debugf("check linux") - - if v.spec.Linux == nil { - return - } - - var nsTypeList = map[rspec.LinuxNamespaceType]struct { - num int - newExist bool - }{ - rspec.PIDNamespace: {0, false}, - rspec.NetworkNamespace: {0, false}, - rspec.MountNamespace: {0, false}, - rspec.IPCNamespace: {0, false}, - rspec.UTSNamespace: {0, false}, - rspec.UserNamespace: {0, false}, - rspec.CgroupNamespace: {0, false}, - } - - for index := 0; index < len(v.spec.Linux.Namespaces); index++ { - ns := v.spec.Linux.Namespaces[index] - if ns.Path != "" && !osFilepath.IsAbs(v.platform, ns.Path) { - errs = multierror.Append(errs, specerror.NewError(specerror.NSPathAbs, fmt.Errorf("namespace.path %q is not an absolute path", ns.Path), rspec.Version)) - } - - tmpItem := nsTypeList[ns.Type] - tmpItem.num = tmpItem.num + 1 - 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 { - tmpItem.newExist = true - } - nsTypeList[ns.Type] = tmpItem - } - - if (len(v.spec.Linux.UIDMappings) > 0 || len(v.spec.Linux.GIDMappings) > 0) && !nsTypeList[rspec.UserNamespace].newExist { - errs = multierror.Append(errs, errors.New("the UID/GID mappings requires a new User namespace to be specified as well")) - } - - for k := range v.spec.Linux.Sysctl { - if strings.HasPrefix(k, "net.") && !nsTypeList[rspec.NetworkNamespace].newExist { - errs = multierror.Append(errs, fmt.Errorf("sysctl %v requires a new Network namespace to be specified as well", k)) - } - if strings.HasPrefix(k, "fs.mqueue.") { - if !nsTypeList[rspec.MountNamespace].newExist || !nsTypeList[rspec.IPCNamespace].newExist { - errs = multierror.Append(errs, fmt.Errorf("sysctl %v requires a new IPC namespace and Mount namespace to be specified as well", k)) - } - } - } - - if v.platform == "linux" && !nsTypeList[rspec.UTSNamespace].newExist && v.spec.Hostname != "" { - errs = multierror.Append(errs, fmt.Errorf("on Linux, hostname requires a new UTS namespace to be specified as well")) - } - - // Linux devices validation - devList := make(map[string]bool) - devTypeList := make(map[string]bool) - for index := 0; index < len(v.spec.Linux.Devices); index++ { - device := v.spec.Linux.Devices[index] - if !deviceValid(device) { - errs = multierror.Append(errs, fmt.Errorf("device %v is invalid", device)) - } - - if _, exists := devList[device.Path]; exists { - errs = multierror.Append(errs, fmt.Errorf("device %s is duplicated", device.Path)) - } else { - 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, device.Path) - fi, err := os.Stat(absPath) - if os.IsNotExist(err) { - devList[device.Path] = true - } else if err != nil { - errs = multierror.Append(errs, err) - } else { - fStat, ok := fi.Sys().(*syscall.Stat_t) - if !ok { - errs = multierror.Append(errs, specerror.NewError(specerror.DevicesAvailable, - fmt.Errorf("cannot determine state for device %s", device.Path), rspec.Version)) - continue - } - var devType string - switch fStat.Mode & syscall.S_IFMT { - case syscall.S_IFCHR: - devType = "c" - case syscall.S_IFBLK: - devType = "b" - case syscall.S_IFIFO: - devType = "p" - default: - devType = "unmatched" - } - if devType != device.Type || (devType == "c" && device.Type == "u") { - errs = multierror.Append(errs, specerror.NewError(specerror.DevicesFileNotMatch, - fmt.Errorf("unmatched %s already exists in filesystem", device.Path), rspec.Version)) - continue - } - if devType != "p" { - dev := fStat.Rdev - major := (dev >> 8) & 0xfff - minor := (dev & 0xff) | ((dev >> 12) & 0xfff00) - if int64(major) != device.Major || int64(minor) != device.Minor { - errs = multierror.Append(errs, specerror.NewError(specerror.DevicesFileNotMatch, - fmt.Errorf("unmatched %s already exists in filesystem", device.Path), rspec.Version)) - continue - } - } - if device.FileMode != nil { - expectedPerm := *device.FileMode & os.ModePerm - actualPerm := fi.Mode() & os.ModePerm - if expectedPerm != actualPerm { - errs = multierror.Append(errs, specerror.NewError(specerror.DevicesFileNotMatch, - fmt.Errorf("unmatched %s already exists in filesystem", device.Path), rspec.Version)) - continue - } - } - if device.UID != nil { - if *device.UID != fStat.Uid { - errs = multierror.Append(errs, specerror.NewError(specerror.DevicesFileNotMatch, - fmt.Errorf("unmatched %s already exists in filesystem", device.Path), rspec.Version)) - continue - } - } - if device.GID != nil { - if *device.GID != fStat.Gid { - errs = multierror.Append(errs, specerror.NewError(specerror.DevicesFileNotMatch, - fmt.Errorf("unmatched %s already exists in filesystem", device.Path), rspec.Version)) - continue - } - } - } - } - - // unify u->c when comparing, they are synonyms - var devID string - if device.Type == "u" { - devID = fmt.Sprintf("%s:%d:%d", "c", device.Major, device.Minor) - } else { - devID = fmt.Sprintf("%s:%d:%d", device.Type, device.Major, device.Minor) - } - - if _, exists := devTypeList[devID]; exists { - logrus.Warnf("%v", specerror.NewError(specerror.DevicesErrorOnDup, fmt.Errorf("type:%s, major:%d and minor:%d for linux devices is duplicated", device.Type, device.Major, device.Minor), rspec.Version)) - } else { - devTypeList[devID] = true - } - } - - if v.spec.Linux.Resources != nil { - errs = multierror.Append(errs, v.CheckLinuxResources()) - } - - for _, maskedPath := range v.spec.Linux.MaskedPaths { - if !strings.HasPrefix(maskedPath, "/") { - errs = multierror.Append(errs, - specerror.NewError( - specerror.MaskedPathsAbs, - fmt.Errorf("maskedPath %v is not an absolute path", maskedPath), - rspec.Version)) - } - } - - for _, readonlyPath := range v.spec.Linux.ReadonlyPaths { - if !strings.HasPrefix(readonlyPath, "/") { - errs = multierror.Append(errs, - specerror.NewError( - specerror.ReadonlyPathsAbs, - fmt.Errorf("readonlyPath %v is not an absolute path", readonlyPath), - rspec.Version)) - } - } - - return -} - // CheckLinuxResources checks v.spec.Linux.Resources func (v *Validator) CheckLinuxResources() (errs error) { logrus.Debugf("check linux resources") @@ -857,17 +678,6 @@ func CapValid(c string, hostSpecific bool) error { return nil } -// LastCap return last cap of system -func LastCap() capability.Cap { - last := capability.CAP_LAST_CAP - // hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap - if last == capability.Cap(63) { - last = capability.CAP_BLOCK_SUSPEND - } - - return last -} - func envValid(env string) bool { items := strings.Split(env, "=") if len(items) < 2 { diff --git a/vendor/github.com/opencontainers/runtime-tools/validate/validate_linux.go b/vendor/github.com/opencontainers/runtime-tools/validate/validate_linux.go new file mode 100644 index 00000000..ddda7a10 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-tools/validate/validate_linux.go @@ -0,0 +1,214 @@ +// +build linux + +package validate + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "strings" + "syscall" + + "github.com/syndtr/gocapability/capability" + + 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/sirupsen/logrus" +) + +// LastCap return last cap of system +func LastCap() capability.Cap { + last := capability.CAP_LAST_CAP + // hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap + if last == capability.Cap(63) { + last = capability.CAP_BLOCK_SUSPEND + } + + return last +} + +// CheckLinux checks v.spec.Linux +func (v *Validator) CheckLinux() (errs error) { + logrus.Debugf("check linux") + + if v.spec.Linux == nil { + return + } + + var nsTypeList = map[rspec.LinuxNamespaceType]struct { + num int + newExist bool + }{ + rspec.PIDNamespace: {0, false}, + rspec.NetworkNamespace: {0, false}, + rspec.MountNamespace: {0, false}, + rspec.IPCNamespace: {0, false}, + rspec.UTSNamespace: {0, false}, + rspec.UserNamespace: {0, false}, + rspec.CgroupNamespace: {0, false}, + } + + for index := 0; index < len(v.spec.Linux.Namespaces); index++ { + ns := v.spec.Linux.Namespaces[index] + if ns.Path != "" && !osFilepath.IsAbs(v.platform, ns.Path) { + errs = multierror.Append(errs, specerror.NewError(specerror.NSPathAbs, fmt.Errorf("namespace.path %q is not an absolute path", ns.Path), rspec.Version)) + } + + tmpItem := nsTypeList[ns.Type] + tmpItem.num = tmpItem.num + 1 + 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 { + tmpItem.newExist = true + } + nsTypeList[ns.Type] = tmpItem + } + + if (len(v.spec.Linux.UIDMappings) > 0 || len(v.spec.Linux.GIDMappings) > 0) && !nsTypeList[rspec.UserNamespace].newExist { + errs = multierror.Append(errs, errors.New("the UID/GID mappings requires a new User namespace to be specified as well")) + } + + for k := range v.spec.Linux.Sysctl { + if strings.HasPrefix(k, "net.") && !nsTypeList[rspec.NetworkNamespace].newExist { + errs = multierror.Append(errs, fmt.Errorf("sysctl %v requires a new Network namespace to be specified as well", k)) + } + if strings.HasPrefix(k, "fs.mqueue.") { + if !nsTypeList[rspec.MountNamespace].newExist || !nsTypeList[rspec.IPCNamespace].newExist { + errs = multierror.Append(errs, fmt.Errorf("sysctl %v requires a new IPC namespace and Mount namespace to be specified as well", k)) + } + } + } + + if v.platform == "linux" && !nsTypeList[rspec.UTSNamespace].newExist && v.spec.Hostname != "" { + errs = multierror.Append(errs, fmt.Errorf("on Linux, hostname requires a new UTS namespace to be specified as well")) + } + + // Linux devices validation + devList := make(map[string]bool) + devTypeList := make(map[string]bool) + for index := 0; index < len(v.spec.Linux.Devices); index++ { + device := v.spec.Linux.Devices[index] + if !deviceValid(device) { + errs = multierror.Append(errs, fmt.Errorf("device %v is invalid", device)) + } + + if _, exists := devList[device.Path]; exists { + errs = multierror.Append(errs, fmt.Errorf("device %s is duplicated", device.Path)) + } else { + 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, device.Path) + fi, err := os.Stat(absPath) + if os.IsNotExist(err) { + devList[device.Path] = true + } else if err != nil { + errs = multierror.Append(errs, err) + } else { + fStat, ok := fi.Sys().(*syscall.Stat_t) + if !ok { + errs = multierror.Append(errs, specerror.NewError(specerror.DevicesAvailable, + fmt.Errorf("cannot determine state for device %s", device.Path), rspec.Version)) + continue + } + var devType string + switch fStat.Mode & syscall.S_IFMT { + case syscall.S_IFCHR: + devType = "c" + case syscall.S_IFBLK: + devType = "b" + case syscall.S_IFIFO: + devType = "p" + default: + devType = "unmatched" + } + if devType != device.Type || (devType == "c" && device.Type == "u") { + errs = multierror.Append(errs, specerror.NewError(specerror.DevicesFileNotMatch, + fmt.Errorf("unmatched %s already exists in filesystem", device.Path), rspec.Version)) + continue + } + if devType != "p" { + dev := fStat.Rdev + major := (dev >> 8) & 0xfff + minor := (dev & 0xff) | ((dev >> 12) & 0xfff00) + if int64(major) != device.Major || int64(minor) != device.Minor { + errs = multierror.Append(errs, specerror.NewError(specerror.DevicesFileNotMatch, + fmt.Errorf("unmatched %s already exists in filesystem", device.Path), rspec.Version)) + continue + } + } + if device.FileMode != nil { + expectedPerm := *device.FileMode & os.ModePerm + actualPerm := fi.Mode() & os.ModePerm + if expectedPerm != actualPerm { + errs = multierror.Append(errs, specerror.NewError(specerror.DevicesFileNotMatch, + fmt.Errorf("unmatched %s already exists in filesystem", device.Path), rspec.Version)) + continue + } + } + if device.UID != nil { + if *device.UID != fStat.Uid { + errs = multierror.Append(errs, specerror.NewError(specerror.DevicesFileNotMatch, + fmt.Errorf("unmatched %s already exists in filesystem", device.Path), rspec.Version)) + continue + } + } + if device.GID != nil { + if *device.GID != fStat.Gid { + errs = multierror.Append(errs, specerror.NewError(specerror.DevicesFileNotMatch, + fmt.Errorf("unmatched %s already exists in filesystem", device.Path), rspec.Version)) + continue + } + } + } + } + + // unify u->c when comparing, they are synonyms + var devID string + if device.Type == "u" { + devID = fmt.Sprintf("%s:%d:%d", "c", device.Major, device.Minor) + } else { + devID = fmt.Sprintf("%s:%d:%d", device.Type, device.Major, device.Minor) + } + + if _, exists := devTypeList[devID]; exists { + logrus.Warnf("type:%s, major:%d and minor:%d for linux devices is duplicated", device.Type, device.Major, device.Minor) + } else { + devTypeList[devID] = true + } + } + + if v.spec.Linux.Resources != nil { + errs = multierror.Append(errs, v.CheckLinuxResources()) + } + + for _, maskedPath := range v.spec.Linux.MaskedPaths { + if !strings.HasPrefix(maskedPath, "/") { + errs = multierror.Append(errs, + specerror.NewError( + specerror.MaskedPathsAbs, + fmt.Errorf("maskedPath %v is not an absolute path", maskedPath), + rspec.Version)) + } + } + + for _, readonlyPath := range v.spec.Linux.ReadonlyPaths { + if !strings.HasPrefix(readonlyPath, "/") { + errs = multierror.Append(errs, + specerror.NewError( + specerror.ReadonlyPathsAbs, + fmt.Errorf("readonlyPath %v is not an absolute path", readonlyPath), + rspec.Version)) + } + } + + return +} diff --git a/vendor/github.com/opencontainers/runtime-tools/validate/validate_unsupported.go b/vendor/github.com/opencontainers/runtime-tools/validate/validate_unsupported.go new file mode 100644 index 00000000..f150c326 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-tools/validate/validate_unsupported.go @@ -0,0 +1,17 @@ +// +build !linux + +package validate + +import ( + "github.com/syndtr/gocapability/capability" +) + +// LastCap return last cap of system +func LastCap() capability.Cap { + return capability.Cap(-1) +} + +// CheckLinux is a noop on this platform +func (v *Validator) CheckLinux() (errs error) { + return nil +}