diff options
Diffstat (limited to 'vendor')
62 files changed, 1268 insertions, 767 deletions
diff --git a/vendor/github.com/containers/buildah/CONTRIBUTING.md b/vendor/github.com/containers/buildah/CONTRIBUTING.md index 0178a517c..553cb15dc 100644 --- a/vendor/github.com/containers/buildah/CONTRIBUTING.md +++ b/vendor/github.com/containers/buildah/CONTRIBUTING.md @@ -178,7 +178,7 @@ that has been setup. #### Buildah Mailing List -You can join the Buildah mailing list by sending an email to `buildah-join@lists.buildah.io` with the word `subscribe` in the subject. You can also go to this [page](https://lists.podman.io/admin/lists/buildah.lists.buildah.io/), then scroll down to the bottom of the page and enter your email and optionally name, then click on the "Subscribe" buton. +You can join the Buildah mailing list by sending an email to `buildah-join@lists.buildah.io` with the word `subscribe` in the subject. You can also go to this [page](https://lists.podman.io/admin/lists/buildah.lists.buildah.io/), then scroll down to the bottom of the page and enter your email and optionally name, then click on the "Subscribe" button. #### GitHub You can also use the github diff --git a/vendor/github.com/containers/buildah/buildah.go b/vendor/github.com/containers/buildah/buildah.go index 6d1d479b1..2ece11acd 100644 --- a/vendor/github.com/containers/buildah/buildah.go +++ b/vendor/github.com/containers/buildah/buildah.go @@ -27,7 +27,7 @@ const ( Package = "buildah" // Version for the Package. Bump version in contrib/rpm/buildah.spec // too. - Version = "1.14.2" + Version = "1.15.0-dev" // The value we use to identify what type of information, currently a // serialized Builder structure, we are using as per-container state. // This should only be changed when we make incompatible changes to diff --git a/vendor/github.com/containers/buildah/chroot/run.go b/vendor/github.com/containers/buildah/chroot/run.go index 482fef693..8dfa8aba0 100644 --- a/vendor/github.com/containers/buildah/chroot/run.go +++ b/vendor/github.com/containers/buildah/chroot/run.go @@ -656,7 +656,7 @@ func runUsingChrootExecMain() { // Set the hostname. We're already in a distinct UTS namespace and are admins in the user // namespace which created it, so we shouldn't get a permissions error, but seccomp policy // might deny our attempt to call sethostname() anyway, so log a debug message for that. - if options.Spec.Hostname != "" { + if options.Spec != nil && options.Spec.Hostname != "" { if err := unix.Sethostname([]byte(options.Spec.Hostname)); err != nil { logrus.Debugf("failed to set hostname %q for process: %v", options.Spec.Hostname, err) } diff --git a/vendor/github.com/containers/buildah/go.mod b/vendor/github.com/containers/buildah/go.mod index 72fbffe2c..97b2eeae8 100644 --- a/vendor/github.com/containers/buildah/go.mod +++ b/vendor/github.com/containers/buildah/go.mod @@ -4,9 +4,9 @@ go 1.12 require ( github.com/containernetworking/cni v0.7.2-0.20190904153231-83439463f784 - github.com/containers/common v0.4.2 + github.com/containers/common v0.5.0 github.com/containers/image/v5 v5.2.1 - github.com/containers/storage v1.16.1 + github.com/containers/storage v1.16.2 github.com/cyphar/filepath-securejoin v0.2.2 github.com/docker/distribution v2.7.1+incompatible github.com/docker/go-metrics v0.0.1 // indirect @@ -25,7 +25,7 @@ require ( github.com/opencontainers/runc v1.0.0-rc9 github.com/opencontainers/runtime-spec v0.1.2-0.20190618234442-a950415649c7 github.com/opencontainers/runtime-tools v0.9.0 - github.com/opencontainers/selinux v1.3.3 + github.com/opencontainers/selinux v1.4.0 github.com/openshift/api v0.0.0-20200106203948-7ab22a2c8316 github.com/openshift/imagebuilder v1.1.1 github.com/pkg/errors v0.9.1 diff --git a/vendor/github.com/containers/buildah/go.sum b/vendor/github.com/containers/buildah/go.sum index 79dc064ce..191eb1f11 100644 --- a/vendor/github.com/containers/buildah/go.sum +++ b/vendor/github.com/containers/buildah/go.sum @@ -103,6 +103,14 @@ github.com/containers/common v0.4.1 h1:Uu7f2ZDM/5xsqOkZwIEVKSjUI3YxKjvNIY5x57kja github.com/containers/common v0.4.1/go.mod h1:m62kenckrWi5rZx32kaLje2Og0hpf6NsaTBn6+b+Oys= github.com/containers/common v0.4.2 h1:O5d1gj/xdpQdZi0MEivRQ/7AeRaVeHdbSP/bvShw458= github.com/containers/common v0.4.2/go.mod h1:m62kenckrWi5rZx32kaLje2Og0hpf6NsaTBn6+b+Oys= +github.com/containers/common v0.4.3 h1:TJ7UQxB8wf//IY4LNZobswrTjbhIjXpidrRbCA2l+kg= +github.com/containers/common v0.4.3/go.mod h1:m62kenckrWi5rZx32kaLje2Og0hpf6NsaTBn6+b+Oys= +github.com/containers/common v0.4.4 h1:oXQUPDQOIQ+XmQ2cWyLCs2TctDfISykAr1gEa3CNwlQ= +github.com/containers/common v0.4.4/go.mod h1:vMkHkvczHslJbUj8xasSQmdNrLUgZYuUxVNGJDfjRIQ= +github.com/containers/common v0.5.0 h1:ZAef7h3oO46PcbTyfooZf8XLHrYad+GkhSu3EhH6P24= +github.com/containers/common v0.5.0/go.mod h1:m62kenckrWi5rZx32kaLje2Og0hpf6NsaTBn6+b+Oys= +github.com/containers/common v1.0.0 h1:sZB48LzGP4bP1CmrkQIFUzdUVBysqRv3kWVk4+qbaVA= +github.com/containers/common v1.0.0/go.mod h1:m62kenckrWi5rZx32kaLje2Og0hpf6NsaTBn6+b+Oys= github.com/containers/conmon v2.0.10+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/image/v4 v4.0.1 h1:idNGHChj0Pyv3vLrxul2oSVMZLeFqpoq3CjLeVgapSQ= github.com/containers/image/v4 v4.0.1/go.mod h1:0ASJH1YgJiX/eqFZObqepgsvIA4XjCgpyfwn9pDGafA= @@ -149,6 +157,8 @@ github.com/containers/storage v1.16.0 h1:sD+s7BmiNBh61CuHN3j8PXGCwMtV9zPVJETAlsh github.com/containers/storage v1.16.0/go.mod h1:nqN09JSi1/RSI1UAUwDYXPRiGSlq5FPbNkN/xb0TfG0= github.com/containers/storage v1.16.1 h1:gVLVqbqaoyopLJbcQ9PQdsnm8SzVy6Vw24fofwMgkE0= github.com/containers/storage v1.16.1/go.mod h1:toFp72SLn/iyJ6YbrnrZ0bW63aH2Qw3dA8JVwL4ADPo= +github.com/containers/storage v1.16.2 h1:S77Y+lmJcnGoPEZB2OOrTrRGyjT8viDCGyhVNNz78h8= +github.com/containers/storage v1.16.2/go.mod h1:/RNmsK01ajCL+VtMSi3W8kHzpBwN+Q5gLYWgfw5wlMg= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= @@ -281,6 +291,7 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= @@ -495,6 +506,8 @@ github.com/opencontainers/selinux v1.3.2 h1:DR4lL9SYVjgcTZKEZIncvDU06fKSc/eygjmN github.com/opencontainers/selinux v1.3.2/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g= github.com/opencontainers/selinux v1.3.3 h1:RX0wAeqtvVSYQcr017X3pFXPkLEtB6V4NjRD7gVQgg4= github.com/opencontainers/selinux v1.3.3/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g= +github.com/opencontainers/selinux v1.4.0 h1:cpiX/2wWIju/6My60T6/z9CxNG7c8xTQyEmA9fChpUo= +github.com/opencontainers/selinux v1.4.0/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g= github.com/openshift/api v0.0.0-20200106203948-7ab22a2c8316 h1:enQG2QUGwug4fR1yM6hL0Fjzx6Km/exZY6RbSPwMu3o= github.com/openshift/api v0.0.0-20200106203948-7ab22a2c8316/go.mod h1:dv+J0b/HWai0QnMVb37/H0v36klkLBi2TNpPeWDxX10= github.com/openshift/api v3.9.1-0.20190810003144-27fb16909b15+incompatible h1:s55wx8JIG/CKnewev892HifTBrtKzMdvgB3rm4rxC2s= diff --git a/vendor/github.com/containers/buildah/image.go b/vendor/github.com/containers/buildah/image.go index d333442b8..94e97d870 100644 --- a/vendor/github.com/containers/buildah/image.go +++ b/vendor/github.com/containers/buildah/image.go @@ -627,7 +627,7 @@ func (i *containerImageSource) GetBlob(ctx context.Context, blob types.BlobInfo, logrus.Debugf("error checking for layer %q in %q: %v", blob.Digest.String(), path, err) } } - if err != nil { + if err != nil || layerFile == nil { logrus.Debugf("error reading layer %q: %v", blob.Digest.String(), err) return nil, -1, errors.Wrapf(err, "error opening file %q to buffer layer blob", filepath.Join(i.path, blob.Digest.String())) } diff --git a/vendor/github.com/containers/buildah/imagebuildah/stage_executor.go b/vendor/github.com/containers/buildah/imagebuildah/stage_executor.go index 6216dac97..8e49395a4 100644 --- a/vendor/github.com/containers/buildah/imagebuildah/stage_executor.go +++ b/vendor/github.com/containers/buildah/imagebuildah/stage_executor.go @@ -238,7 +238,13 @@ func (s *StageExecutor) volumeCacheRestore() error { if err := os.Chmod(archivedPath, st.Mode()); err != nil { return errors.Wrapf(err, "error restoring permissions on %q", archivedPath) } - if err := os.Chown(archivedPath, 0, 0); err != nil { + uid := 0 + gid := 0 + if st.Sys() != nil { + uid = util.UID(st) + gid = util.GID(st) + } + if err := os.Chown(archivedPath, uid, gid); err != nil { return errors.Wrapf(err, "error setting ownership on %q", archivedPath) } if err := os.Chtimes(archivedPath, st.ModTime(), st.ModTime()); err != nil { diff --git a/vendor/github.com/containers/buildah/pull.go b/vendor/github.com/containers/buildah/pull.go index 4a38abeab..cbb98cbcf 100644 --- a/vendor/github.com/containers/buildah/pull.go +++ b/vendor/github.com/containers/buildah/pull.go @@ -216,8 +216,13 @@ func Pull(ctx context.Context, imageName string, options PullOptions) (imageID s } else { imageID = img.ID } + if errs == nil { + err = nil + } else { + err = errs.ErrorOrNil() + } - return imageID, errs.ErrorOrNil() + return imageID, err } func pullImage(ctx context.Context, store storage.Store, srcRef types.ImageReference, options PullOptions, sc *types.SystemContext) (types.ImageReference, error) { diff --git a/vendor/github.com/containers/buildah/run_linux.go b/vendor/github.com/containers/buildah/run_linux.go index 6df6ef41a..6e4d31d78 100644 --- a/vendor/github.com/containers/buildah/run_linux.go +++ b/vendor/github.com/containers/buildah/run_linux.go @@ -702,7 +702,9 @@ func runUsingRuntime(isolation Isolation, options RunOptions, configureNetwork b return 1, errors.Wrapf(err, "error creating pipe for notifying to stop stdio") } finishedCopy := make(chan struct{}) + var pargs []string if spec.Process != nil { + pargs = spec.Process.Args if spec.Process.Terminal { copyConsole = true // Create a listening socket for accepting the container's terminal's PTY master. @@ -773,7 +775,7 @@ func runUsingRuntime(isolation Isolation, options RunOptions, configureNetwork b logrus.Debugf("Running %q", create.Args) err = create.Run() if err != nil { - return 1, errors.Wrapf(err, "error creating container for %v: %s", spec.Process.Args, runCollectOutput(errorFds, closeBeforeReadingErrorFds)) + return 1, errors.Wrapf(err, "error creating container for %v: %s", pargs, runCollectOutput(errorFds, closeBeforeReadingErrorFds)) } defer func() { err2 := del.Run() @@ -808,7 +810,7 @@ func runUsingRuntime(isolation Isolation, options RunOptions, configureNetwork b }() if configureNetwork { - teardown, err := runConfigureNetwork(isolation, options, configureNetworks, pid, containerName, spec.Process.Args) + teardown, err := runConfigureNetwork(isolation, options, configureNetworks, pid, containerName, pargs) if teardown != nil { defer teardown() } @@ -1044,6 +1046,9 @@ func runConfigureNetwork(isolation Isolation, options RunOptions, configureNetwo } continue } + if nc.Network == nil { + continue + } cl, err := libcni.ConfListFromConf(nc) if err != nil { return nil, errors.Wrapf(err, "error converting networking configuration from file %q for %v", file, command) @@ -1450,8 +1455,13 @@ func runUsingRuntimeMain() { if err := setChildProcess(); err != nil { os.Exit(1) } + var ospec *specs.Spec + if options.Spec != nil { + ospec = options.Spec + } + // Run the container, start to finish. - status, err := runUsingRuntime(options.Isolation, options.Options, options.ConfigureNetwork, options.ConfigureNetworks, options.MoreCreateArgs, options.Spec, options.BundlePath, options.ContainerName) + status, err := runUsingRuntime(options.Isolation, options.Options, options.ConfigureNetwork, options.ConfigureNetworks, options.MoreCreateArgs, ospec, options.BundlePath, options.ContainerName) if err != nil { fmt.Fprintf(os.Stderr, "error running container: %v\n", err) os.Exit(1) diff --git a/vendor/github.com/containers/buildah/util/util.go b/vendor/github.com/containers/buildah/util/util.go index 05d661b58..a358b7c54 100644 --- a/vendor/github.com/containers/buildah/util/util.go +++ b/vendor/github.com/containers/buildah/util/util.go @@ -365,7 +365,7 @@ func GetHostIDs(uidmap, gidmap []specs.LinuxIDMapping, uid, gid uint32) (uint32, // GetHostRootIDs uses ID mappings in spec to compute the host-level IDs that will // correspond to UID/GID 0/0 in the container. func GetHostRootIDs(spec *specs.Spec) (uint32, uint32, error) { - if spec.Linux == nil { + if spec == nil || spec.Linux == nil { return 0, 0, nil } return GetHostIDs(spec.Linux.UIDMappings, spec.Linux.GIDMappings, 0, 0) @@ -455,7 +455,7 @@ func FindLocalRuntime(runtime string) string { logrus.Debugf("Error loading container config when searching for local runtime.") return localRuntime } - for _, val := range conf.Libpod.OCIRuntimes[runtime] { + for _, val := range conf.Engine.OCIRuntimes[runtime] { if fileExistsAndNotADir(val) { localRuntime = val break diff --git a/vendor/github.com/containers/buildah/util/util_linux.go b/vendor/github.com/containers/buildah/util/util_linux.go index cca1f9e7e..1a13699df 100644 --- a/vendor/github.com/containers/buildah/util/util_linux.go +++ b/vendor/github.com/containers/buildah/util/util_linux.go @@ -1,6 +1,7 @@ package util import ( + "os" "syscall" "golang.org/x/sys/unix" @@ -18,3 +19,11 @@ func IsCgroup2UnifiedMode() (bool, error) { }) return isUnified, isUnifiedErr } + +func UID(st os.FileInfo) int { + return int(st.Sys().(*syscall.Stat_t).Uid) +} + +func GID(st os.FileInfo) int { + return int(st.Sys().(*syscall.Stat_t).Gid) +} diff --git a/vendor/github.com/containers/buildah/util/util_unsupported.go b/vendor/github.com/containers/buildah/util/util_unsupported.go index 05a68f60b..8810536a6 100644 --- a/vendor/github.com/containers/buildah/util/util_unsupported.go +++ b/vendor/github.com/containers/buildah/util/util_unsupported.go @@ -2,7 +2,19 @@ package util +import ( + "os" +) + // IsCgroup2UnifiedMode returns whether we are running in cgroup 2 cgroup2 mode. func IsCgroup2UnifiedMode() (bool, error) { return false, nil } + +func UID(st os.FileInfo) int { + return 0 +} + +func GID(st os.FileInfo) int { + return 0 +} diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go index 4b536b3a5..0a09d994e 100644 --- a/vendor/github.com/containers/common/pkg/config/config.go +++ b/vendor/github.com/containers/common/pkg/config/config.go @@ -12,7 +12,6 @@ import ( "github.com/BurntSushi/toml" "github.com/containers/common/pkg/capabilities" "github.com/containers/common/pkg/unshare" - "github.com/containers/storage" units "github.com/docker/go-units" selinux "github.com/opencontainers/selinux/go-selinux" "github.com/pkg/errors" @@ -29,14 +28,14 @@ const ( ) // RuntimeStateStore is a constant indicating which state store implementation -// should be used by libpod +// should be used by engine type RuntimeStateStore int const ( // InvalidStateStore is an invalid state store InvalidStateStore RuntimeStateStore = iota // InMemoryStateStore is an in-memory state that will not persist data - // on containers and pods between libpod instances or after system + // on containers and pods between engine instances or after system // reboot InMemoryStateStore RuntimeStateStore = iota // SQLiteStateStore is a state backed by a SQLite database @@ -46,12 +45,24 @@ const ( BoltDBStateStore RuntimeStateStore = iota ) +// PullPolicy whether to pull new image +type PullPolicy int + +const ( + // PullImageAlways always try to pull new image when create or run + PullImageAlways PullPolicy = iota + // PullImageMissing pulls image if it is not locally + PullImageMissing + // PullImageNever will never pull new image + PullImageNever +) + // Config contains configuration options for container tools type Config struct { // Containers specify settings that configure how containers will run ont the system Containers ContainersConfig `toml:"containers"` - // Libpod specifies how the container engine based on Libpod will run - Libpod LibpodConfig `toml:"libpod"` + // Engine specifies how the container engine based on Engine will run + Engine EngineConfig `toml:"engine"` // Network section defines the configuration of CNI Plugins Network NetworkConfig `toml:"network"` } @@ -164,8 +175,12 @@ type ContainersConfig struct { UserNSSize int `toml:"userns_size"` } -// LibpodConfig contains configuration options used to set up a libpod runtime -type LibpodConfig struct { +// EngineConfig contains configuration options used to set up a engine runtime +type EngineConfig struct { + // CgroupCheck indicates the configuration has been rewritten after an + // upgrade to Fedora 31 to change the default OCI runtime for cgroupsv2. + CgroupCheck bool `toml:"cgroup_check,omitempty"` + // CGroupManager is the CGroup Manager to use Valid values are "cgroupfs" // and "systemd". CgroupManager string `toml:"cgroup_manager"` @@ -183,7 +198,7 @@ type LibpodConfig struct { //DetachKeys is the sequence of keys used to detach a container. DetachKeys string `toml:"detach_keys"` - // EnablePortReservation determines whether libpod will reserve ports on the + // EnablePortReservation determines whether engine will reserve ports on the // host when they are forwarded to containers. When enabled, when ports are // forwarded to containers, they are held open by conmon as long as the // container is running, ensuring that they cannot be reused by other @@ -220,9 +235,9 @@ type LibpodConfig struct { // LockType is the type of locking to use. LockType string `toml:"lock_type,omitempty"` - // Namespace is the libpod namespace to use. Namespaces are used to create + // Namespace is the engine namespace to use. Namespaces are used to create // scopes to separate containers and pods in the state. When namespace is - // set, libpod will only view containers and pods in the same namespace. All + // set, engine will only view containers and pods in the same namespace. All // containers and pods created will default to the namespace set here. A // namespace of "", the empty string, is equivalent to no namespace, and all // containers and pods will be visible. The default namespace is "". @@ -244,6 +259,15 @@ type LibpodConfig struct { // OCIRuntimes are the set of configured OCI runtimes (default is runc). OCIRuntimes map[string][]string `toml:"runtimes"` + // PullPolicy determines whether to pull image before creating or running a container + // default is "missing" + PullPolicy string `toml:"pull_policy"` + // RuntimePath is the path to OCI runtime binary for launching containers. + // The first path pointing to a valid file will be used This is used only + // when there are no OCIRuntime/OCIRuntimes defined. It is used only to be + // backward compatible with older versions of Podman. + RuntimePath []string `toml:"runtime_path,omitempty"` + // RuntimeSupportsJSON is the list of the OCI runtimes that support // --format=json. RuntimeSupportsJSON []string `toml:"runtime_supports_json"` @@ -253,7 +277,7 @@ type LibpodConfig struct { RuntimeSupportsNoCgroups []string `toml:"runtime_supports_nocgroups"` // SetOptions contains a subset of config options. It's used to indicate if - // a given option has either been set by the user or by a parsed libpod + // a given option has either been set by the user or by the parsed // configuration file. If not, the corresponding option might be // overwritten by values from the database. This behavior guarantees // backwards compat with older version of libpod and Podman. @@ -278,11 +302,6 @@ type LibpodConfig struct { // before sending kill signal. StopTimeout uint `toml:"stop_timeout"` - // StorageConfig is the configuration used by containers/storage Not - // included in the on-disk config, use the dedicated containers/storage - // configuration file instead. - StorageConfig storage.StoreOptions `toml:"-"` - // TmpDir is the path to a temporary directory to store per-boot container // files. Must be stored in a tmpfs. TmpDir string `toml:"tmp_dir"` @@ -294,7 +313,7 @@ type LibpodConfig struct { } // SetOptions contains a subset of options in a Config. It's used to indicate if -// a given option has either been set by the user or by a parsed libpod +// a given option has either been set by the user or by a parsed engine // configuration file. If not, the corresponding option might be overwritten by // values from the database. This behavior guarantees backwards compat with // older version of libpod and Podman. @@ -364,16 +383,9 @@ func NewConfig(userConfigPath string) (*Config, error) { return nil, err } - // If the caller specified a config path to use, then we read this - // rather then using the system defaults. - if userConfigPath != "" { - var err error - // readConfigFromFile reads in container config in the specified - // file and then merge changes with the current default. - config, err = readConfigFromFile(userConfigPath, config) - if err != nil { - return nil, errors.Wrapf(err, "error reading user config %q", userConfigPath) - } + // read libpod.conf and convert the config to *Config + if err = newLibpodConfig(config); err != nil && !os.IsNotExist(err) { + logrus.Errorf("error reading libpod.conf: %v", err) } // Now, gather the system configs and merge them as needed. @@ -392,7 +404,18 @@ func NewConfig(userConfigPath string) (*Config, error) { logrus.Debugf("Merged system config %q: %v", path, config) } - config.checkCgroupsAndAdjustConfig() + // If the caller specified a config path to use, then we read it to + // override the system defaults. + if userConfigPath != "" { + var err error + // readConfigFromFile reads in container config in the specified + // file and then merge changes with the current default. + config, err = readConfigFromFile(userConfigPath, config) + if err != nil { + return nil, errors.Wrapf(err, "error reading user config %q", userConfigPath) + } + logrus.Debugf("Merged user config %q: %v", userConfigPath, config) + } config.addCAPPrefix() if err := config.Validate(); err != nil { @@ -412,14 +435,14 @@ func readConfigFromFile(path string, config *Config) (*Config, error) { if err != nil { return nil, fmt.Errorf("unable to decode configuration %v: %v", path, err) } - if config.Libpod.VolumePath != "" { - config.Libpod.VolumePathSet = true + if config.Engine.VolumePath != "" { + config.Engine.VolumePathSet = true } - if config.Libpod.StaticDir != "" { - config.Libpod.StaticDirSet = true + if config.Engine.StaticDir != "" { + config.Engine.StaticDirSet = true } - if config.Libpod.TmpDir != "" { - config.Libpod.TmpDirSet = true + if config.Engine.TmpDir != "" { + config.Engine.TmpDirSet = true } return config, err @@ -455,11 +478,11 @@ func systemConfigs() ([]string, error) { return configs, nil } -// checkCgroupsAndAdjustConfig checks if we're running rootless with the systemd +// CheckCgroupsAndAdjustConfig checks if we're running rootless with the systemd // cgroup manager. In case the user session isn't available, we're switching the // cgroup manager to cgroupfs. Note, this only applies to rootless. -func (c *Config) checkCgroupsAndAdjustConfig() { - if !unshare.IsRootless() || c.Libpod.CgroupManager != SystemdCgroupsManager { +func (c *Config) CheckCgroupsAndAdjustConfig() { + if !unshare.IsRootless() || c.Engine.CgroupManager != SystemdCgroupsManager { return } @@ -475,7 +498,7 @@ func (c *Config) checkCgroupsAndAdjustConfig() { logrus.Warningf("For using systemd, you may need to login using an user session") logrus.Warningf("Alternatively, you can enable lingering with: `loginctl enable-linger %d` (possibly as root)", unshare.GetRootlessUID()) logrus.Warningf("Falling back to --cgroup-manager=cgroupfs") - c.Libpod.CgroupManager = CgroupfsCgroupsManager + c.Engine.CgroupManager = CgroupfsCgroupsManager } } @@ -495,32 +518,47 @@ func (c *Config) addCAPPrefix() { func (c *Config) Validate() error { if err := c.Containers.Validate(); err != nil { - return errors.Wrapf(err, "containers config") + return errors.Wrapf(err, " error validating containers config") } if !c.Containers.EnableLabeling { selinux.SetDisabled() } + if err := c.Engine.Validate(); err != nil { + return errors.Wrapf(err, "error validating engine configs") + } + + if err := c.Network.Validate(); err != nil { + return errors.Wrapf(err, "error validating network configs") + } + return nil } -// Validate is the main entry point for Libpod configuration validation +// Validate is the main entry point for Engine configuration validation // It returns an `error` on validation failure, otherwise // `nil`. -func (c *LibpodConfig) Validate() error { +func (c *EngineConfig) Validate() error { // Relative paths can cause nasty bugs, because core paths we use could // shift between runs (or even parts of the program - the OCI runtime // uses a different working directory than we do, for example. - if !filepath.IsAbs(c.StaticDir) { + if c.StaticDir != "" && !filepath.IsAbs(c.StaticDir) { return fmt.Errorf("static directory must be an absolute path - instead got %q", c.StaticDir) } - if !filepath.IsAbs(c.TmpDir) { + if c.TmpDir != "" && !filepath.IsAbs(c.TmpDir) { return fmt.Errorf("temporary directory must be an absolute path - instead got %q", c.TmpDir) } - if !filepath.IsAbs(c.VolumePath) { + if c.VolumePath != "" && !filepath.IsAbs(c.VolumePath) { return fmt.Errorf("volume path must be an absolute path - instead got %q", c.VolumePath) } + + // Check if the pullPolicy from containers.conf is valid + // if it is invalid returns the error + pullPolicy := strings.ToLower(c.PullPolicy) + if _, err := ValidatePullPolicy(pullPolicy); err != nil { + return errors.Wrapf(err, "invalid pull type from containers.conf %q", c.PullPolicy) + } return nil } @@ -583,69 +621,21 @@ func (c *NetworkConfig) Validate() error { return errors.Errorf("invalid cni_plugin_dirs: %s", strings.Join(c.CNIPluginDirs, ",")) } -// DBConfig is a set of Libpod runtime configuration settings that are saved in -// a State when it is first created, and can subsequently be retrieved. -type DBConfig struct { - LibpodRoot string - LibpodTmp string - StorageRoot string - StorageTmp string - GraphDriver string - VolumePath string -} - -// MergeDBConfig merges the configuration from the database. -func (c *Config) MergeDBConfig(dbConfig *DBConfig) error { - - if !c.Libpod.StorageConfigRunRootSet && dbConfig.StorageTmp != "" { - if c.Libpod.StorageConfig.RunRoot != dbConfig.StorageTmp && - c.Libpod.StorageConfig.RunRoot != "" { - logrus.Debugf("Overriding run root %q with %q from database", - c.Libpod.StorageConfig.RunRoot, dbConfig.StorageTmp) - } - c.Libpod.StorageConfig.RunRoot = dbConfig.StorageTmp - } - - if !c.Libpod.StorageConfigGraphRootSet && dbConfig.StorageRoot != "" { - if c.Libpod.StorageConfig.GraphRoot != dbConfig.StorageRoot && - c.Libpod.StorageConfig.GraphRoot != "" { - logrus.Debugf("Overriding graph root %q with %q from database", - c.Libpod.StorageConfig.GraphRoot, dbConfig.StorageRoot) - } - c.Libpod.StorageConfig.GraphRoot = dbConfig.StorageRoot - } - - if !c.Libpod.StorageConfigGraphDriverNameSet && dbConfig.GraphDriver != "" { - if c.Libpod.StorageConfig.GraphDriverName != dbConfig.GraphDriver && - c.Libpod.StorageConfig.GraphDriverName != "" { - logrus.Errorf("User-selected graph driver %q overwritten by graph driver %q from database - delete libpod local files to resolve", - c.Libpod.StorageConfig.GraphDriverName, dbConfig.GraphDriver) - } - c.Libpod.StorageConfig.GraphDriverName = dbConfig.GraphDriver - } - - if !c.Libpod.StaticDirSet && dbConfig.LibpodRoot != "" { - if c.Libpod.StaticDir != dbConfig.LibpodRoot && c.Libpod.StaticDir != "" { - logrus.Debugf("Overriding static dir %q with %q from database", c.Libpod.StaticDir, dbConfig.LibpodRoot) - } - c.Libpod.StaticDir = dbConfig.LibpodRoot - } - - if !c.Libpod.TmpDirSet && dbConfig.LibpodTmp != "" { - if c.Libpod.TmpDir != dbConfig.LibpodTmp && c.Libpod.TmpDir != "" { - logrus.Debugf("Overriding tmp dir %q with %q from database", c.Libpod.TmpDir, dbConfig.LibpodTmp) - } - c.Libpod.TmpDir = dbConfig.LibpodTmp - c.Libpod.EventsLogFilePath = filepath.Join(dbConfig.LibpodTmp, "events", "events.log") - } - - if !c.Libpod.VolumePathSet && dbConfig.VolumePath != "" { - if c.Libpod.VolumePath != dbConfig.VolumePath && c.Libpod.VolumePath != "" { - logrus.Debugf("Overriding volume path %q with %q from database", c.Libpod.VolumePath, dbConfig.VolumePath) - } - c.Libpod.VolumePath = dbConfig.VolumePath +// ValidatePullPolicy check if the pullPolicy from CLI is valid and returns the valid enum type +// if the value from CLI or containers.conf is invalid returns the error +func ValidatePullPolicy(pullPolicy string) (PullPolicy, error) { + switch pullPolicy { + case "always": + return PullImageAlways, nil + case "missing": + return PullImageMissing, nil + case "never": + return PullImageNever, nil + case "": + return PullImageMissing, nil + default: + return PullImageMissing, errors.Errorf("invalid pull policy %q", pullPolicy) } - return nil } // FindConmon iterates over (*Config).ConmonPath and returns the path @@ -653,7 +643,7 @@ func (c *Config) MergeDBConfig(dbConfig *DBConfig) error { // to do a path lookup of "conmon". func (c *Config) FindConmon() (string, error) { foundOutdatedConmon := false - for _, path := range c.Libpod.ConmonPath { + for _, path := range c.Engine.ConmonPath { stat, err := os.Stat(path) if err != nil { continue @@ -689,7 +679,7 @@ func (c *Config) FindConmon() (string, error) { return "", errors.Wrapf(ErrInvalidArg, "could not find a working conmon binary (configured options: %v)", - c.Libpod.ConmonPath) + c.Engine.ConmonPath) } // GetDefaultEnv returns the environment variables for the container. diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf b/vendor/github.com/containers/common/pkg/config/containers.conf index 91106b576..b01db5f88 100644 --- a/vendor/github.com/containers/common/pkg/config/containers.conf +++ b/vendor/github.com/containers/common/pkg/config/containers.conf @@ -1,9 +1,9 @@ # The containers configuration file specifies all of the available configuration -# command-line options/flags for container runtime tools like Podman & Buildah, +# command-line options/flags for container engine tools like Podman & Buildah, # but in a TOML format that can be easily modified and versioned. # Please refer to containers.conf(5) for details of all configuration options. -# Not all container tools implement all of the options. +# Not all container engines implement all of the options. # All of the options have hard coded defaults and these options will override # the built in defaults. Users can then override these options via the command # line. Container engines will read containers.conf files in up to three @@ -30,7 +30,7 @@ # # volumes = [] -# Used to change the name of the default AppArmor profile of container engines. +# Used to change the name of the default AppArmor profile of container engine. # # apparmor_profile = "container-default" @@ -143,7 +143,8 @@ # # ipcns = "private" -# container engines use container separation using MAC(SELinux) labeling. +# Flag tells container engine to whether to use container separation using +# MAC(SELinux)labeling or not. # Flag is ignored on label disabled systems. # # label = true @@ -167,7 +168,7 @@ # # netns = "private" -# Create /etc/hosts for the container. By default, container engines manage +# Create /etc/hosts for the container. By default, container engine manage # /etc/hosts, automatically adding the container's own IP address. # # no_hosts = false @@ -228,7 +229,7 @@ # # network_config_dir = "/etc/cni/net.d/" -[libpod] +[engine] # Cgroup management implementation used for the runtime. # Valid options “systemd” or “cgroupfs” @@ -260,7 +261,7 @@ # # detach_keys = "ctrl-p,ctrl-q" -# Determines whether libpod will reserve ports on the host when they are +# Determines whether engine will reserve ports on the host when they are # forwarded to containers. When enabled, when ports are forwarded to containers, # ports are held open by as long as the container is running, ensuring that # they cannot be reused by other programs on the host. However, this can cause @@ -297,8 +298,8 @@ # # lock_type** = "shm" -# Default libpod namespace -# If libpod is joined to a namespace, it will see only containers and pods +# Default engine namespace +# If engine is joined to a namespace, it will see only containers and pods # that were created in the same namespace, and will create new containers and # pods in that namespace. # The default namespace is "", which corresponds to no namespace. When no @@ -316,7 +317,10 @@ # # num_locks = 2048 -# Directory for persistent libpod files (database, etc) +# Whether to pull new image before running a container +# pull_policy = "missing" + +# Directory for persistent engine files (database, etc) # By default, this will be configured relative to where the containers/storage # stores containers # Uncomment to change location from this default @@ -339,12 +343,12 @@ # runtime = "runc" # List of the OCI runtimes that support --format=json. When json is supported -# libpod will use it for reporting nicer errors. +# engine will use it for reporting nicer errors. # # runtime_supports_json = ["crun", "runc"] # Paths to look for a valid OCI runtime (runc, runv, etc) -[libpod.runtimes] +[engine.runtimes] # runc = [ # "/usr/bin/runc", # "/usr/sbin/runc", @@ -368,7 +372,7 @@ # Number of seconds to wait for container to exit before sending kill signal. #stop_timeout = 10 -# The [libpod.runtimes] table MUST be the last entry in this file. +# The [engine.runtimes] table MUST be the last entry in this file. # (Unless another table is added) # TOML does not provide a way to end a table other than a further table being # defined, so every key hereafter will be part of [runtimes] and not the main diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go index 6b83d7703..dca320d87 100644 --- a/vendor/github.com/containers/common/pkg/config/default.go +++ b/vendor/github.com/containers/common/pkg/config/default.go @@ -98,6 +98,8 @@ const ( // DefaultPidsLimit is the default value for maximum number of processes // allowed inside a container DefaultPidsLimit = 2048 + // DefaultPullPolicy pulls the image if it does not exist locally + DefaultPullPolicy = "missing" // DefaultRootlessSignaturePolicyPath is the default value for the // rootless policy.json file. DefaultRootlessSignaturePolicyPath = ".config/containers/policy.json" @@ -116,7 +118,7 @@ const ( // DefaultConfig defines the default values from containers.conf func DefaultConfig() (*Config, error) { - defaultLibpodConfig, err := defaultConfigFromMemory() + defaultEngineConfig, err := defaultConfigFromMemory() if err != nil { return nil, err } @@ -175,14 +177,14 @@ func DefaultConfig() (*Config, error) { NetworkConfigDir: cniConfigDir, CNIPluginDirs: cniBinDir, }, - Libpod: *defaultLibpodConfig, + Engine: *defaultEngineConfig, }, nil } -// defaultConfigFromMemory returns a default libpod configuration. Note that the +// defaultConfigFromMemory returns a default engine configuration. Note that the // config is different for root and rootless. It also parses the storage.conf. -func defaultConfigFromMemory() (*LibpodConfig, error) { - c := new(LibpodConfig) +func defaultConfigFromMemory() (*EngineConfig, error) { + c := new(EngineConfig) tmp, err := defaultTmpDir() if err != nil { return nil, err @@ -201,7 +203,6 @@ func defaultConfigFromMemory() (*LibpodConfig, error) { } c.StaticDir = filepath.Join(storeOpts.GraphRoot, "libpod") c.VolumePath = filepath.Join(storeOpts.GraphRoot, "volumes") - c.StorageConfig = storeOpts c.HooksDir = DefaultHooksDirs c.ImageDefaultTransport = _defaultTransport @@ -249,6 +250,7 @@ func defaultConfigFromMemory() (*LibpodConfig, error) { "/usr/local/sbin/conmon", "/run/current-system/sw/bin/conmon", } + c.PullPolicy = DefaultPullPolicy c.RuntimeSupportsJSON = []string{ "crun", "runc", diff --git a/vendor/github.com/containers/common/pkg/config/libpodConfig.go b/vendor/github.com/containers/common/pkg/config/libpodConfig.go new file mode 100644 index 000000000..be168208b --- /dev/null +++ b/vendor/github.com/containers/common/pkg/config/libpodConfig.go @@ -0,0 +1,382 @@ +package config + +/* libpodConfig.go contains deprecated functionality and should not be used any longer */ + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" + + "github.com/BurntSushi/toml" + "github.com/containers/common/pkg/unshare" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +const ( + // _rootlessConfigPath is the path to the rootless libpod.conf in $HOME. + _rootlessConfigPath = ".config/containers/libpod.conf" + + // _rootConfigPath is the path to the libpod configuration file + // This file is loaded to replace the builtin default config before + // runtime options (e.g. WithStorageConfig) are applied. + // If it is not present, the builtin default config is used instead + // This path can be overridden when the runtime is created by using + // NewRuntimeFromConfig() instead of NewRuntime(). + _rootConfigPath = _installPrefix + "/share/containers/libpod.conf" + + // _rootOverrideConfigPath is the path to an override for the default libpod + // configuration file. If OverrideConfigPath exists, it will be used in + // place of the configuration file pointed to by ConfigPath. + _rootOverrideConfigPath = _etcDir + "/containers/libpod.conf" +) + +// ConfigFromLibpod contains configuration options used to set up a libpod runtime +type ConfigFromLibpod struct { + // NOTE: when changing this struct, make sure to update (*Config).Merge(). + + // SetOptions contains a subset of config options. It's used to indicate if + // a given option has either been set by the user or by a parsed libpod + // configuration file. If not, the corresponding option might be + // overwritten by values from the database. This behavior guarantees + // backwards compat with older version of libpod and Podman. + SetOptions + + // VolumePath is the default location that named volumes will be created + // under. This convention is followed by the default volume driver, but + // may not be by other drivers. + VolumePath string `toml:"volume_path,omitempty"` + + // ImageDefaultTransport is the default transport method used to fetch + // images. + ImageDefaultTransport string `toml:"image_default_transport,omitempty"` + + // SignaturePolicyPath is the path to a signature policy to use for + // validating images. If left empty, the containers/image default signature + // policy will be used. + SignaturePolicyPath string `toml:"signature_policy_path,omitempty"` + + // OCIRuntime is the OCI runtime to use. + OCIRuntime string `toml:"runtime,omitempty"` + + // OCIRuntimes are the set of configured OCI runtimes (default is runc). + OCIRuntimes map[string][]string `toml:"runtimes,omitempty"` + + // RuntimeSupportsJSON is the list of the OCI runtimes that support + // --format=json. + RuntimeSupportsJSON []string `toml:"runtime_supports_json,omitempty"` + + // RuntimeSupportsNoCgroups is a list of OCI runtimes that support + // running containers without CGroups. + RuntimeSupportsNoCgroups []string `toml:"runtime_supports_nocgroups,omitempty"` + + // RuntimePath is the path to OCI runtime binary for launching containers. + // The first path pointing to a valid file will be used This is used only + // when there are no OCIRuntime/OCIRuntimes defined. It is used only to be + // backward compatible with older versions of Podman. + RuntimePath []string `toml:"runtime_path,omitempty"` + + // ConmonPath is the path to the Conmon binary used for managing containers. + // The first path pointing to a valid file will be used. + ConmonPath []string `toml:"conmon_path,omitempty"` + + // ConmonEnvVars are environment variables to pass to the Conmon binary + // when it is launched. + ConmonEnvVars []string `toml:"conmon_env_vars,omitempty"` + + // CGroupManager is the CGroup Manager to use Valid values are "cgroupfs" + // and "systemd". + CgroupManager string `toml:"cgroup_manager,omitempty"` + + // InitPath is the path to the container-init binary. + InitPath string `toml:"init_path,omitempty"` + + // StaticDir is the path to a persistent directory to store container + // files. + StaticDir string `toml:"static_dir,omitempty"` + + // TmpDir is the path to a temporary directory to store per-boot container + // files. Must be stored in a tmpfs. + TmpDir string `toml:"tmp_dir,omitempty"` + + // MaxLogSize is the maximum size of container logfiles. + MaxLogSize int64 `toml:"max_log_size,omitempty"` + + // NoPivotRoot sets whether to set no-pivot-root in the OCI runtime. + NoPivotRoot bool `toml:"no_pivot_root,omitempty"` + + // CNIConfigDir sets the directory where CNI configuration files are + // stored. + CNIConfigDir string `toml:"cni_config_dir,omitempty"` + + // CNIPluginDir sets a number of directories where the CNI network + // plugins can be located. + CNIPluginDir []string `toml:"cni_plugin_dir,omitempty"` + + // CNIDefaultNetwork is the network name of the default CNI network + // to attach pods to. + CNIDefaultNetwork string `toml:"cni_default_network,omitempty"` + + // HooksDir holds paths to the directories containing hooks + // configuration files. When the same filename is present in in + // multiple directories, the file in the directory listed last in + // this slice takes precedence. + HooksDir []string `toml:"hooks_dir,omitempty"` + + // Namespace is the libpod namespace to use. Namespaces are used to create + // scopes to separate containers and pods in the state. When namespace is + // set, libpod will only view containers and pods in the same namespace. All + // containers and pods created will default to the namespace set here. A + // namespace of "", the empty string, is equivalent to no namespace, and all + // containers and pods will be visible. The default namespace is "". + Namespace string `toml:"namespace,omitempty"` + + // InfraImage is the image a pod infra container will use to manage + // namespaces. + InfraImage string `toml:"infra_image,omitempty"` + + // InfraCommand is the command run to start up a pod infra container. + InfraCommand string `toml:"infra_command,omitempty"` + + // EnablePortReservation determines whether libpod will reserve ports on the + // host when they are forwarded to containers. When enabled, when ports are + // forwarded to containers, they are held open by conmon as long as the + // container is running, ensuring that they cannot be reused by other + // programs on the host. However, this can cause significant memory usage if + // a container has many ports forwarded to it. Disabling this can save + // memory. + EnablePortReservation bool `toml:"enable_port_reservation,omitempty"` + + // EnableLabeling indicates whether libpod will support container labeling. + EnableLabeling bool `toml:"label,omitempty"` + + // NetworkCmdPath is the path to the slirp4netns binary. + NetworkCmdPath string `toml:"network_cmd_path,omitempty"` + + // NumLocks is the number of locks to make available for containers and + // pods. + NumLocks uint32 `toml:"num_locks,omitempty"` + + // LockType is the type of locking to use. + LockType string `toml:"lock_type,omitempty"` + + // EventsLogger determines where events should be logged. + EventsLogger string `toml:"events_logger,omitempty"` + + // EventsLogFilePath is where the events log is stored. + EventsLogFilePath string `toml:"events_logfile_path,omitempty"` + + //DetachKeys is the sequence of keys used to detach a container. + DetachKeys string `toml:"detach_keys,omitempty"` + + // SDNotify tells Libpod to allow containers to notify the host systemd of + // readiness using the SD_NOTIFY mechanism. + SDNotify bool `toml:",omitempty"` + + // CgroupCheck indicates the configuration has been rewritten after an + // upgrade to Fedora 31 to change the default OCI runtime for cgroupsv2. + CgroupCheck bool `toml:"cgroup_check,omitempty"` +} + +// newLibpodConfig creates a new ConfigFromLibpod and converts it to Config. +// Depending if we're running as root or rootless, we then merge the system configuration followed +// by merging the default config (hard-coded default in memory). +// Note that the OCI runtime is hard-set to `crun` if we're running on a system +// with cgroupsv2. Other OCI runtimes are not yet supporting cgroupsv2. This +// might change in the future. +func newLibpodConfig(c *Config) error { + // Start with the default config and interatively merge + // fields in the system configs. + config := c.libpodConfig() + + // Now, check if the user can access system configs and merge them if needed. + configs, err := systemLibpodConfigs() + if err != nil { + return errors.Wrapf(err, "error finding config on system") + } + + for _, path := range configs { + config, err = readLibpodConfigFromFile(path, config) + if err != nil { + return errors.Wrapf(err, "error reading system config %q", path) + } + } + + // Since runc does not currently support cgroupV2 + // Change to default crun on first running of libpod.conf + // TODO Once runc has support for cgroups, this function should be removed. + if !config.CgroupCheck && unshare.IsRootless() { + cgroupsV2, err := isCgroup2UnifiedMode() + if err != nil { + return err + } + if cgroupsV2 { + path, err := exec.LookPath("crun") + if err != nil { + // Can't find crun path so do nothing + logrus.Warnf("Can not find crun package on the host, containers might fail to run on cgroup V2 systems without crun: %q", err) + } else { + config.CgroupCheck = true + config.OCIRuntime = path + } + } + } + + c.libpodToContainersConfig(config) + + return nil +} + +// readConfigFromFile reads the specified config file at `path` and attempts to +// unmarshal its content into a Config. The config param specifies the previous +// default config. If the path, only specifies a few fields in the Toml file +// the defaults from the config parameter will be used for all other fields. +func readLibpodConfigFromFile(path string, config *ConfigFromLibpod) (*ConfigFromLibpod, error) { + logrus.Debugf("Reading configuration file %q", path) + _, err := toml.DecodeFile(path, config) + if err != nil { + return nil, fmt.Errorf("unable to decode configuration %v: %v", path, err) + } + + // For the sake of backwards compat we need to check if the config fields + // with *Set suffix are set in the config. Note that the storage-related + // fields are NOT set in the config here but in the storage.conf OR directly + // by the user. + if config.VolumePath != "" { + config.VolumePathSet = true + } + if config.StaticDir != "" { + config.StaticDirSet = true + } + if config.TmpDir != "" { + config.TmpDirSet = true + } + + return config, err +} + +func systemLibpodConfigs() ([]string, error) { + if unshare.IsRootless() { + path, err := rootlessLibpodConfigPath() + if err != nil { + return nil, err + } + if _, err := os.Stat(path); err == nil { + containersConfPath, err := rootlessConfigPath() + if err != nil { + containersConfPath = filepath.Join("$HOME", UserOverrideContainersConfig) + } + // TODO: Raise to Warnf, when Podman is updated to + // remove libpod.conf by default + logrus.Debugf("Found deprecated file %s, please remove. Use %s to override defaults.\n", path, containersConfPath) + return []string{path}, nil + } + return nil, err + } + + configs := []string{} + if _, err := os.Stat(_rootConfigPath); err == nil { + // TODO: Raise to Warnf, when Podman is updated to + // remove libpod.conf by default + logrus.Debugf("Found deprecated file %s, please remove. Use %s to override defaults.\n", _rootConfigPath, OverrideContainersConfig) + configs = append(configs, _rootConfigPath) + } + if _, err := os.Stat(_rootOverrideConfigPath); err == nil { + // TODO: Raise to Warnf, when Podman is updated to + // remove libpod.conf by default + logrus.Debugf("Found deprecated file %s, please remove. Use %s to override defaults.\n", _rootOverrideConfigPath, OverrideContainersConfig) + configs = append(configs, _rootOverrideConfigPath) + } + return configs, nil +} + +func rootlessLibpodConfigPath() (string, error) { + home, err := unshare.HomeDir() + if err != nil { + return "", err + } + + return filepath.Join(home, _rootlessConfigPath), nil +} + +func (c *Config) libpodConfig() *ConfigFromLibpod { + return &ConfigFromLibpod{ + SignaturePolicyPath: c.Containers.SignaturePolicyPath, + InitPath: c.Containers.InitPath, + MaxLogSize: c.Containers.LogSizeMax, + EnableLabeling: c.Containers.EnableLabeling, + + SetOptions: c.Engine.SetOptions, + VolumePath: c.Engine.VolumePath, + ImageDefaultTransport: c.Engine.ImageDefaultTransport, + OCIRuntime: c.Engine.OCIRuntime, + OCIRuntimes: c.Engine.OCIRuntimes, + RuntimeSupportsJSON: c.Engine.RuntimeSupportsJSON, + RuntimeSupportsNoCgroups: c.Engine.RuntimeSupportsNoCgroups, + RuntimePath: c.Engine.RuntimePath, + ConmonPath: c.Engine.ConmonPath, + ConmonEnvVars: c.Engine.ConmonEnvVars, + CgroupManager: c.Engine.CgroupManager, + StaticDir: c.Engine.StaticDir, + TmpDir: c.Engine.TmpDir, + NoPivotRoot: c.Engine.NoPivotRoot, + HooksDir: c.Engine.HooksDir, + Namespace: c.Engine.Namespace, + InfraImage: c.Engine.InfraImage, + InfraCommand: c.Engine.InfraCommand, + EnablePortReservation: c.Engine.EnablePortReservation, + NetworkCmdPath: c.Engine.NetworkCmdPath, + NumLocks: c.Engine.NumLocks, + LockType: c.Engine.LockType, + EventsLogger: c.Engine.EventsLogger, + EventsLogFilePath: c.Engine.EventsLogFilePath, + DetachKeys: c.Engine.DetachKeys, + SDNotify: c.Engine.SDNotify, + CgroupCheck: c.Engine.CgroupCheck, + + CNIConfigDir: c.Network.NetworkConfigDir, + CNIPluginDir: c.Network.CNIPluginDirs, + CNIDefaultNetwork: c.Network.DefaultNetwork, + } +} + +func (c *Config) libpodToContainersConfig(libpodConf *ConfigFromLibpod) { + + c.Containers.SignaturePolicyPath = libpodConf.SignaturePolicyPath + c.Containers.InitPath = libpodConf.InitPath + c.Containers.LogSizeMax = libpodConf.MaxLogSize + c.Containers.EnableLabeling = libpodConf.EnableLabeling + + c.Engine.SetOptions = libpodConf.SetOptions + c.Engine.VolumePath = libpodConf.VolumePath + c.Engine.ImageDefaultTransport = libpodConf.ImageDefaultTransport + c.Engine.OCIRuntime = libpodConf.OCIRuntime + c.Engine.OCIRuntimes = libpodConf.OCIRuntimes + c.Engine.RuntimeSupportsJSON = libpodConf.RuntimeSupportsJSON + c.Engine.RuntimeSupportsNoCgroups = libpodConf.RuntimeSupportsNoCgroups + c.Engine.RuntimePath = libpodConf.RuntimePath + c.Engine.ConmonPath = libpodConf.ConmonPath + c.Engine.ConmonEnvVars = libpodConf.ConmonEnvVars + c.Engine.CgroupManager = libpodConf.CgroupManager + c.Engine.StaticDir = libpodConf.StaticDir + c.Engine.TmpDir = libpodConf.TmpDir + c.Engine.NoPivotRoot = libpodConf.NoPivotRoot + c.Engine.HooksDir = libpodConf.HooksDir + c.Engine.Namespace = libpodConf.Namespace + c.Engine.InfraImage = libpodConf.InfraImage + c.Engine.InfraCommand = libpodConf.InfraCommand + c.Engine.EnablePortReservation = libpodConf.EnablePortReservation + c.Engine.NetworkCmdPath = libpodConf.NetworkCmdPath + c.Engine.NumLocks = libpodConf.NumLocks + c.Engine.LockType = libpodConf.LockType + c.Engine.EventsLogger = libpodConf.EventsLogger + c.Engine.EventsLogFilePath = libpodConf.EventsLogFilePath + c.Engine.DetachKeys = libpodConf.DetachKeys + c.Engine.SDNotify = libpodConf.SDNotify + c.Engine.CgroupCheck = libpodConf.CgroupCheck + + c.Network.NetworkConfigDir = libpodConf.CNIConfigDir + c.Network.CNIPluginDirs = libpodConf.CNIPluginDir + c.Network.DefaultNetwork = libpodConf.CNIDefaultNetwork +} diff --git a/vendor/github.com/containers/storage/VERSION b/vendor/github.com/containers/storage/VERSION index 4a02d2c31..c807441cf 100644 --- a/vendor/github.com/containers/storage/VERSION +++ b/vendor/github.com/containers/storage/VERSION @@ -1 +1 @@ -1.16.2 +1.16.3 diff --git a/vendor/github.com/containers/storage/drivers/chown.go b/vendor/github.com/containers/storage/drivers/chown.go index f2f1ec386..7604a86db 100644 --- a/vendor/github.com/containers/storage/drivers/chown.go +++ b/vendor/github.com/containers/storage/drivers/chown.go @@ -5,10 +5,10 @@ import ( "encoding/json" "fmt" "os" - "path/filepath" "github.com/containers/storage/pkg/idtools" "github.com/containers/storage/pkg/reexec" + "github.com/opencontainers/selinux/pkg/pwalk" ) const ( @@ -51,16 +51,13 @@ func chownByMapsMain() { if len(toHost.UIDs()) == 0 && len(toHost.GIDs()) == 0 { toHost = nil } - chown := func(path string, info os.FileInfo, err error) error { - if err != nil { - return fmt.Errorf("error walking to %q: %v", path, err) - } + chown := func(path string, info os.FileInfo, _ error) error { if path == "." { return nil } return platformLChown(path, info, toHost, toContainer) } - if err := filepath.Walk(".", chown); err != nil { + if err := pwalk.Walk(".", chown); err != nil { fmt.Fprintf(os.Stderr, "error during chown: %v", err) os.Exit(1) } diff --git a/vendor/github.com/containers/storage/drivers/chown_unix.go b/vendor/github.com/containers/storage/drivers/chown_unix.go index 94c641536..3a3978b71 100644 --- a/vendor/github.com/containers/storage/drivers/chown_unix.go +++ b/vendor/github.com/containers/storage/drivers/chown_unix.go @@ -12,66 +12,63 @@ import ( ) func platformLChown(path string, info os.FileInfo, toHost, toContainer *idtools.IDMappings) error { - sysinfo := info.Sys() - if st, ok := sysinfo.(*syscall.Stat_t); ok { - // Map an on-disk UID/GID pair from host to container - // using the first map, then back to the host using the - // second map. Skip that first step if they're 0, to - // compensate for cases where a parent layer should - // have had a mapped value, but didn't. - uid, gid := int(st.Uid), int(st.Gid) - if toContainer != nil { - pair := idtools.IDPair{ - UID: uid, - GID: gid, - } - mappedUID, mappedGID, err := toContainer.ToContainer(pair) - if err != nil { - if (uid != 0) || (gid != 0) { - return fmt.Errorf("error mapping host ID pair %#v for %q to container: %v", pair, path, err) - } - mappedUID, mappedGID = uid, gid - } - uid, gid = mappedUID, mappedGID + st, ok := info.Sys().(*syscall.Stat_t) + if !ok { + return nil + } + // Map an on-disk UID/GID pair from host to container + // using the first map, then back to the host using the + // second map. Skip that first step if they're 0, to + // compensate for cases where a parent layer should + // have had a mapped value, but didn't. + uid, gid := int(st.Uid), int(st.Gid) + if toContainer != nil { + pair := idtools.IDPair{ + UID: uid, + GID: gid, } - if toHost != nil { - pair := idtools.IDPair{ - UID: uid, - GID: gid, - } - mappedPair, err := toHost.ToHost(pair) - if err != nil { - return fmt.Errorf("error mapping container ID pair %#v for %q to host: %v", pair, path, err) + mappedUID, mappedGID, err := toContainer.ToContainer(pair) + if err != nil { + if (uid != 0) || (gid != 0) { + return fmt.Errorf("error mapping host ID pair %#v for %q to container: %v", pair, path, err) } - uid, gid = mappedPair.UID, mappedPair.GID + mappedUID, mappedGID = uid, gid + } + uid, gid = mappedUID, mappedGID + } + if toHost != nil { + pair := idtools.IDPair{ + UID: uid, + GID: gid, + } + mappedPair, err := toHost.ToHost(pair) + if err != nil { + return fmt.Errorf("error mapping container ID pair %#v for %q to host: %v", pair, path, err) + } + uid, gid = mappedPair.UID, mappedPair.GID + } + if uid != int(st.Uid) || gid != int(st.Gid) { + cap, err := system.Lgetxattr(path, "security.capability") + if err != nil && err != system.ErrNotSupportedPlatform { + return fmt.Errorf("%s: Lgetxattr(%q): %v", os.Args[0], path, err) } - if uid != int(st.Uid) || gid != int(st.Gid) { - stat, err := os.Lstat(path) - if err != nil { - return fmt.Errorf("%s: lstat(%q): %v", os.Args[0], path, err) - } - cap, err := system.Lgetxattr(path, "security.capability") - if err != nil && err != system.ErrNotSupportedPlatform { - return fmt.Errorf("%s: Lgetxattr(%q): %v", os.Args[0], path, err) - } - // Make the change. - if err := syscall.Lchown(path, uid, gid); err != nil { - return fmt.Errorf("%s: chown(%q): %v", os.Args[0], path, err) - } - // Restore the SUID and SGID bits if they were originally set. - if (stat.Mode()&os.ModeSymlink == 0) && stat.Mode()&(os.ModeSetuid|os.ModeSetgid) != 0 { - if err := os.Chmod(path, stat.Mode()); err != nil { - return fmt.Errorf("%s: chmod(%q): %v", os.Args[0], path, err) - } + // Make the change. + if err := syscall.Lchown(path, uid, gid); err != nil { + return fmt.Errorf("%s: chown(%q): %v", os.Args[0], path, err) + } + // Restore the SUID and SGID bits if they were originally set. + if (info.Mode()&os.ModeSymlink == 0) && info.Mode()&(os.ModeSetuid|os.ModeSetgid) != 0 { + if err := os.Chmod(path, info.Mode()); err != nil { + return fmt.Errorf("%s: chmod(%q): %v", os.Args[0], path, err) } - if cap != nil { - if err := system.Lsetxattr(path, "security.capability", cap, 0); err != nil { - return fmt.Errorf("%s: Lsetxattr(%q): %v", os.Args[0], path, err) - } + } + if cap != nil { + if err := system.Lsetxattr(path, "security.capability", cap, 0); err != nil { + return fmt.Errorf("%s: Lsetxattr(%q): %v", os.Args[0], path, err) } - } + } return nil } diff --git a/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go b/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go index 867ad1196..d0c7fab0a 100644 --- a/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go +++ b/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go @@ -1209,7 +1209,7 @@ func (devices *DeviceSet) growFS(info *devInfo) error { options = joinMountOptions(options, devices.mountOptions) if err := mount.Mount(info.DevName(), fsMountPoint, devices.BaseDeviceFilesystem, options); err != nil { - return fmt.Errorf("Error mounting '%s' on '%s': %s\n%v", info.DevName(), fsMountPoint, err, string(dmesg.Dmesg(256))) + return errors.Wrapf(err, "Failed to mount; dmesg: %s", string(dmesg.Dmesg(256))) } defer unix.Unmount(fsMountPoint, unix.MNT_DETACH) @@ -2414,7 +2414,7 @@ func (devices *DeviceSet) MountDevice(hash, path string, moptions graphdriver.Mo options = joinMountOptions(options, label.FormatMountLabel("", moptions.MountLabel)) if err := mount.Mount(info.DevName(), path, fstype, options); err != nil { - return fmt.Errorf("devmapper: Error mounting '%s' on '%s': %s\n%v", info.DevName(), path, err, string(dmesg.Dmesg(256))) + return errors.Wrapf(err, "Failed to mount; dmesg: %s", string(dmesg.Dmesg(256))) } if fstype == xfs && devices.xfsNospaceRetries != "" { diff --git a/vendor/github.com/containers/storage/go.mod b/vendor/github.com/containers/storage/go.mod index 8a3b7bb60..84bfc9616 100644 --- a/vendor/github.com/containers/storage/go.mod +++ b/vendor/github.com/containers/storage/go.mod @@ -11,7 +11,7 @@ require ( github.com/mistifyio/go-zfs v2.1.1+incompatible github.com/opencontainers/go-digest v1.0.0-rc1 github.com/opencontainers/runc v1.0.0-rc9 - github.com/opencontainers/selinux v1.3.3 + github.com/opencontainers/selinux v1.4.0 github.com/pkg/errors v0.9.1 github.com/pquerna/ffjson v0.0.0-20181028064349-e517b90714f7 github.com/sirupsen/logrus v1.4.2 diff --git a/vendor/github.com/containers/storage/go.sum b/vendor/github.com/containers/storage/go.sum index 6674a08f5..5d86e062f 100644 --- a/vendor/github.com/containers/storage/go.sum +++ b/vendor/github.com/containers/storage/go.sum @@ -55,8 +55,8 @@ github.com/opencontainers/runc v1.0.0-rc9 h1:/k06BMULKF5hidyoZymkoDCzdJzltZpz/UU github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/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/selinux v1.3.3 h1:RX0wAeqtvVSYQcr017X3pFXPkLEtB6V4NjRD7gVQgg4= -github.com/opencontainers/selinux v1.3.3/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g= +github.com/opencontainers/selinux v1.4.0 h1:cpiX/2wWIju/6My60T6/z9CxNG7c8xTQyEmA9fChpUo= +github.com/opencontainers/selinux v1.4.0/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= diff --git a/vendor/github.com/containers/storage/pkg/mount/flags_freebsd.go b/vendor/github.com/containers/storage/pkg/mount/flags_freebsd.go deleted file mode 100644 index 5f76f331b..000000000 --- a/vendor/github.com/containers/storage/pkg/mount/flags_freebsd.go +++ /dev/null @@ -1,49 +0,0 @@ -// +build freebsd,cgo - -package mount - -/* -#include <sys/mount.h> -*/ -import "C" - -const ( - // RDONLY will mount the filesystem as read-only. - RDONLY = C.MNT_RDONLY - - // NOSUID will not allow set-user-identifier or set-group-identifier bits to - // take effect. - NOSUID = C.MNT_NOSUID - - // NOEXEC will not allow execution of any binaries on the mounted file system. - NOEXEC = C.MNT_NOEXEC - - // SYNCHRONOUS will allow any I/O to the file system to be done synchronously. - SYNCHRONOUS = C.MNT_SYNCHRONOUS - - // NOATIME will not update the file access time when reading from a file. - NOATIME = C.MNT_NOATIME -) - -// These flags are unsupported. -const ( - BIND = 0 - DIRSYNC = 0 - MANDLOCK = 0 - NODEV = 0 - NODIRATIME = 0 - UNBINDABLE = 0 - RUNBINDABLE = 0 - PRIVATE = 0 - RPRIVATE = 0 - SHARED = 0 - RSHARED = 0 - SLAVE = 0 - RSLAVE = 0 - RBIND = 0 - RELATIVE = 0 - RELATIME = 0 - REMOUNT = 0 - STRICTATIME = 0 - mntDetach = 0 -) diff --git a/vendor/github.com/containers/storage/pkg/mount/flags_linux.go b/vendor/github.com/containers/storage/pkg/mount/flags_linux.go index a5dc5e287..0425d0dd6 100644 --- a/vendor/github.com/containers/storage/pkg/mount/flags_linux.go +++ b/vendor/github.com/containers/storage/pkg/mount/flags_linux.go @@ -82,4 +82,6 @@ const ( // it possible for the kernel to default to relatime or noatime but still // allow userspace to override it. STRICTATIME = unix.MS_STRICTATIME + + mntDetach = unix.MNT_DETACH ) diff --git a/vendor/github.com/containers/storage/pkg/mount/flags_unsupported.go b/vendor/github.com/containers/storage/pkg/mount/flags_unsupported.go index 9ed741e3f..9afd26d4c 100644 --- a/vendor/github.com/containers/storage/pkg/mount/flags_unsupported.go +++ b/vendor/github.com/containers/storage/pkg/mount/flags_unsupported.go @@ -1,4 +1,4 @@ -// +build !linux,!freebsd freebsd,!cgo solaris,!cgo +// +build !linux package mount diff --git a/vendor/github.com/containers/storage/pkg/mount/mount.go b/vendor/github.com/containers/storage/pkg/mount/mount.go index 7197448da..4276d63af 100644 --- a/vendor/github.com/containers/storage/pkg/mount/mount.go +++ b/vendor/github.com/containers/storage/pkg/mount/mount.go @@ -2,12 +2,47 @@ package mount import ( "sort" + "strconv" "strings" - "time" "github.com/containers/storage/pkg/fileutils" ) +// mountError holds an error from a mount or unmount operation +type mountError struct { + op string + source, target string + flags uintptr + data string + err error +} + +// Error returns a string representation of mountError +func (e *mountError) Error() string { + out := e.op + " " + + if e.source != "" { + out += e.source + ":" + e.target + } else { + out += e.target + } + + if e.flags != uintptr(0) { + out += ", flags: 0x" + strconv.FormatUint(uint64(e.flags), 16) + } + if e.data != "" { + out += ", data: " + e.data + } + + out += ": " + e.err.Error() + return out +} + +// Cause returns the underlying cause of the error +func (e *mountError) Cause() error { + return e.err +} + // GetMounts retrieves a list of mounts for the current running process. func GetMounts() ([]*Info, error) { return parseMountTable() @@ -39,13 +74,13 @@ func Mounted(mountpoint string) (bool, error) { // specified like the mount or fstab unix commands: "opt1=val1,opt2=val2". See // flags.go for supported option flags. func Mount(device, target, mType, options string) error { - flag, _ := ParseOptions(options) + flag, data := ParseOptions(options) if flag&REMOUNT != REMOUNT { if mounted, err := Mounted(target); err != nil || mounted { return err } } - return ForceMount(device, target, mType, options) + return mount(device, target, mType, uintptr(flag), data) } // ForceMount will mount a filesystem according to the specified configuration, @@ -60,14 +95,11 @@ func ForceMount(device, target, mType, options string) error { // Unmount lazily unmounts a filesystem on supported platforms, otherwise // does a normal unmount. func Unmount(target string) error { - if mounted, err := Mounted(target); err != nil || !mounted { - return err - } - return ForceUnmount(target) + return unmount(target, mntDetach) } // RecursiveUnmount unmounts the target and all mounts underneath, starting with -// the deepsest mount first. +// the deepest mount first. func RecursiveUnmount(target string) error { mounts, err := GetMounts() if err != nil { @@ -75,16 +107,16 @@ func RecursiveUnmount(target string) error { } // Make the deepest mount be first - sort.Sort(sort.Reverse(byMountpoint(mounts))) + sort.Slice(mounts, func(i, j int) bool { + return len(mounts[i].Mountpoint) > len(mounts[j].Mountpoint) + }) for i, m := range mounts { if !strings.HasPrefix(m.Mountpoint, target) { continue } if err := Unmount(m.Mountpoint); err != nil && i == len(mounts)-1 { - if mounted, err := Mounted(m.Mountpoint); err != nil || mounted { - return err - } + return err // Ignore errors for submounts and continue trying to unmount others // The final unmount should fail if there ane any submounts remaining } @@ -92,15 +124,10 @@ func RecursiveUnmount(target string) error { return nil } -// ForceUnmount will force an unmount of the target filesystem, regardless if -// it is mounted or not. -func ForceUnmount(target string) (err error) { - // Simple retry logic for unmount - for i := 0; i < 10; i++ { - if err = unmount(target, 0); err == nil { - return nil - } - time.Sleep(100 * time.Millisecond) - } - return nil +// ForceUnmount lazily unmounts a filesystem on supported platforms, +// otherwise does a normal unmount. +// +// Deprecated: please use Unmount instead, it is identical. +func ForceUnmount(target string) error { + return unmount(target, mntDetach) } diff --git a/vendor/github.com/containers/storage/pkg/mount/mounter_freebsd.go b/vendor/github.com/containers/storage/pkg/mount/mounter_freebsd.go index 814896cc9..b31cf99d0 100644 --- a/vendor/github.com/containers/storage/pkg/mount/mounter_freebsd.go +++ b/vendor/github.com/containers/storage/pkg/mount/mounter_freebsd.go @@ -14,8 +14,6 @@ import ( "fmt" "strings" "unsafe" - - "golang.org/x/sys/unix" ) func allocateIOVecs(options []string) []C.struct_iovec { @@ -54,7 +52,3 @@ func mount(device, target, mType string, flag uintptr, data string) error { } return nil } - -func unmount(target string, flag int) error { - return unix.Unmount(target, flag) -} diff --git a/vendor/github.com/containers/storage/pkg/mount/mounter_linux.go b/vendor/github.com/containers/storage/pkg/mount/mounter_linux.go index de47c7af8..594cd0881 100644 --- a/vendor/github.com/containers/storage/pkg/mount/mounter_linux.go +++ b/vendor/github.com/containers/storage/pkg/mount/mounter_linux.go @@ -35,25 +35,40 @@ func mount(device, target, mType string, flags uintptr, data string) error { // Initial call applying all non-propagation flags for mount // or remount with changed data if err := unix.Mount(device, target, mType, oflags, data); err != nil { - return err + return &mountError{ + op: "mount", + source: device, + target: target, + flags: oflags, + data: data, + err: err, + } } } if flags&ptypes != 0 { // Change the propagation type. if err := unix.Mount("", target, "", flags&pflags, ""); err != nil { - return err + return &mountError{ + op: "remount", + target: target, + flags: flags & pflags, + err: err, + } } } if oflags&broflags == broflags { // Remount the bind to apply read only. - return unix.Mount("", target, "", oflags|unix.MS_REMOUNT, "") + if err := unix.Mount("", target, "", oflags|unix.MS_REMOUNT, ""); err != nil { + return &mountError{ + op: "remount-ro", + target: target, + flags: oflags | unix.MS_REMOUNT, + err: err, + } + } } return nil } - -func unmount(target string, flag int) error { - return unix.Unmount(target, flag) -} diff --git a/vendor/github.com/containers/storage/pkg/mount/mounter_solaris.go b/vendor/github.com/containers/storage/pkg/mount/mounter_solaris.go deleted file mode 100644 index 48b86771e..000000000 --- a/vendor/github.com/containers/storage/pkg/mount/mounter_solaris.go +++ /dev/null @@ -1,34 +0,0 @@ -// +build solaris,cgo - -package mount - -import ( - "unsafe" - - "golang.org/x/sys/unix" -) - -// #include <stdlib.h> -// #include <stdio.h> -// #include <sys/mount.h> -// int Mount(const char *spec, const char *dir, int mflag, -// char *fstype, char *dataptr, int datalen, char *optptr, int optlen) { -// return mount(spec, dir, mflag, fstype, dataptr, datalen, optptr, optlen); -// } -import "C" - -func mount(device, target, mType string, flag uintptr, data string) error { - spec := C.CString(device) - dir := C.CString(target) - fstype := C.CString(mType) - _, err := C.Mount(spec, dir, C.int(flag), fstype, nil, 0, nil, 0) - C.free(unsafe.Pointer(spec)) - C.free(unsafe.Pointer(dir)) - C.free(unsafe.Pointer(fstype)) - return err -} - -func unmount(target string, flag int) error { - err := unix.Unmount(target, flag) - return err -} diff --git a/vendor/github.com/containers/storage/pkg/mount/mounter_unsupported.go b/vendor/github.com/containers/storage/pkg/mount/mounter_unsupported.go index a2a3bb457..42d1d422c 100644 --- a/vendor/github.com/containers/storage/pkg/mount/mounter_unsupported.go +++ b/vendor/github.com/containers/storage/pkg/mount/mounter_unsupported.go @@ -1,11 +1,7 @@ -// +build !linux,!freebsd,!solaris freebsd,!cgo solaris,!cgo +// +build !linux package mount func mount(device, target, mType string, flag uintptr, data string) error { panic("Not implemented") } - -func unmount(target string, flag int) error { - panic("Not implemented") -} diff --git a/vendor/github.com/containers/storage/pkg/mount/mountinfo.go b/vendor/github.com/containers/storage/pkg/mount/mountinfo.go index ff4cc1d86..e3fc3535e 100644 --- a/vendor/github.com/containers/storage/pkg/mount/mountinfo.go +++ b/vendor/github.com/containers/storage/pkg/mount/mountinfo.go @@ -38,17 +38,3 @@ type Info struct { // VfsOpts represents per super block options. VfsOpts string } - -type byMountpoint []*Info - -func (by byMountpoint) Len() int { - return len(by) -} - -func (by byMountpoint) Less(i, j int) bool { - return by[i].Mountpoint < by[j].Mountpoint -} - -func (by byMountpoint) Swap(i, j int) { - by[i], by[j] = by[j], by[i] -} diff --git a/vendor/github.com/containers/storage/pkg/mount/mountinfo_linux.go b/vendor/github.com/containers/storage/pkg/mount/mountinfo_linux.go index be69fee1d..19556d06b 100644 --- a/vendor/github.com/containers/storage/pkg/mount/mountinfo_linux.go +++ b/vendor/github.com/containers/storage/pkg/mount/mountinfo_linux.go @@ -1,5 +1,3 @@ -// +build linux - package mount import ( @@ -7,25 +5,10 @@ import ( "fmt" "io" "os" + "strconv" "strings" -) -const ( - /* 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue - (1)(2)(3) (4) (5) (6) (7) (8) (9) (10) (11) - - (1) mount ID: unique identifier of the mount (may be reused after umount) - (2) parent ID: ID of parent (or of self for the top of the mount tree) - (3) major:minor: value of st_dev for files on filesystem - (4) root: root of the mount within the filesystem - (5) mount point: mount point relative to the process's root - (6) mount options: per mount options - (7) optional fields: zero or more fields of the form "tag[:value]" - (8) separator: marks the end of the optional fields - (9) filesystem type: name of filesystem of the form "type[.subtype]" - (10) mount source: filesystem specific information or "none" - (11) super options: per super block options*/ - mountinfoFormat = "%d %d %d:%d %s %s %s %s" + "github.com/pkg/errors" ) // Parse /proc/self/mountinfo because comparing Dev and ino does not work from @@ -41,43 +24,85 @@ func parseMountTable() ([]*Info, error) { } func parseInfoFile(r io.Reader) ([]*Info, error) { - var ( - s = bufio.NewScanner(r) - out = []*Info{} - ) + s := bufio.NewScanner(r) + out := []*Info{} for s.Scan() { - if err := s.Err(); err != nil { - return nil, err + /* + 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue + (0)(1)(2) (3) (4) (5) (6) (7) (8) (9) (10) + + (0) mount ID: unique identifier of the mount (may be reused after umount) + (1) parent ID: ID of parent (or of self for the top of the mount tree) + (2) major:minor: value of st_dev for files on filesystem + (3) root: root of the mount within the filesystem + (4) mount point: mount point relative to the process's root + (5) mount options: per mount options + (6) optional fields: zero or more fields of the form "tag[:value]" + (7) separator: marks the end of the optional fields + (8) filesystem type: name of filesystem of the form "type[.subtype]" + (9) mount source: filesystem specific information or "none" + (10) super options: per super block options + */ + text := s.Text() + fields := strings.Split(text, " ") + numFields := len(fields) + if numFields < 10 { + // should be at least 10 fields + return nil, errors.Errorf("Parsing %q failed: not enough fields (%d)", text, numFields) } - var ( - p = &Info{} - text = s.Text() - optionalFields string - ) + p := &Info{} + // ignore any number parsing errors, there should not be any + p.ID, _ = strconv.Atoi(fields[0]) + p.Parent, _ = strconv.Atoi(fields[1]) + mm := strings.Split(fields[2], ":") + if len(mm) != 2 { + return nil, fmt.Errorf("Parsing %q failed: unexpected minor:major pair %s", text, mm) + } + p.Major, _ = strconv.Atoi(mm[0]) + p.Minor, _ = strconv.Atoi(mm[1]) + p.Root = fields[3] + p.Mountpoint = fields[4] + p.Opts = fields[5] - if _, err := fmt.Sscanf(text, mountinfoFormat, - &p.ID, &p.Parent, &p.Major, &p.Minor, - &p.Root, &p.Mountpoint, &p.Opts, &optionalFields); err != nil { - return nil, fmt.Errorf("Scanning '%s' failed: %s", text, err) + // one or more optional fields, when a separator (-) + i := 6 + for ; i < numFields && fields[i] != "-"; i++ { + switch i { + case 6: + p.Optional = string(fields[6]) + default: + /* NOTE there might be more optional fields before the separator, + such as fields[7] or fields[8], although as of Linux kernel 5.5 + the only known ones are mount propagation flags in fields[6]. + The correct behavior is to ignore any unknown optional fields. + */ + } } - // Safe as mountinfo encodes mountpoints with spaces as \040. - index := strings.Index(text, " - ") - postSeparatorFields := strings.Fields(text[index+3:]) - if len(postSeparatorFields) < 3 { - return nil, fmt.Errorf("Error found less than 3 fields post '-' in %q", text) + if i == numFields { + return nil, fmt.Errorf("Parsing %q failed: missing - separator", text) } - if optionalFields != "-" { - p.Optional = optionalFields + // There should be 3 fields after the separator... + if i+4 > numFields { + return nil, fmt.Errorf("Parsing %q failed: not enough fields after a - separator", text) } + // ... but in Linux <= 3.9 mounting a cifs with spaces in a share name + // (like "//serv/My Documents") _may_ end up having a space in the last field + // of mountinfo (like "unc=//serv/My Documents"). Since kernel 3.10-rc1, cifs + // option unc= is ignored, so a space should not appear. In here we ignore + // those "extra" fields caused by extra spaces. + p.Fstype = fields[i+1] + p.Source = fields[i+2] + p.VfsOpts = fields[i+3] - p.Fstype = postSeparatorFields[0] - p.Source = postSeparatorFields[1] - p.VfsOpts = strings.Join(postSeparatorFields[2:], " ") out = append(out, p) } + if err := s.Err(); err != nil { + return nil, err + } + return out, nil } diff --git a/vendor/github.com/containers/storage/pkg/mount/mountinfo_solaris.go b/vendor/github.com/containers/storage/pkg/mount/mountinfo_solaris.go deleted file mode 100644 index ad9ab57f8..000000000 --- a/vendor/github.com/containers/storage/pkg/mount/mountinfo_solaris.go +++ /dev/null @@ -1,37 +0,0 @@ -// +build solaris,cgo - -package mount - -/* -#include <stdio.h> -#include <sys/mnttab.h> -*/ -import "C" - -import ( - "fmt" -) - -func parseMountTable() ([]*Info, error) { - mnttab := C.fopen(C.CString(C.MNTTAB), C.CString("r")) - if mnttab == nil { - return nil, fmt.Errorf("Failed to open %s", C.MNTTAB) - } - - var out []*Info - var mp C.struct_mnttab - - ret := C.getmntent(mnttab, &mp) - for ret == 0 { - var mountinfo Info - mountinfo.Mountpoint = C.GoString(mp.mnt_mountp) - mountinfo.Source = C.GoString(mp.mnt_special) - mountinfo.Fstype = C.GoString(mp.mnt_fstype) - mountinfo.Opts = C.GoString(mp.mnt_mntopts) - out = append(out, &mountinfo) - ret = C.getmntent(mnttab, &mp) - } - - C.fclose(mnttab) - return out, nil -} diff --git a/vendor/github.com/containers/storage/pkg/mount/mountinfo_unsupported.go b/vendor/github.com/containers/storage/pkg/mount/mountinfo_unsupported.go index 7fbcf1921..6cde1ed77 100644 --- a/vendor/github.com/containers/storage/pkg/mount/mountinfo_unsupported.go +++ b/vendor/github.com/containers/storage/pkg/mount/mountinfo_unsupported.go @@ -1,4 +1,4 @@ -// +build !windows,!linux,!freebsd,!solaris freebsd,!cgo solaris,!cgo +// +build !linux package mount diff --git a/vendor/github.com/containers/storage/pkg/mount/mountinfo_windows.go b/vendor/github.com/containers/storage/pkg/mount/mountinfo_windows.go deleted file mode 100644 index dab8a37ed..000000000 --- a/vendor/github.com/containers/storage/pkg/mount/mountinfo_windows.go +++ /dev/null @@ -1,6 +0,0 @@ -package mount - -func parseMountTable() ([]*Info, error) { - // Do NOT return an error! - return nil, nil -} diff --git a/vendor/github.com/containers/storage/pkg/mount/sharedsubtree_linux.go b/vendor/github.com/containers/storage/pkg/mount/sharedsubtree_linux.go index 8ceec84bc..80922ad5c 100644 --- a/vendor/github.com/containers/storage/pkg/mount/sharedsubtree_linux.go +++ b/vendor/github.com/containers/storage/pkg/mount/sharedsubtree_linux.go @@ -1,69 +1,64 @@ -// +build linux - package mount // MakeShared ensures a mounted filesystem has the SHARED mount option enabled. // See the supported options in flags.go for further reference. func MakeShared(mountPoint string) error { - return ensureMountedAs(mountPoint, "shared") + return ensureMountedAs(mountPoint, SHARED) } // MakeRShared ensures a mounted filesystem has the RSHARED mount option enabled. // See the supported options in flags.go for further reference. func MakeRShared(mountPoint string) error { - return ensureMountedAs(mountPoint, "rshared") + return ensureMountedAs(mountPoint, RSHARED) } // MakePrivate ensures a mounted filesystem has the PRIVATE mount option enabled. // See the supported options in flags.go for further reference. func MakePrivate(mountPoint string) error { - return ensureMountedAs(mountPoint, "private") + return ensureMountedAs(mountPoint, PRIVATE) } // MakeRPrivate ensures a mounted filesystem has the RPRIVATE mount option // enabled. See the supported options in flags.go for further reference. func MakeRPrivate(mountPoint string) error { - return ensureMountedAs(mountPoint, "rprivate") + return ensureMountedAs(mountPoint, RPRIVATE) } // MakeSlave ensures a mounted filesystem has the SLAVE mount option enabled. // See the supported options in flags.go for further reference. func MakeSlave(mountPoint string) error { - return ensureMountedAs(mountPoint, "slave") + return ensureMountedAs(mountPoint, SLAVE) } // MakeRSlave ensures a mounted filesystem has the RSLAVE mount option enabled. // See the supported options in flags.go for further reference. func MakeRSlave(mountPoint string) error { - return ensureMountedAs(mountPoint, "rslave") + return ensureMountedAs(mountPoint, RSLAVE) } // MakeUnbindable ensures a mounted filesystem has the UNBINDABLE mount option // enabled. See the supported options in flags.go for further reference. func MakeUnbindable(mountPoint string) error { - return ensureMountedAs(mountPoint, "unbindable") + return ensureMountedAs(mountPoint, UNBINDABLE) } // MakeRUnbindable ensures a mounted filesystem has the RUNBINDABLE mount // option enabled. See the supported options in flags.go for further reference. func MakeRUnbindable(mountPoint string) error { - return ensureMountedAs(mountPoint, "runbindable") + return ensureMountedAs(mountPoint, RUNBINDABLE) } -func ensureMountedAs(mountPoint, options string) error { - mounted, err := Mounted(mountPoint) +func ensureMountedAs(mnt string, flags int) error { + mounted, err := Mounted(mnt) if err != nil { return err } if !mounted { - if err := Mount(mountPoint, mountPoint, "none", "bind,rw"); err != nil { + if err := mount(mnt, mnt, "none", uintptr(BIND), ""); err != nil { return err } } - if _, err = Mounted(mountPoint); err != nil { - return err - } - return ForceMount("", mountPoint, "none", options) + return mount("", mnt, "none", uintptr(flags), "") } diff --git a/vendor/github.com/containers/storage/pkg/mount/sharedsubtree_solaris.go b/vendor/github.com/containers/storage/pkg/mount/sharedsubtree_solaris.go deleted file mode 100644 index 09f6b03cb..000000000 --- a/vendor/github.com/containers/storage/pkg/mount/sharedsubtree_solaris.go +++ /dev/null @@ -1,58 +0,0 @@ -// +build solaris - -package mount - -// MakeShared ensures a mounted filesystem has the SHARED mount option enabled. -// See the supported options in flags.go for further reference. -func MakeShared(mountPoint string) error { - return ensureMountedAs(mountPoint, "shared") -} - -// MakeRShared ensures a mounted filesystem has the RSHARED mount option enabled. -// See the supported options in flags.go for further reference. -func MakeRShared(mountPoint string) error { - return ensureMountedAs(mountPoint, "rshared") -} - -// MakePrivate ensures a mounted filesystem has the PRIVATE mount option enabled. -// See the supported options in flags.go for further reference. -func MakePrivate(mountPoint string) error { - return ensureMountedAs(mountPoint, "private") -} - -// MakeRPrivate ensures a mounted filesystem has the RPRIVATE mount option -// enabled. See the supported options in flags.go for further reference. -func MakeRPrivate(mountPoint string) error { - return ensureMountedAs(mountPoint, "rprivate") -} - -// MakeSlave ensures a mounted filesystem has the SLAVE mount option enabled. -// See the supported options in flags.go for further reference. -func MakeSlave(mountPoint string) error { - return ensureMountedAs(mountPoint, "slave") -} - -// MakeRSlave ensures a mounted filesystem has the RSLAVE mount option enabled. -// See the supported options in flags.go for further reference. -func MakeRSlave(mountPoint string) error { - return ensureMountedAs(mountPoint, "rslave") -} - -// MakeUnbindable ensures a mounted filesystem has the UNBINDABLE mount option -// enabled. See the supported options in flags.go for further reference. -func MakeUnbindable(mountPoint string) error { - return ensureMountedAs(mountPoint, "unbindable") -} - -// MakeRUnbindable ensures a mounted filesystem has the RUNBINDABLE mount -// option enabled. See the supported options in flags.go for further reference. -func MakeRUnbindable(mountPoint string) error { - return ensureMountedAs(mountPoint, "runbindable") -} - -func ensureMountedAs(mountPoint, options string) error { - // TODO: Solaris does not support bind mounts. - // Evaluate lofs and also look at the relevant - // mount flags to be supported. - return nil -} diff --git a/vendor/github.com/containers/storage/pkg/mount/unmount_unix.go b/vendor/github.com/containers/storage/pkg/mount/unmount_unix.go new file mode 100644 index 000000000..1d1afeee2 --- /dev/null +++ b/vendor/github.com/containers/storage/pkg/mount/unmount_unix.go @@ -0,0 +1,22 @@ +// +build !windows + +package mount + +import "golang.org/x/sys/unix" + +func unmount(target string, flags int) error { + err := unix.Unmount(target, flags) + if err == nil || err == unix.EINVAL { + // Ignore "not mounted" error here. Note the same error + // can be returned if flags are invalid, so this code + // assumes that the flags value is always correct. + return nil + } + + return &mountError{ + op: "umount", + target: target, + flags: uintptr(flags), + err: err, + } +} diff --git a/vendor/github.com/containers/storage/pkg/mount/unmount_unsupported.go b/vendor/github.com/containers/storage/pkg/mount/unmount_unsupported.go new file mode 100644 index 000000000..eebc4ab84 --- /dev/null +++ b/vendor/github.com/containers/storage/pkg/mount/unmount_unsupported.go @@ -0,0 +1,7 @@ +// +build windows + +package mount + +func unmount(target string, flag int) error { + panic("Not implemented") +} diff --git a/vendor/github.com/containers/storage/pkg/system/lstat_unix.go b/vendor/github.com/containers/storage/pkg/system/lstat_unix.go index bd23c4d50..e9d301f09 100644 --- a/vendor/github.com/containers/storage/pkg/system/lstat_unix.go +++ b/vendor/github.com/containers/storage/pkg/system/lstat_unix.go @@ -3,6 +3,7 @@ package system import ( + "os" "syscall" ) @@ -13,7 +14,7 @@ import ( func Lstat(path string) (*StatT, error) { s := &syscall.Stat_t{} if err := syscall.Lstat(path, s); err != nil { - return nil, err + return nil, &os.PathError{"Lstat", path, err} } return fromStatT(s) } diff --git a/vendor/github.com/containers/storage/pkg/system/rm.go b/vendor/github.com/containers/storage/pkg/system/rm.go index b1599d23f..618c1dc75 100644 --- a/vendor/github.com/containers/storage/pkg/system/rm.go +++ b/vendor/github.com/containers/storage/pkg/system/rm.go @@ -34,7 +34,7 @@ func EnsureRemoveAll(dir string) error { for { err := os.RemoveAll(dir) if err == nil { - return err + return nil } pe, ok := err.(*os.PathError) @@ -63,12 +63,8 @@ func EnsureRemoveAll(dir string) error { return err } - if mounted, _ := mount.Mounted(pe.Path); mounted { - if e := mount.Unmount(pe.Path); e != nil { - if mounted, _ := mount.Mounted(pe.Path); mounted { - return errors.Wrapf(e, "error while removing %s", dir) - } - } + if e := mount.Unmount(pe.Path); e != nil { + return errors.Wrapf(e, "error while removing %s", dir) } if exitOnErr[pe.Path] == maxRetry { diff --git a/vendor/github.com/containers/storage/pkg/system/stat_unix.go b/vendor/github.com/containers/storage/pkg/system/stat_unix.go index f9a1b4877..2fac918bf 100644 --- a/vendor/github.com/containers/storage/pkg/system/stat_unix.go +++ b/vendor/github.com/containers/storage/pkg/system/stat_unix.go @@ -3,6 +3,8 @@ package system import ( + "os" + "strconv" "syscall" ) @@ -54,7 +56,7 @@ func (s StatT) Mtim() syscall.Timespec { func Stat(path string) (*StatT, error) { s := &syscall.Stat_t{} if err := syscall.Stat(path, s); err != nil { - return nil, err + return nil, &os.PathError{Op: "Stat", Path: path, Err: err} } return fromStatT(s) } @@ -66,7 +68,7 @@ func Stat(path string) (*StatT, error) { func Fstat(fd int) (*StatT, error) { s := &syscall.Stat_t{} if err := syscall.Fstat(fd, s); err != nil { - return nil, err + return nil, &os.PathError{Op: "Fstat", Path: strconv.Itoa(fd), Err: err} } return fromStatT(s) } diff --git a/vendor/github.com/fsnotify/fsnotify/.editorconfig b/vendor/github.com/fsnotify/fsnotify/.editorconfig index ba49e3c23..fad895851 100644 --- a/vendor/github.com/fsnotify/fsnotify/.editorconfig +++ b/vendor/github.com/fsnotify/fsnotify/.editorconfig @@ -1,5 +1,12 @@ root = true -[*] +[*.go] indent_style = tab indent_size = 4 +insert_final_newline = true + +[*.{yml,yaml}] +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/vendor/github.com/fsnotify/fsnotify/.gitattributes b/vendor/github.com/fsnotify/fsnotify/.gitattributes new file mode 100644 index 000000000..32f1001be --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/.gitattributes @@ -0,0 +1 @@ +go.sum linguist-generated diff --git a/vendor/github.com/fsnotify/fsnotify/.travis.yml b/vendor/github.com/fsnotify/fsnotify/.travis.yml index 981d1bb81..a9c30165c 100644 --- a/vendor/github.com/fsnotify/fsnotify/.travis.yml +++ b/vendor/github.com/fsnotify/fsnotify/.travis.yml @@ -2,29 +2,35 @@ sudo: false language: go go: - - 1.8.x - - 1.9.x - - tip + - "stable" + - "1.11.x" + - "1.10.x" + - "1.9.x" matrix: + include: + - go: "stable" + env: GOLINT=true allow_failures: - go: tip fast_finish: true -before_script: - - go get -u github.com/golang/lint/golint + +before_install: + - if [ ! -z "${GOLINT}" ]; then go get -u golang.org/x/lint/golint; fi script: - - go test -v --race ./... + - go test --race ./... after_script: - test -z "$(gofmt -s -l -w . | tee /dev/stderr)" - - test -z "$(golint ./... | tee /dev/stderr)" + - if [ ! -z "${GOLINT}" ]; then echo running golint; golint --set_exit_status ./...; else echo skipping golint; fi - go vet ./... os: - linux - osx + - windows notifications: email: false diff --git a/vendor/github.com/fsnotify/fsnotify/LICENSE b/vendor/github.com/fsnotify/fsnotify/LICENSE index f21e54080..e180c8fb0 100644 --- a/vendor/github.com/fsnotify/fsnotify/LICENSE +++ b/vendor/github.com/fsnotify/fsnotify/LICENSE @@ -1,5 +1,5 @@ Copyright (c) 2012 The Go Authors. All rights reserved. -Copyright (c) 2012 fsnotify Authors. All rights reserved. +Copyright (c) 2012-2019 fsnotify Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/vendor/github.com/fsnotify/fsnotify/README.md b/vendor/github.com/fsnotify/fsnotify/README.md index 399320741..b2629e522 100644 --- a/vendor/github.com/fsnotify/fsnotify/README.md +++ b/vendor/github.com/fsnotify/fsnotify/README.md @@ -10,16 +10,16 @@ go get -u golang.org/x/sys/... Cross platform: Windows, Linux, BSD and macOS. -|Adapter |OS |Status | -|----------|----------|----------| -|inotify |Linux 2.6.27 or later, Android\*|Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify)| -|kqueue |BSD, macOS, iOS\*|Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify)| -|ReadDirectoryChangesW|Windows|Supported [![Build status](https://ci.appveyor.com/api/projects/status/ivwjubaih4r0udeh/branch/master?svg=true)](https://ci.appveyor.com/project/NathanYoungman/fsnotify/branch/master)| -|FSEvents |macOS |[Planned](https://github.com/fsnotify/fsnotify/issues/11)| -|FEN |Solaris 11 |[In Progress](https://github.com/fsnotify/fsnotify/issues/12)| -|fanotify |Linux 2.6.37+ | | -|USN Journals |Windows |[Maybe](https://github.com/fsnotify/fsnotify/issues/53)| -|Polling |*All* |[Maybe](https://github.com/fsnotify/fsnotify/issues/9)| +| Adapter | OS | Status | +| --------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| inotify | Linux 2.6.27 or later, Android\* | Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify) | +| kqueue | BSD, macOS, iOS\* | Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify) | +| ReadDirectoryChangesW | Windows | Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify) | +| FSEvents | macOS | [Planned](https://github.com/fsnotify/fsnotify/issues/11) | +| FEN | Solaris 11 | [In Progress](https://github.com/fsnotify/fsnotify/issues/12) | +| fanotify | Linux 2.6.37+ | [Planned](https://github.com/fsnotify/fsnotify/issues/114) | +| USN Journals | Windows | [Maybe](https://github.com/fsnotify/fsnotify/issues/53) | +| Polling | *All* | [Maybe](https://github.com/fsnotify/fsnotify/issues/9) | \* Android and iOS are untested. @@ -33,6 +33,53 @@ All [releases](https://github.com/fsnotify/fsnotify/releases) are tagged based o Go 1.6 supports dependencies located in the `vendor/` folder. Unless you are creating a library, it is recommended that you copy fsnotify into `vendor/github.com/fsnotify/fsnotify` within your project, and likewise for `golang.org/x/sys`. +## Usage + +```go +package main + +import ( + "log" + + "github.com/fsnotify/fsnotify" +) + +func main() { + watcher, err := fsnotify.NewWatcher() + if err != nil { + log.Fatal(err) + } + defer watcher.Close() + + done := make(chan bool) + go func() { + for { + select { + case event, ok := <-watcher.Events: + if !ok { + return + } + log.Println("event:", event) + if event.Op&fsnotify.Write == fsnotify.Write { + log.Println("modified file:", event.Name) + } + case err, ok := <-watcher.Errors: + if !ok { + return + } + log.Println("error:", err) + } + } + }() + + err = watcher.Add("/tmp/foo") + if err != nil { + log.Fatal(err) + } + <-done +} +``` + ## Contributing Please refer to [CONTRIBUTING][] before opening an issue or pull request. @@ -65,6 +112,10 @@ There are OS-specific limits as to how many watches can be created: * Linux: /proc/sys/fs/inotify/max_user_watches contains the limit, reaching this limit results in a "no space left on device" error. * BSD / OSX: sysctl variables "kern.maxfiles" and "kern.maxfilesperproc", reaching these limits results in a "too many open files" error. +**Why don't notifications work with NFS filesystems or filesystem in userspace (FUSE)?** + +fsnotify requires support from underlying OS to work. The current NFS protocol does not provide network level support for file notifications. + [#62]: https://github.com/howeyc/fsnotify/issues/62 [#18]: https://github.com/fsnotify/fsnotify/issues/18 [#11]: https://github.com/fsnotify/fsnotify/issues/11 diff --git a/vendor/github.com/fsnotify/fsnotify/fsnotify.go b/vendor/github.com/fsnotify/fsnotify/fsnotify.go index 190bf0de5..89cab046d 100644 --- a/vendor/github.com/fsnotify/fsnotify/fsnotify.go +++ b/vendor/github.com/fsnotify/fsnotify/fsnotify.go @@ -63,4 +63,6 @@ func (e Event) String() string { } // Common errors that can be reported by a watcher -var ErrEventOverflow = errors.New("fsnotify queue overflow") +var ( + ErrEventOverflow = errors.New("fsnotify queue overflow") +) diff --git a/vendor/github.com/fsnotify/fsnotify/go.mod b/vendor/github.com/fsnotify/fsnotify/go.mod new file mode 100644 index 000000000..ff11e13f2 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/go.mod @@ -0,0 +1,5 @@ +module github.com/fsnotify/fsnotify + +go 1.13 + +require golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9 diff --git a/vendor/github.com/fsnotify/fsnotify/go.sum b/vendor/github.com/fsnotify/fsnotify/go.sum new file mode 100644 index 000000000..f60af9855 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/go.sum @@ -0,0 +1,2 @@ +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9 h1:L2auWcuQIvxz9xSEqzESnV/QN/gNRXNApHi3fYwl2w0= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/github.com/fsnotify/fsnotify/inotify_poller.go b/vendor/github.com/fsnotify/fsnotify/inotify_poller.go index cc7db4b22..b33f2b4d4 100644 --- a/vendor/github.com/fsnotify/fsnotify/inotify_poller.go +++ b/vendor/github.com/fsnotify/fsnotify/inotify_poller.go @@ -40,12 +40,12 @@ func newFdPoller(fd int) (*fdPoller, error) { poller.fd = fd // Create epoll fd - poller.epfd, errno = unix.EpollCreate1(0) + poller.epfd, errno = unix.EpollCreate1(unix.EPOLL_CLOEXEC) if poller.epfd == -1 { return nil, errno } // Create pipe; pipe[0] is the read end, pipe[1] the write end. - errno = unix.Pipe2(poller.pipe[:], unix.O_NONBLOCK) + errno = unix.Pipe2(poller.pipe[:], unix.O_NONBLOCK|unix.O_CLOEXEC) if errno != nil { return nil, errno } diff --git a/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go b/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go index 7d8de1451..2306c4620 100644 --- a/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go +++ b/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go @@ -8,4 +8,4 @@ package fsnotify import "golang.org/x/sys/unix" -const openMode = unix.O_NONBLOCK | unix.O_RDONLY +const openMode = unix.O_NONBLOCK | unix.O_RDONLY | unix.O_CLOEXEC diff --git a/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go b/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go index 9139e1716..870c4d6d1 100644 --- a/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go +++ b/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go @@ -9,4 +9,4 @@ package fsnotify import "golang.org/x/sys/unix" // note: this constant is not defined on BSD -const openMode = unix.O_EVTONLY +const openMode = unix.O_EVTONLY | unix.O_CLOEXEC diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/label/label.go b/vendor/github.com/opencontainers/selinux/go-selinux/label/label.go index e178568fd..6e38d3d32 100644 --- a/vendor/github.com/opencontainers/selinux/go-selinux/label/label.go +++ b/vendor/github.com/opencontainers/selinux/go-selinux/label/label.go @@ -1,109 +1,77 @@ -// +build !selinux !linux - package label -// InitLabels returns the process label and file labels to be used within -// the container. A list of options can be passed into this function to alter -// the labels. -func InitLabels(options []string) (string, string, error) { - return "", "", nil -} - -func ROMountLabel() string { - return "" -} - -func GenLabels(options string) (string, string, error) { - return "", "", nil -} +import ( + "github.com/opencontainers/selinux/go-selinux" +) -func FormatMountLabel(src string, mountLabel string) string { - return src -} +// Deprecated: use selinux.ROFileLabel +var ROMountLabel = selinux.ROFileLabel -func SetProcessLabel(processLabel string) error { - return nil -} +// SetProcessLabel takes a process label and tells the kernel to assign the +// label to the next program executed by the current process. +// Deprecated: use selinux.SetExecLabel +var SetProcessLabel = selinux.SetExecLabel -func ProcessLabel() (string, error) { - return "", nil -} +// ProcessLabel returns the process label that the kernel will assign +// to the next program executed by the current process. If "" is returned +// this indicates that the default labeling will happen for the process. +// Deprecated: use selinux.ExecLabel +var ProcessLabel = selinux.ExecLabel -func SetSocketLabel(processLabel string) error { - return nil -} +// SetSocketLabel takes a process label and tells the kernel to assign the +// label to the next socket that gets created +// Deprecated: use selinux.SetSocketLabel +var SetSocketLabel = selinux.SetSocketLabel -func SocketLabel() (string, error) { - return "", nil -} +// SocketLabel retrieves the current default socket label setting +// Deprecated: use selinux.SocketLabel +var SocketLabel = selinux.SocketLabel -func SetKeyLabel(processLabel string) error { - return nil -} +// SetKeyLabel takes a process label and tells the kernel to assign the +// label to the next kernel keyring that gets created +// Deprecated: use selinux.SetKeyLabel +var SetKeyLabel = selinux.SetKeyLabel -func KeyLabel() (string, error) { - return "", nil -} +// KeyLabel retrieves the current default kernel keyring label setting +// Deprecated: use selinux.KeyLabel +var KeyLabel = selinux.KeyLabel -func FileLabel(path string) (string, error) { - return "", nil -} +// FileLabel returns the label for specified path +// Deprecated: use selinux.FileLabel +var FileLabel = selinux.FileLabel -func SetFileLabel(path string, fileLabel string) error { - return nil -} - -func SetFileCreateLabel(fileLabel string) error { - return nil -} - -func Relabel(path string, fileLabel string, shared bool) error { - return nil -} - -func PidLabel(pid int) (string, error) { - return "", nil -} +// PidLabel will return the label of the process running with the specified pid +// Deprecated: use selinux.PidLabel +var PidLabel = selinux.PidLabel +// Init initialises the labeling system func Init() { + selinux.GetEnabled() } -// ClearLabels clears all reserved labels -func ClearLabels() { - return -} +// ClearLabels will clear all reserved labels +// Deprecated: use selinux.ClearLabels +var ClearLabels = selinux.ClearLabels +// ReserveLabel will record the fact that the MCS label has already been used. +// This will prevent InitLabels from using the MCS label in a newly created +// container +// Deprecated: use selinux.ReserveLabel func ReserveLabel(label string) error { + selinux.ReserveLabel(label) return nil } +// ReleaseLabel will remove the reservation of the MCS label. +// This will allow InitLabels to use the MCS label in a newly created +// containers +// Deprecated: use selinux.ReleaseLabel func ReleaseLabel(label string) error { + selinux.ReleaseLabel(label) return nil } // DupSecOpt takes a process label and returns security options that // can be used to set duplicate labels on future container processes -func DupSecOpt(src string) ([]string, error) { - return nil, nil -} - -// DisableSecOpt returns a security opt that can disable labeling -// support for future container processes -func DisableSecOpt() []string { - return nil -} - -// Validate checks that the label does not include unexpected options -func Validate(label string) error { - return nil -} - -// RelabelNeeded checks whether the user requested a relabel -func RelabelNeeded(label string) bool { - return false -} - -// IsShared checks that the label includes a "shared" mark -func IsShared(label string) bool { - return false -} +// Deprecated: use selinux.DupSecOpt +var DupSecOpt = selinux.DupSecOpt diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go b/vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go index 2730fcf4a..903829958 100644 --- a/vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go +++ b/vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/opencontainers/selinux/go-selinux" + "github.com/pkg/errors" ) // Valid Label Options @@ -21,7 +22,7 @@ var validOptions = map[string]bool{ "level": true, } -var ErrIncompatibleLabel = fmt.Errorf("Bad SELinux option z and Z can not be used together") +var ErrIncompatibleLabel = errors.New("Bad SELinux option z and Z can not be used together") // InitLabels returns the process label and file labels to be used within // the container. A list of options can be passed into this function to alter @@ -35,7 +36,7 @@ func InitLabels(options []string) (plabel string, mlabel string, Err error) { if processLabel != "" { defer func() { if Err != nil { - ReleaseLabel(mountLabel) + selinux.ReleaseLabel(mountLabel) } }() pcon, err := selinux.NewContext(processLabel) @@ -52,11 +53,11 @@ func InitLabels(options []string) (plabel string, mlabel string, Err error) { return "", mountLabel, nil } if i := strings.Index(opt, ":"); i == -1 { - return "", "", fmt.Errorf("Bad label option %q, valid options 'disable' or \n'user, role, level, type, filetype' followed by ':' and a value", opt) + return "", "", errors.Errorf("Bad label option %q, valid options 'disable' or \n'user, role, level, type, filetype' followed by ':' and a value", opt) } con := strings.SplitN(opt, ":", 2) if !validOptions[con[0]] { - return "", "", fmt.Errorf("Bad label option %q, valid options 'disable, user, role, level, type, filetype'", con[0]) + return "", "", errors.Errorf("Bad label option %q, valid options 'disable, user, role, level, type, filetype'", con[0]) } if con[0] == "filetype" { @@ -67,19 +68,16 @@ func InitLabels(options []string) (plabel string, mlabel string, Err error) { mcon[con[0]] = con[1] } } - _ = ReleaseLabel(processLabel) + selinux.ReleaseLabel(processLabel) processLabel = pcon.Get() mountLabel = mcon.Get() - _ = ReserveLabel(processLabel) + selinux.ReserveLabel(processLabel) } return processLabel, mountLabel, nil } -func ROMountLabel() string { - return selinux.ROFileLabel() -} - -// DEPRECATED: The GenLabels function is only to be used during the transition to the official API. +// Deprecated: The GenLabels function is only to be used during the transition +// to the official API. Use InitLabels(strings.Fields(options)) instead. func GenLabels(options string) (string, string, error) { return InitLabels(strings.Fields(options)) } @@ -102,71 +100,27 @@ func FormatMountLabel(src, mountLabel string) string { return src } -// SetProcessLabel takes a process label and tells the kernel to assign the -// label to the next program executed by the current process. -func SetProcessLabel(processLabel string) error { - return selinux.SetExecLabel(processLabel) -} - -// SetSocketLabel takes a process label and tells the kernel to assign the -// label to the next socket that gets created -func SetSocketLabel(processLabel string) error { - return selinux.SetSocketLabel(processLabel) -} - -// SocketLabel retrieves the current default socket label setting -func SocketLabel() (string, error) { - return selinux.SocketLabel() -} - -// SetKeyLabel takes a process label and tells the kernel to assign the -// label to the next kernel keyring that gets created -func SetKeyLabel(processLabel string) error { - return selinux.SetKeyLabel(processLabel) -} - -// KeyLabel retrieves the current default kernel keyring label setting -func KeyLabel() (string, error) { - return selinux.KeyLabel() -} - -// ProcessLabel returns the process label that the kernel will assign -// to the next program executed by the current process. If "" is returned -// this indicates that the default labeling will happen for the process. -func ProcessLabel() (string, error) { - return selinux.ExecLabel() -} - -// FileLabel returns the label for specified path -func FileLabel(path string) (string, error) { - return selinux.FileLabel(path) -} - // SetFileLabel modifies the "path" label to the specified file label func SetFileLabel(path string, fileLabel string) error { - if selinux.GetEnabled() && fileLabel != "" { - return selinux.SetFileLabel(path, fileLabel) + if !selinux.GetEnabled() || fileLabel == "" { + return nil } - return nil + return selinux.SetFileLabel(path, fileLabel) } // SetFileCreateLabel tells the kernel the label for all files to be created func SetFileCreateLabel(fileLabel string) error { - if selinux.GetEnabled() { - return selinux.SetFSCreateLabel(fileLabel) + if !selinux.GetEnabled() { + return nil } - return nil + return selinux.SetFSCreateLabel(fileLabel) } // Relabel changes the label of path to the filelabel string. // It changes the MCS label to s0 if shared is true. // This will allow all containers to share the content. func Relabel(path string, fileLabel string, shared bool) error { - if !selinux.GetEnabled() { - return nil - } - - if fileLabel == "" { + if !selinux.GetEnabled() || fileLabel == "" { return nil } @@ -211,7 +165,7 @@ func Relabel(path string, fileLabel string, shared bool) error { path = strings.TrimSuffix(path, "/") } if exclude_paths[path] { - return fmt.Errorf("SELinux relabeling of %s is not allowed", path) + return errors.Errorf("SELinux relabeling of %s is not allowed", path) } if shared { @@ -229,48 +183,10 @@ func Relabel(path string, fileLabel string, shared bool) error { return nil } -// PidLabel will return the label of the process running with the specified pid -func PidLabel(pid int) (string, error) { - return selinux.PidLabel(pid) -} - -// Init initialises the labeling system -func Init() { - selinux.GetEnabled() -} - -// ClearLabels will clear all reserved labels -func ClearLabels() { - selinux.ClearLabels() -} - -// ReserveLabel will record the fact that the MCS label has already been used. -// This will prevent InitLabels from using the MCS label in a newly created -// container -func ReserveLabel(label string) error { - selinux.ReserveLabel(label) - return nil -} - -// ReleaseLabel will remove the reservation of the MCS label. -// This will allow InitLabels to use the MCS label in a newly created -// containers -func ReleaseLabel(label string) error { - selinux.ReleaseLabel(label) - return nil -} - -// DupSecOpt takes a process label and returns security options that -// can be used to set duplicate labels on future container processes -func DupSecOpt(src string) ([]string, error) { - return selinux.DupSecOpt(src) -} - // DisableSecOpt returns a security opt that can disable labeling // support for future container processes -func DisableSecOpt() []string { - return selinux.DisableSecOpt() -} +// Deprecated: use selinux.DisableSecOpt +var DisableSecOpt = selinux.DisableSecOpt // Validate checks that the label does not include unexpected options func Validate(label string) error { diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/label/label_stub.go b/vendor/github.com/opencontainers/selinux/go-selinux/label/label_stub.go new file mode 100644 index 000000000..cda59d671 --- /dev/null +++ b/vendor/github.com/opencontainers/selinux/go-selinux/label/label_stub.go @@ -0,0 +1,54 @@ +// +build !selinux !linux + +package label + +// InitLabels returns the process label and file labels to be used within +// the container. A list of options can be passed into this function to alter +// the labels. +func InitLabels(options []string) (string, string, error) { + return "", "", nil +} + +// Deprecated: The GenLabels function is only to be used during the transition +// to the official API. Use InitLabels(strings.Fields(options)) instead. +func GenLabels(options string) (string, string, error) { + return "", "", nil +} + +func FormatMountLabel(src string, mountLabel string) string { + return src +} + +func SetFileLabel(path string, fileLabel string) error { + return nil +} + +func SetFileCreateLabel(fileLabel string) error { + return nil +} + +func Relabel(path string, fileLabel string, shared bool) error { + return nil +} + +// DisableSecOpt returns a security opt that can disable labeling +// support for future container processes +func DisableSecOpt() []string { + // TODO the selinux.DisableSecOpt stub returns []string{"disable"} instead of "nil" + return nil +} + +// Validate checks that the label does not include unexpected options +func Validate(label string) error { + return nil +} + +// RelabelNeeded checks whether the user requested a relabel +func RelabelNeeded(label string) bool { + return false +} + +// IsShared checks that the label includes a "shared" mark +func IsShared(label string) bool { + return false +} diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go index c51ddfda2..599bdb6e2 100644 --- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go +++ b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go @@ -17,8 +17,8 @@ import ( "strconv" "strings" "sync" - "syscall" + "github.com/opencontainers/selinux/pkg/pwalk" "github.com/pkg/errors" "golang.org/x/sys/unix" ) @@ -37,7 +37,6 @@ const ( selinuxTypeTag = "SELINUXTYPE" selinuxTag = "SELINUX" xattrNameSelinux = "security.selinux" - stRdOnly = 0x01 ) type selinuxState struct { @@ -103,13 +102,13 @@ func SetDisabled() { } func verifySELinuxfsMount(mnt string) bool { - var buf syscall.Statfs_t + var buf unix.Statfs_t for { - err := syscall.Statfs(mnt, &buf) + err := unix.Statfs(mnt, &buf) if err == nil { break } - if err == syscall.EAGAIN { + if err == unix.EAGAIN { continue } return false @@ -118,7 +117,7 @@ func verifySELinuxfsMount(mnt string) bool { if uint32(buf.Type) != uint32(unix.SELINUX_MAGIC) { return false } - if (buf.Flags & stRdOnly) != 0 { + if (buf.Flags & unix.ST_RDONLY) != 0 { return false } @@ -251,10 +250,10 @@ func isProcHandle(fh *os.File) error { var buf unix.Statfs_t err := unix.Fstatfs(int(fh.Fd()), &buf) if err != nil { - return fmt.Errorf("statfs(%q) failed: %v", fh.Name(), err) + return errors.Wrapf(err, "statfs(%q) failed", fh.Name()) } if buf.Type != unix.PROC_SUPER_MAGIC { - return fmt.Errorf("file %q is not on procfs", fh.Name()) + return errors.Errorf("file %q is not on procfs", fh.Name()) } return nil @@ -282,12 +281,29 @@ func readCon(fpath string) (string, error) { return strings.Trim(retval, "\x00"), nil } +// ClassIndex returns the int index for an object class in the loaded policy, or -1 and an error +func ClassIndex(class string) (int, error) { + permpath := fmt.Sprintf("class/%s/index", class) + indexpath := filepath.Join(getSelinuxMountPoint(), permpath) + + indexB, err := ioutil.ReadFile(indexpath) + if err != nil { + return -1, err + } + index, err := strconv.Atoi(string(indexB)) + if err != nil { + return -1, err + } + + return index, nil +} + // SetFileLabel sets the SELinux label for this path or returns an error. func SetFileLabel(fpath string, label string) error { if fpath == "" { return ErrEmptyPath } - if err := lsetxattr(fpath, xattrNameSelinux, []byte(label), 0); err != nil { + if err := unix.Lsetxattr(fpath, xattrNameSelinux, []byte(label), 0); err != nil { return errors.Wrapf(err, "failed to set file label on %s", fpath) } return nil @@ -390,7 +406,7 @@ func attrPath(attr string) string { return path.Join(threadSelfPrefix, attr) } - return path.Join("/proc/self/task/", strconv.Itoa(syscall.Gettid()), "/attr/", attr) + return path.Join("/proc/self/task/", strconv.Itoa(unix.Gettid()), "/attr/", attr) } func readAttr(attr string) (string, error) { @@ -410,6 +426,18 @@ func CanonicalizeContext(val string) (string, error) { return readWriteCon(filepath.Join(getSelinuxMountPoint(), "context"), val) } +/* +ComputeCreateContext requests the type transition from source to target for class from the kernel. +*/ +func ComputeCreateContext(source string, target string, class string) (string, error) { + classidx, err := ClassIndex(class) + if err != nil { + return "", err + } + + return readWriteCon(filepath.Join(getSelinuxMountPoint(), "create"), fmt.Sprintf("%s %s %d", source, target, classidx)) +} + func readWriteCon(fpath string, val string) (string, error) { if fpath == "" { return "", ErrEmptyPath @@ -461,17 +489,17 @@ func SocketLabel() (string, error) { // PeerLabel retrieves the label of the client on the other side of a socket func PeerLabel(fd uintptr) (string, error) { - return unix.GetsockoptString(int(fd), syscall.SOL_SOCKET, syscall.SO_PEERSEC) + return unix.GetsockoptString(int(fd), unix.SOL_SOCKET, unix.SO_PEERSEC) } // SetKeyLabel takes a process label and tells the kernel to assign the // label to the next kernel keyring that gets created func SetKeyLabel(label string) error { err := writeCon("/proc/self/attr/keycreate", label) - if os.IsNotExist(err) { + if os.IsNotExist(errors.Cause(err)) { return nil } - if label == "" && os.IsPermission(err) { + if label == "" && os.IsPermission(errors.Cause(err)) { return nil } return err @@ -772,14 +800,14 @@ func badPrefix(fpath string) error { badPrefixes := []string{"/usr"} for _, prefix := range badPrefixes { if strings.HasPrefix(fpath, prefix) { - return fmt.Errorf("relabeling content in %s is not allowed", prefix) + return errors.Errorf("relabeling content in %s is not allowed", prefix) } } return nil } -// Chcon changes the `fpath` file object to the SELinux label `label`. -// If `fpath` is a directory and `recurse`` is true, Chcon will walk the +// Chcon changes the fpath file object to the SELinux label label. +// If fpath is a directory and recurse is true, Chcon will walk the // directory tree setting the label. func Chcon(fpath string, label string, recurse bool) error { if fpath == "" { @@ -791,19 +819,19 @@ func Chcon(fpath string, label string, recurse bool) error { if err := badPrefix(fpath); err != nil { return err } - callback := func(p string, info os.FileInfo, err error) error { + + if !recurse { + return SetFileLabel(fpath, label) + } + + return pwalk.Walk(fpath, func(p string, info os.FileInfo, err error) error { e := SetFileLabel(p, label) - if os.IsNotExist(e) { + // Walk a file tree can race with removal, so ignore ENOENT + if os.IsNotExist(errors.Cause(e)) { return nil } return e - } - - if recurse { - return filepath.Walk(fpath, callback) - } - - return SetFileLabel(fpath, label) + }) } // DupSecOpt takes an SELinux process label and returns security options that diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go index 0c2e1cd38..f349513d9 100644 --- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go +++ b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go @@ -1,4 +1,4 @@ -// +build !selinux +// +build !selinux !linux package selinux @@ -35,6 +35,11 @@ func GetEnabled() bool { return false } +// ClassIndex returns the int index for an object class in the loaded policy, or -1 and an error +func ClassIndex(class string) (int, error) { + return -1, nil +} + // SetFileLabel sets the SELinux label for this path or returns an error. func SetFileLabel(fpath string, label string) error { return nil @@ -89,6 +94,13 @@ func CanonicalizeContext(val string) (string, error) { } /* +ComputeCreateContext requests the type transition from source to target for class from the kernel. +*/ +func ComputeCreateContext(source string, target string, class string) (string, error) { + return "", nil +} + +/* SetExecLabel sets the SELinux label that the kernel will use for any programs that are executed by the current process thread, or an error. */ diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go b/vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go index 4e711a9f8..de5c80ef3 100644 --- a/vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go +++ b/vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go @@ -12,8 +12,8 @@ func lgetxattr(path string, attr string) ([]byte, error) { // Start with a 128 length byte array dest := make([]byte, 128) sz, errno := unix.Lgetxattr(path, attr, dest) - if errno == unix.ERANGE { - // Buffer too small, get the real size first + for errno == unix.ERANGE { + // Buffer too small, use zero-sized buffer to get the actual size sz, errno = unix.Lgetxattr(path, attr, []byte{}) if errno != nil { return nil, errno @@ -28,7 +28,3 @@ func lgetxattr(path string, attr string) ([]byte, error) { return dest[:sz], nil } - -func lsetxattr(path string, attr string, data []byte, flags int) error { - return unix.Lsetxattr(path, attr, data, flags) -} diff --git a/vendor/github.com/opencontainers/selinux/pkg/pwalk/README.md b/vendor/github.com/opencontainers/selinux/pkg/pwalk/README.md new file mode 100644 index 000000000..16c4dfd3e --- /dev/null +++ b/vendor/github.com/opencontainers/selinux/pkg/pwalk/README.md @@ -0,0 +1,42 @@ +## pwalk: parallel implementation of filepath.Walk + +This is a wrapper for [filepath.Walk](https://pkg.go.dev/path/filepath?tab=doc#Walk) +which may speed it up by calling multiple callback functions (WalkFunc) in parallel, +utilizing goroutines. + +By default, it utilizes 2\*runtime.NumCPU() goroutines for callbacks. +This can be changed by using WalkN function which has the additional +parameter, specifying the number of goroutines (concurrency). + +### Caveats + +Please note the following limitations of this code: + +* Unlike filepath.Walk, the order of calls is non-deterministic; + +* Only primitive error handling is supported: + + * filepath.SkipDir is not supported; + + * no errors are ever passed to WalkFunc; + + * once any error is returned from any WalkFunc instance, no more new calls + to WalkFunc are made, and the error is returned to the caller of Walk; + + * if more than one walkFunc instance will return an error, only one + of such errors will be propagated and returned by Walk, others + will be silently discarded. + +### Documentation + +For the official documentation, see +https://pkg.go.dev/github.com/opencontainers/selinux/pkg/pwalk?tab=doc + +### Benchmarks + +For a WalkFunc that consists solely of the return statement, this +implementation is about 10% slower than the standard library's +filepath.Walk. + +Otherwise (if a WalkFunc is doing something) this is usually faster, +except when the WalkN(..., 1) is used. diff --git a/vendor/github.com/opencontainers/selinux/pkg/pwalk/pwalk.go b/vendor/github.com/opencontainers/selinux/pkg/pwalk/pwalk.go new file mode 100644 index 000000000..2ee0d0150 --- /dev/null +++ b/vendor/github.com/opencontainers/selinux/pkg/pwalk/pwalk.go @@ -0,0 +1,99 @@ +package pwalk + +import ( + "os" + "path/filepath" + "runtime" + "sync" + + "github.com/pkg/errors" +) + +type WalkFunc = filepath.WalkFunc + +// Walk is a wrapper for filepath.Walk which can call multiple walkFn +// in parallel, allowing to handle each item concurrently. A maximum of +// twice the runtime.NumCPU() walkFn will be called at any one time. +// If you want to change the maximum, use WalkN instead. +// +// The order of calls is non-deterministic. +// +// Note that this implementation only supports primitive error handling: +// +// * no errors are ever passed to WalkFn +// +// * once a walkFn returns any error, all further processing stops +// and the error is returned to the caller of Walk; +// +// * filepath.SkipDir is not supported; +// +// * if more than one walkFn instance will return an error, only one +// of such errors will be propagated and returned by Walk, others +// will be silently discarded. +// +func Walk(root string, walkFn WalkFunc) error { + return WalkN(root, walkFn, runtime.NumCPU()*2) +} + +// WalkN is a wrapper for filepath.Walk which can call multiple walkFn +// in parallel, allowing to handle each item concurrently. A maximum of +// num walkFn will be called at any one time. +func WalkN(root string, walkFn WalkFunc, num int) error { + // make sure limit is sensible + if num < 1 { + return errors.Errorf("walk(%q): num must be > 0", root) + } + + files := make(chan *walkArgs, 2*num) + errCh := make(chan error, 1) // get the first error, ignore others + + // Start walking a tree asap + var err error + go func() { + err = filepath.Walk(root, func(p string, info os.FileInfo, err error) error { + if err != nil { + close(files) + return err + } + // add a file to the queue unless a callback sent an error + select { + case e := <-errCh: + close(files) + return e + default: + files <- &walkArgs{path: p, info: &info} + return nil + } + }) + if err == nil { + close(files) + } + }() + + var wg sync.WaitGroup + wg.Add(num) + for i := 0; i < num; i++ { + go func() { + for file := range files { + if e := walkFn(file.path, *file.info, nil); e != nil { + select { + case errCh <- e: // sent ok + default: // buffer full + } + } + } + wg.Done() + }() + } + + wg.Wait() + + return err +} + +// walkArgs holds the arguments that were passed to the Walk or WalkLimit +// functions. +type walkArgs struct { + path string + info *os.FileInfo +} diff --git a/vendor/modules.txt b/vendor/modules.txt index b6f075400..1b9352334 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -62,7 +62,7 @@ github.com/containernetworking/plugins/pkg/ns github.com/containernetworking/plugins/pkg/utils/hwaddr github.com/containernetworking/plugins/plugins/ipam/host-local/backend github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator -# github.com/containers/buildah v1.14.2 +# github.com/containers/buildah v1.14.3-0.20200313154200-d26f437b2a46 github.com/containers/buildah github.com/containers/buildah/bind github.com/containers/buildah/chroot @@ -80,7 +80,7 @@ github.com/containers/buildah/pkg/secrets github.com/containers/buildah/pkg/supplemented github.com/containers/buildah/pkg/umask github.com/containers/buildah/util -# github.com/containers/common v0.4.2 +# github.com/containers/common v0.5.0 github.com/containers/common/pkg/capabilities github.com/containers/common/pkg/config github.com/containers/common/pkg/unshare @@ -145,7 +145,7 @@ github.com/containers/psgo/internal/dev github.com/containers/psgo/internal/host github.com/containers/psgo/internal/proc github.com/containers/psgo/internal/process -# github.com/containers/storage v1.16.2 +# github.com/containers/storage v1.16.3 github.com/containers/storage github.com/containers/storage/drivers github.com/containers/storage/drivers/aufs @@ -265,7 +265,7 @@ github.com/docker/spdystream github.com/docker/spdystream/spdy # github.com/etcd-io/bbolt v1.3.3 github.com/etcd-io/bbolt -# github.com/fsnotify/fsnotify v1.4.7 +# github.com/fsnotify/fsnotify v1.4.9 github.com/fsnotify/fsnotify # github.com/fsouza/go-dockerclient v1.6.3 github.com/fsouza/go-dockerclient @@ -407,9 +407,10 @@ 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.3.3 +# github.com/opencontainers/selinux v1.4.0 github.com/opencontainers/selinux/go-selinux github.com/opencontainers/selinux/go-selinux/label +github.com/opencontainers/selinux/pkg/pwalk # github.com/openshift/api v0.0.0-20200106203948-7ab22a2c8316 github.com/openshift/api/config/v1 # github.com/openshift/imagebuilder v1.1.1 @@ -633,9 +634,9 @@ gopkg.in/square/go-jose.v2/json gopkg.in/tomb.v1 # gopkg.in/yaml.v2 v2.2.8 gopkg.in/yaml.v2 -# k8s.io/api v0.17.3 +# k8s.io/api v0.17.4 k8s.io/api/core/v1 -# k8s.io/apimachinery v0.17.3 +# k8s.io/apimachinery v0.17.4 k8s.io/apimachinery/pkg/api/errors k8s.io/apimachinery/pkg/api/resource k8s.io/apimachinery/pkg/apis/meta/v1 |