From 2e85b81d12a214150cff2a32625fa5f355b052fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Nov 2025 15:13:36 +0000 Subject: [PATCH] Bump github.com/containerd/containerd/v2 from 2.1.2 to 2.1.5 Bumps [github.com/containerd/containerd/v2](https://github.com/containerd/containerd) from 2.1.2 to 2.1.5. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v2.1.2...v2.1.5) --- updated-dependencies: - dependency-name: github.com/containerd/containerd/v2 dependency-version: 2.1.5 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 +- .../containerd/v2/core/mount/mount_linux.go | 114 ++++++++++++------ .../containerd/v2/core/mount/temp.go | 20 +++ .../containerd/v2/pkg/sys/unshare_linux.go | 8 +- .../containerd/v2/version/version.go | 2 +- vendor/modules.txt | 2 +- 7 files changed, 108 insertions(+), 44 deletions(-) diff --git a/go.mod b/go.mod index bd14688948..4950e0b849 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/containerd/cgroups/v3 v3.0.5 github.com/containerd/console v1.0.4 github.com/containerd/containerd/api v1.9.0 - github.com/containerd/containerd/v2 v2.1.2 + github.com/containerd/containerd/v2 v2.1.5 github.com/containerd/errdefs v1.0.0 github.com/containerd/errdefs/pkg v0.3.0 github.com/containerd/go-runc v1.1.0 diff --git a/go.sum b/go.sum index 53ceeffb17..c54d418070 100644 --- a/go.sum +++ b/go.sum @@ -445,8 +445,8 @@ github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/containerd/api v1.9.0 h1:HZ/licowTRazus+wt9fM6r/9BQO7S0vD5lMcWspGIg0= github.com/containerd/containerd/api v1.9.0/go.mod h1:GhghKFmTR3hNtyznBoQ0EMWr9ju5AqHjcZPsSpTKutI= -github.com/containerd/containerd/v2 v2.1.2 h1:4ZQxB+FVYmwXZgpBcKfar6ieppm3KC5C6FRKvtJ6DRU= -github.com/containerd/containerd/v2 v2.1.2/go.mod h1:8C5QV9djwsYDNhxfTCFjWtTBZrqjditQ4/ghHSYjnHM= +github.com/containerd/containerd/v2 v2.1.5 h1:pWSmPxUszaLZKQPvOx27iD4iH+aM6o0BoN9+hg77cro= +github.com/containerd/containerd/v2 v2.1.5/go.mod h1:8C5QV9djwsYDNhxfTCFjWtTBZrqjditQ4/ghHSYjnHM= github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= diff --git a/vendor/github.com/containerd/containerd/v2/core/mount/mount_linux.go b/vendor/github.com/containerd/containerd/v2/core/mount/mount_linux.go index 86686f15c2..e0775ca4c6 100644 --- a/vendor/github.com/containerd/containerd/v2/core/mount/mount_linux.go +++ b/vendor/github.com/containerd/containerd/v2/core/mount/mount_linux.go @@ -24,7 +24,6 @@ import ( "path" "path/filepath" "runtime" - "strconv" "strings" "github.com/containerd/log" @@ -55,10 +54,7 @@ func init() { // // It returns: // 1. New options that include new "lowedir=..." mount option. -// 2. "Clean up" function -- it should be called as a defer one before -// checking for error, because if do the second and avoid calling "clean up", -// you're going to have "dirty" setup -- there's no guarantee that those -// temporary mount points for lowedirs will be cleaned properly. +// 2. "Clean up" function -- it should be called only if no error is returned. // 3. Error -- nil if everything's fine, otherwise an error. func prepareIDMappedOverlay(usernsFd int, options []string) ([]string, func(), error) { lowerIdx, lowerDirs := findOverlayLowerdirs(options) @@ -66,12 +62,7 @@ func prepareIDMappedOverlay(usernsFd int, options []string) ([]string, func(), e return options, nil, fmt.Errorf("failed to parse overlay lowerdir's from given options") } - tempRemountsLocation, err := os.MkdirTemp(tempMountLocation, "ovl-idmapped") - if err != nil { - return options, nil, fmt.Errorf("failed to create temporary overlay lowerdir mount location: %w", err) - } - - tmpLowerdirs, idMapCleanUp, err := doPrepareIDMappedOverlay(tempRemountsLocation, lowerDirs, usernsFd) + tmpLowerdirs, idMapCleanUp, err := doPrepareIDMappedOverlay(tempMountLocation, lowerDirs, usernsFd) if err != nil { return options, idMapCleanUp, fmt.Errorf("failed to create idmapped mount: %w", err) } @@ -115,11 +106,11 @@ func (m *Mount) mount(target string) (err error) { userNsCleanUp func() ) options, userNsCleanUp, err = prepareIDMappedOverlay(int(usernsFd.Fd()), options) - defer userNsCleanUp() - if err != nil { return fmt.Errorf("failed to prepare idmapped overlay: %w", err) } + defer userNsCleanUp() + // To not meet concurrency issues while using the same lowedirs // for different containers, replace them by temporary directories, if optionsSize(options) >= pagesize-512 { @@ -249,39 +240,86 @@ func getUnprivilegedMountFlags(path string) (int, error) { return flags, nil } -func doPrepareIDMappedOverlay(tempRemountsLocation string, lowerDirs []string, usernsFd int) ([]string, func(), error) { - tmpLowerDirs := make([]string, 0, len(lowerDirs)) - - cleanUp := func() { - for _, lowerDir := range tmpLowerDirs { - if err := unix.Unmount(lowerDir, 0); err != nil { - log.L.WithError(err).Warnf("failed to unmount temp lowerdir %s", lowerDir) - continue - } - // Using os.Remove() so if it's not empty, we don't delete files in the - // rootfs. - if err := os.Remove(lowerDir); err != nil { - log.L.WithError(err).Warnf("failed to remove temporary overlay lowerdir") - } - } +func doPrepareIDMappedOverlay(tmpDir string, lowerDirs []string, usernsFd int) (_ []string, _ func(), retErr error) { + commonDir, err := getCommonDirectory(lowerDirs) + if err != nil { + return nil, nil, fmt.Errorf("failed to determine common parent: %w", err) + } - // This dir should be empty now. Otherwise, we don't do anything. + tempRemountsLocation, err := os.MkdirTemp(tmpDir, "ovl-idmapped") + if err != nil { + return nil, nil, fmt.Errorf("failed to create temporary overlay lowerdir mount location: %w", err) + } + cleanDir := func() { if err := os.Remove(tempRemountsLocation); err != nil { - log.L.WithError(err).Infof("failed to remove temporary overlay dir") + log.L.WithError(err).Infof("failed to remove idmapped directory") } } - for i, lowerDir := range lowerDirs { - tmpLowerDir := filepath.Join(tempRemountsLocation, strconv.Itoa(i)) - tmpLowerDirs = append(tmpLowerDirs, tmpLowerDir) + defer func() { + if retErr != nil { + cleanDir() + } + }() - if err := os.MkdirAll(tmpLowerDir, 0700); err != nil { - return nil, cleanUp, fmt.Errorf("failed to create temporary dir: %w", err) + // IDMapMount the directory containing all the layers + if err := IDMapMountWithAttrs(commonDir, tempRemountsLocation, usernsFd, unix.MOUNT_ATTR_RDONLY, 0); err != nil { + return nil, nil, err + } + cleanMount := func() { + // Use the Unmount helper that does retries because there can be easily an open fd + // to the idmapped directory and when containerd forks to create a userns fd (maybe + // for another container), it will make the mount busy for a few ms. + err := Unmount(tempRemountsLocation, 0) + if err != nil { + log.L.WithError(err).Warnf("failed to unmount idmapped directory %s: %v", tempRemountsLocation, err) } - if err := IDMapMountWithAttrs(lowerDir, tmpLowerDir, usernsFd, unix.MOUNT_ATTR_RDONLY, 0); err != nil { - return nil, cleanUp, err + } + defer func() { + if retErr != nil { + cleanMount() } + }() + + // Build new lower dir paths through the idmapped directory + tmpLowerDirs := buildIDMappedPaths(lowerDirs, commonDir, tempRemountsLocation) + + cleanup := func() { + cleanMount() + cleanDir() + } + return tmpLowerDirs, cleanup, nil +} + +// getCommonDirectory finds the common directory among the lowerDirs passed in. +// "/" and "." are considered invalid common directories and are treated as error +func getCommonDirectory(lowerDirs []string) (string, error) { + commonPrefix := longestCommonPrefix(lowerDirs) + if commonPrefix == "" { + return "", fmt.Errorf("no common prefix found") + } + + // Ensure the common prefix ends at a directory boundary + commonPrefix = path.Dir(commonPrefix) + + if commonPrefix == "." || commonPrefix == "/" { + return "", fmt.Errorf("invalid common directory: %s", commonPrefix) } - return tmpLowerDirs, cleanUp, nil + + return commonPrefix, nil +} + +// buildIDMappedPaths constructs new lower directory paths through an idmapped mount of the commonDir. +// It takes the original lowerDirs, the commonDir of those dirs, and rewrites the paths +// to go through the idMappedDir directory to achieve idmapped lowerdirs ready for overlayfs +func buildIDMappedPaths(lowerDirs []string, commonDir, idMappedDir string) []string { + tmpLowerDirs := make([]string, 0, len(lowerDirs)) + + for _, lowerDir := range lowerDirs { + relativePath := strings.TrimPrefix(lowerDir, commonDir) + tmpLowerDirs = append(tmpLowerDirs, filepath.Join(idMappedDir, relativePath)) + } + + return tmpLowerDirs } // parseMountOptions takes fstab style mount options and parses them for diff --git a/vendor/github.com/containerd/containerd/v2/core/mount/temp.go b/vendor/github.com/containerd/containerd/v2/core/mount/temp.go index ba37ba5f3d..39a7aaaddf 100644 --- a/vendor/github.com/containerd/containerd/v2/core/mount/temp.go +++ b/vendor/github.com/containerd/containerd/v2/core/mount/temp.go @@ -20,6 +20,7 @@ import ( "context" "fmt" "os" + "strings" "github.com/containerd/log" ) @@ -104,6 +105,25 @@ func RemoveVolatileOption(mounts []Mount) []Mount { return mounts } +// RemoveIDMapOption copies and removes the uidmap/gidmap options on any of the mounts using it. +func RemoveIDMapOption(mounts []Mount) []Mount { + var out []Mount + for i, m := range mounts { + for j, opt := range m.Options { + if strings.HasPrefix(opt, "uidmap") || strings.HasPrefix(opt, "gidmap") { + if out == nil { + out = copyMounts(mounts) + } + out[i].Options = append(out[i].Options[:j], out[i].Options[j+1:]...) + } + } + } + if out != nil { + return out + } + return mounts +} + // copyMounts creates a copy of the original slice to allow for modification and not altering the original func copyMounts(in []Mount) []Mount { out := make([]Mount, len(in)) diff --git a/vendor/github.com/containerd/containerd/v2/pkg/sys/unshare_linux.go b/vendor/github.com/containerd/containerd/v2/pkg/sys/unshare_linux.go index 85af4fe3b8..02f2a123b8 100644 --- a/vendor/github.com/containerd/containerd/v2/pkg/sys/unshare_linux.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/sys/unshare_linux.go @@ -35,6 +35,10 @@ func UnshareAfterEnterUserns(uidMap, gidMap string, unshareFlags uintptr, f func return fmt.Errorf("unshare flags should not include user namespace") } + if !SupportsPidFD() { + return fmt.Errorf("kernel doesn't support pidfd") + } + uidMaps, err := parseIDMapping(uidMap) if err != nil { return err @@ -65,7 +69,7 @@ func UnshareAfterEnterUserns(uidMap, gidMap string, unshareFlags uintptr, f func return fmt.Errorf("failed to start noop process for unshare: %w", err) } - if pidfd == -1 || !SupportsPidFD() { + if pidfd == -1 { proc.Kill() proc.Wait() return fmt.Errorf("kernel doesn't support CLONE_PIDFD") @@ -86,6 +90,8 @@ func UnshareAfterEnterUserns(uidMap, gidMap string, unshareFlags uintptr, f func pidfd = dupPidfd } + defer unix.Close(pidfd) + defer func() { derr := unix.PidfdSendSignal(pidfd, unix.SIGKILL, nil, 0) if derr != nil { diff --git a/vendor/github.com/containerd/containerd/v2/version/version.go b/vendor/github.com/containerd/containerd/v2/version/version.go index 758bd631fe..be9fd1b044 100644 --- a/vendor/github.com/containerd/containerd/v2/version/version.go +++ b/vendor/github.com/containerd/containerd/v2/version/version.go @@ -24,7 +24,7 @@ var ( Package = "github.com/containerd/containerd/v2" // Version holds the complete version number. Filled in at linking time. - Version = "2.1.2+unknown" + Version = "2.1.5+unknown" // Revision is filled with the VCS (e.g. git) revision being used to build // the program at linking time. diff --git a/vendor/modules.txt b/vendor/modules.txt index f57930032a..33a89b55c7 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -58,7 +58,7 @@ github.com/containerd/containerd/api/runtime/task/v3 github.com/containerd/containerd/api/services/ttrpc/events/v1 github.com/containerd/containerd/api/types github.com/containerd/containerd/api/types/task -# github.com/containerd/containerd/v2 v2.1.2 +# github.com/containerd/containerd/v2 v2.1.5 ## explicit; go 1.23.0 github.com/containerd/containerd/v2/core/events github.com/containerd/containerd/v2/core/mount