Skip to content

Commit 762ec4b

Browse files
committed
plugin: fix mounting /etc/hosts when running in UserNS
Fix `error mounting "/etc/hosts" to rootfs at "/etc/hosts": mount /etc/hosts:/etc/hosts (via /proc/self/fd/6), flags: 0x5021: operation not permitted`. This error was introduced in 7d08d84 (`dockerd-rootless.sh: set rootlesskit --state-dir=DIR`) that changed the filesystem of the state dir from /tmp to /run (in a typical setup). Fix issue 47248 Signed-off-by: Akihiro Suda <[email protected]>
1 parent 979f03f commit 762ec4b

1 file changed

Lines changed: 36 additions & 0 deletions

File tree

plugin/v2/plugin_linux.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
2+
//go:build go1.19
3+
14
package v2 // import "github.com/docker/docker/plugin/v2"
25

36
import (
@@ -6,7 +9,10 @@ import (
69
"runtime"
710
"strings"
811

12+
"github.com/containerd/containerd/pkg/userns"
913
"github.com/docker/docker/api/types"
14+
"github.com/docker/docker/internal/rootless/mountopts"
15+
"github.com/docker/docker/internal/sliceutil"
1016
"github.com/docker/docker/oci"
1117
specs "github.com/opencontainers/runtime-spec/specs-go"
1218
"github.com/pkg/errors"
@@ -136,5 +142,35 @@ func (p *Plugin) InitSpec(execRoot string) (*specs.Spec, error) {
136142
p.modifyRuntimeSpec(&s)
137143
}
138144

145+
// Rootless mode requires modifying the mount flags
146+
// https://github.com/moby/moby/issues/47248#issuecomment-1927776700
147+
// https://github.com/moby/moby/pull/47558
148+
if userns.RunningInUserNS() {
149+
for i := range s.Mounts {
150+
m := &s.Mounts[i]
151+
for _, o := range m.Options {
152+
switch o {
153+
case "bind", "rbind":
154+
if _, err := os.Lstat(m.Source); err != nil {
155+
if errors.Is(err, os.ErrNotExist) {
156+
continue
157+
}
158+
return nil, err
159+
}
160+
// UnprivilegedMountFlags gets the set of mount flags that are set on the mount that contains the given
161+
// path and are locked by CL_UNPRIVILEGED. This is necessary to ensure that
162+
// bind-mounting "with options" will not fail with user namespaces, due to
163+
// kernel restrictions that require user namespace mounts to preserve
164+
// CL_UNPRIVILEGED locked flags.
165+
unpriv, err := mountopts.UnprivilegedMountFlags(m.Source)
166+
if err != nil {
167+
return nil, errors.Wrapf(err, "failed to get unprivileged mount flags for %+v", m)
168+
}
169+
m.Options = sliceutil.Dedup(append(m.Options, unpriv...))
170+
}
171+
}
172+
}
173+
}
174+
139175
return &s, nil
140176
}

0 commit comments

Comments
 (0)