Skip to content

Commit 41d74ae

Browse files
committed
cri: Fix userns with Dockerfile VOLUME mounts that need copy
If a Dockerfile is using a `VOLUME` directive and the directory exists in the rootfs, like in this example: FROM docker.io/library/alpine:latest VOLUME [ "/run" ] The alpine container image already contains a "/run" directory. This will force the code in WithVolumes() to copy its content to the new volume created for the VOLUME directive. This copies the content as well as the ownership. However, as we perform the mounts from the host POV without being inside a userns, the idmap option will just shift the IDs in ways that will screw up the ownerships when copied. We should only use the idmap option when running the container inside a userns, so the ownerships are fine (the userns will do a shift and the idmap another, to make it all seem as if there was no UID/GID shift in the first place). This PR does just that, remove the idmap option from mounts so we copy the files without any ID transformations. It's simpler and easier to reason about if we just don't mount with the idmap option here: all files are copied just fine without ID transformations and ID transformation is applied via the idmap option at mount time when running the pod. Also, note that `VOLUME` directives that refer to directories that don't exist on the rootfs work fine (`VOLUME [ "/rata" ]` for example), as there is no copy done in that case so the permissions weren't changed. Signed-off-by: Rodrigo Campos <[email protected]> (cherry picked from commit 41953f7) Signed-off-by: Rodrigo Campos <[email protected]>
1 parent c8c4575 commit 41d74ae

File tree

2 files changed

+25
-0
lines changed

2 files changed

+25
-0
lines changed

core/mount/temp.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"context"
2121
"fmt"
2222
"os"
23+
"strings"
2324

2425
"github.com/containerd/log"
2526
)
@@ -104,6 +105,25 @@ func RemoveVolatileOption(mounts []Mount) []Mount {
104105
return mounts
105106
}
106107

108+
// RemoveIDMapOption copies and removes the uidmap/gidmap options on any of the mounts using it.
109+
func RemoveIDMapOption(mounts []Mount) []Mount {
110+
var out []Mount
111+
for i, m := range mounts {
112+
for j, opt := range m.Options {
113+
if strings.HasPrefix(opt, "uidmap") || strings.HasPrefix(opt, "gidmap") {
114+
if out == nil {
115+
out = copyMounts(mounts)
116+
}
117+
out[i].Options = append(out[i].Options[:j], out[i].Options[j+1:]...)
118+
}
119+
}
120+
}
121+
if out != nil {
122+
return out
123+
}
124+
return mounts
125+
}
126+
107127
// copyMounts creates a copy of the original slice to allow for modification and not altering the original
108128
func copyMounts(in []Mount) []Mount {
109129
out := make([]Mount, len(in))

internal/cri/opts/container.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ func WithVolumes(volumeMounts map[string]string, platform imagespec.Platform) co
7676
}
7777
mounts = mount.RemoveVolatileOption(mounts)
7878

79+
// Always copy files without UID/GID transformations.
80+
// The ID transformations are only needed when running inside a userns, that is not
81+
// the case here.
82+
mounts = mount.RemoveIDMapOption(mounts)
83+
7984
root, err := os.MkdirTemp("", "ctd-volume")
8085
if err != nil {
8186
return err

0 commit comments

Comments
 (0)