Browse Source

Merge pull request #47558 from AkihiroSuda/fix-47248

plugin: fix mounting /etc/hosts when running in UserNS
Bjorn Neergaard 1 year ago
parent
commit
959c2ee6cf
1 changed files with 36 additions and 0 deletions
  1. 36 0
      plugin/v2/plugin_linux.go

+ 36 - 0
plugin/v2/plugin_linux.go

@@ -1,3 +1,6 @@
+// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
+//go:build go1.19
+
 package v2 // import "github.com/docker/docker/plugin/v2"
 package v2 // import "github.com/docker/docker/plugin/v2"
 
 
 import (
 import (
@@ -6,7 +9,10 @@ import (
 	"runtime"
 	"runtime"
 	"strings"
 	"strings"
 
 
+	"github.com/containerd/containerd/pkg/userns"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/internal/rootless/mountopts"
+	"github.com/docker/docker/internal/sliceutil"
 	"github.com/docker/docker/oci"
 	"github.com/docker/docker/oci"
 	specs "github.com/opencontainers/runtime-spec/specs-go"
 	specs "github.com/opencontainers/runtime-spec/specs-go"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
@@ -136,5 +142,35 @@ func (p *Plugin) InitSpec(execRoot string) (*specs.Spec, error) {
 		p.modifyRuntimeSpec(&s)
 		p.modifyRuntimeSpec(&s)
 	}
 	}
 
 
+	// Rootless mode requires modifying the mount flags
+	// https://github.com/moby/moby/issues/47248#issuecomment-1927776700
+	// https://github.com/moby/moby/pull/47558
+	if userns.RunningInUserNS() {
+		for i := range s.Mounts {
+			m := &s.Mounts[i]
+			for _, o := range m.Options {
+				switch o {
+				case "bind", "rbind":
+					if _, err := os.Lstat(m.Source); err != nil {
+						if errors.Is(err, os.ErrNotExist) {
+							continue
+						}
+						return nil, err
+					}
+					// UnprivilegedMountFlags gets the set of mount flags that are set on the mount that contains the given
+					// path and are locked by CL_UNPRIVILEGED. This is necessary to ensure that
+					// bind-mounting "with options" will not fail with user namespaces, due to
+					// kernel restrictions that require user namespace mounts to preserve
+					// CL_UNPRIVILEGED locked flags.
+					unpriv, err := mountopts.UnprivilegedMountFlags(m.Source)
+					if err != nil {
+						return nil, errors.Wrapf(err, "failed to get unprivileged mount flags for %+v", m)
+					}
+					m.Options = sliceutil.Dedup(append(m.Options, unpriv...))
+				}
+			}
+		}
+	}
+
 	return &s, nil
 	return &s, nil
 }
 }