diff options
author | Giuseppe Scrivano <gscrivan@redhat.com> | 2019-02-25 16:41:16 +0100 |
---|---|---|
committer | Giuseppe Scrivano <gscrivan@redhat.com> | 2019-02-25 18:56:09 +0100 |
commit | 0f5ae3c5af60f95b73c709b51db50d39ae1b3693 (patch) | |
tree | 2896a55965cd5db977e0ddfbeed883ddc722b803 | |
parent | 553ac800c87b31de0bb22ae0c6f2e2e24bdcfe73 (diff) | |
download | podman-0f5ae3c5af60f95b73c709b51db50d39ae1b3693.tar.gz podman-0f5ae3c5af60f95b73c709b51db50d39ae1b3693.tar.bz2 podman-0f5ae3c5af60f95b73c709b51db50d39ae1b3693.zip |
podman: fix ro bind mounts if no* opts are on the source
This is a workaround for the runc issue:
https://github.com/opencontainers/runc/issues/1247
If the source of a bind mount has any of nosuid, noexec or nodev, be
sure to propagate them to the bind mount so that when runc tries to
remount using MS_RDONLY, these options are also used.
Closes: https://github.com/containers/libpod/issues/2312
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
-rw-r--r-- | pkg/spec/spec.go | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index 76b8963ff..28a636fa6 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -3,10 +3,12 @@ package createconfig import ( "os" "path" + "path/filepath" "strings" "github.com/containers/libpod/pkg/rootless" "github.com/containers/storage/pkg/mount" + pmount "github.com/containers/storage/pkg/mount" "github.com/docker/docker/daemon/caps" "github.com/docker/go-units" "github.com/opencontainers/runc/libcontainer/user" @@ -392,9 +394,65 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint configSpec.Linux.Resources = &spec.LinuxResources{} } + // Make sure that the bind mounts keep options like nosuid, noexec, nodev. + mounts, err := pmount.GetMounts() + if err != nil { + return nil, err + } + for i := range configSpec.Mounts { + m := &configSpec.Mounts[i] + isBind := false + for _, o := range m.Options { + if o == "bind" || o == "rbind" { + isBind = true + break + } + } + if !isBind { + continue + } + mount, err := findMount(m.Source, mounts) + if err != nil { + return nil, err + } + if mount == nil { + continue + } + next_option: + for _, o := range strings.Split(mount.Opts, ",") { + if o == "nosuid" || o == "noexec" || o == "nodev" { + for _, e := range m.Options { + if e == o { + continue next_option + } + } + m.Options = append(m.Options, o) + } + } + } + return configSpec, nil } +func findMount(target string, mounts []*pmount.Info) (*pmount.Info, error) { + var err error + target, err = filepath.Abs(target) + if err != nil { + return nil, errors.Wrapf(err, "cannot resolve %s", target) + } + var bestSoFar *pmount.Info + for _, i := range mounts { + if bestSoFar != nil && len(bestSoFar.Mountpoint) > len(i.Mountpoint) { + // Won't be better than what we have already found + continue + } + if strings.HasPrefix(target, i.Mountpoint) { + bestSoFar = i + } + } + return bestSoFar, nil +} + func blockAccessToKernelFilesystems(config *CreateConfig, g *generate.Generator) { if config.PidMode.IsHost() && rootless.IsRootless() { return |