diff --git a/go.mod b/go.mod index 1a10c87db5b..a49d7da8d2b 100644 --- a/go.mod +++ b/go.mod @@ -64,7 +64,7 @@ require ( github.com/vbauerster/mpb/v8 v8.12.0 github.com/vishvananda/netlink v1.3.1 go.podman.io/buildah v1.42.1-0.20260501153811-377cf64e213b - go.podman.io/common v0.67.2-0.20260506114327-35c76125c5b5 + go.podman.io/common v0.67.2-0.20260506125647-380549a2bd33 go.podman.io/image/v5 v5.39.3-0.20260506114327-35c76125c5b5 go.podman.io/storage v1.62.1-0.20260506114327-35c76125c5b5 golang.org/x/crypto v0.50.0 @@ -188,3 +188,5 @@ require ( gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect tags.cncf.io/container-device-interface/specs-go v1.1.0 // indirect ) + +replace go.podman.io/storage => github.com/giuseppe/container-libs/storage v0.0.0-20260506143911-d06e746b86ab diff --git a/go.sum b/go.sum index a734e7616a8..5542cfbb85d 100644 --- a/go.sum +++ b/go.sum @@ -123,6 +123,8 @@ github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx5 github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= github.com/fsouza/go-dockerclient v1.13.1 h1:HbkJO8UPUhuQ1wHIgX+ho7AUucBmjtOfzSWYUgmWL/8= github.com/fsouza/go-dockerclient v1.13.1/go.mod h1:0gx0SIFGV1F+79sM9p5K+UCc8enYKA8DBp7BlwlixpM= +github.com/giuseppe/container-libs/storage v0.0.0-20260506143911-d06e746b86ab h1:jHVCL3DkGr6EsBe86f4BR18FTc3XHhxyK7vdHrtYJ7k= +github.com/giuseppe/container-libs/storage v0.0.0-20260506143911-d06e746b86ab/go.mod h1:eZIqDigffFi9NlPezLvUVw/nsUIruaui436E5E4GmXs= github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs= github.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M= @@ -431,12 +433,10 @@ go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09 go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= go.podman.io/buildah v1.42.1-0.20260501153811-377cf64e213b h1:i8ntFzITajbJA3ojnA0ZdpbC+I+ccweZvZaGIhQb4i8= go.podman.io/buildah v1.42.1-0.20260501153811-377cf64e213b/go.mod h1:hPvgsjBU09C+15fKoIZJvKvNaxR+c0QvMg/n4NgBS7A= -go.podman.io/common v0.67.2-0.20260506114327-35c76125c5b5 h1:rjsl4OiSteuD58lb76F9f0e3VOapd7cKdpL6sc+77PI= -go.podman.io/common v0.67.2-0.20260506114327-35c76125c5b5/go.mod h1:TYI+ocF4gfL8QCBo5GqOSUAOA3QnVgkjjg/nQZRG3o0= +go.podman.io/common v0.67.2-0.20260506125647-380549a2bd33 h1:fn6ct2NUsMqMC6J+p2HKjikC8cm8THTzdkYlavT+0ww= +go.podman.io/common v0.67.2-0.20260506125647-380549a2bd33/go.mod h1:TYI+ocF4gfL8QCBo5GqOSUAOA3QnVgkjjg/nQZRG3o0= go.podman.io/image/v5 v5.39.3-0.20260506114327-35c76125c5b5 h1:xkEpeE5/HO2MryNXLk443DJhXayWGJC7mku9CjRqHrg= go.podman.io/image/v5 v5.39.3-0.20260506114327-35c76125c5b5/go.mod h1:D+09OPzsrFuzeKqsJEaaxtItkSd12+eZyOdFyuJF8TY= -go.podman.io/storage v1.62.1-0.20260506114327-35c76125c5b5 h1:yPIjkKjl5VTjz66zg8pStN2ysvd2OFMIzCvsO3CJYn0= -go.podman.io/storage v1.62.1-0.20260506114327-35c76125c5b5/go.mod h1:eZIqDigffFi9NlPezLvUVw/nsUIruaui436E5E4GmXs= go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= diff --git a/vendor/go.podman.io/storage/containers.go b/vendor/go.podman.io/storage/containers.go index ebdd19c5991..5319df3759b 100644 --- a/vendor/go.podman.io/storage/containers.go +++ b/vendor/go.podman.io/storage/containers.go @@ -76,9 +76,12 @@ type Container struct { // is set before using it. Created time.Time `json:"created"` - // UIDMap and GIDMap are used for setting up a container's root - // filesystem for use inside of a user namespace where UID mapping is - // being used. + // UIDMap and GIDMap are the caller's requested UID/GID mapping for this + // container's user namespace. They always reflect what the caller + // asked for, regardless of whether the mapping was applied at layer + // creation time (chown) or is deferred to mount time (idmapped mounts). + // At mount time, these maps are passed to the graph driver so that the + // container sees the expected file ownership. UIDMap []idtools.IDMap `json:"uidmap,omitempty"` GIDMap []idtools.IDMap `json:"gidmap,omitempty"` diff --git a/vendor/go.podman.io/storage/drivers/driver.go b/vendor/go.podman.io/storage/drivers/driver.go index 1ca50b6462d..4eab783aa9f 100644 --- a/vendor/go.podman.io/storage/drivers/driver.go +++ b/vendor/go.podman.io/storage/drivers/driver.go @@ -95,9 +95,6 @@ type MountOpts struct { // Volatile specifies whether the container storage can be optimized // at the cost of not syncing all the dirty files in memory. Volatile bool - - // DisableShifting forces the driver to not do any ID shifting at runtime. - DisableShifting bool } // ApplyDiffOpts contains optional arguments for ApplyDiff methods. diff --git a/vendor/go.podman.io/storage/drivers/overlay/overlay.go b/vendor/go.podman.io/storage/drivers/overlay/overlay.go index b50319707b0..ec1d1630090 100644 --- a/vendor/go.podman.io/storage/drivers/overlay/overlay.go +++ b/vendor/go.podman.io/storage/drivers/overlay/overlay.go @@ -1504,7 +1504,7 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO readWrite := !inAdditionalStore - if !d.SupportsShifting(options.UidMaps, options.GidMaps) || options.DisableShifting { + if !d.SupportsShifting(options.UidMaps, options.GidMaps) { disableShifting = true } diff --git a/vendor/go.podman.io/storage/layers.go b/vendor/go.podman.io/storage/layers.go index d176e456c10..a1040981df3 100644 --- a/vendor/go.podman.io/storage/layers.go +++ b/vendor/go.podman.io/storage/layers.go @@ -167,8 +167,11 @@ type Layer struct { // Flags is arbitrary data about the layer. Flags map[string]any `json:"flags,omitempty"` - // UIDMap and GIDMap are used for setting up a layer's contents - // for use inside of a user namespace where UID mapping is being used. + // UIDMap and GIDMap are the on-disk ID mappings for this layer: the + // chown mapping that was applied to the layer's files at creation + // time. When the driver supports shifting (idmapped mounts), no + // chown occurs and these fields are empty. The caller's requested + // mapping is applied at mount time instead (see Container.UIDMap/GIDMap). UIDMap []idtools.IDMap `json:"uidmap,omitempty"` GIDMap []idtools.IDMap `json:"gidmap,omitempty"` @@ -1596,8 +1599,8 @@ func (r *layerStore) create(id string, parentLayer *Layer, names []string, mount UIDs: templateUIDs, GIDs: templateGIDs, Flags: newMapFrom(moreOptions.Flags), - UIDMap: copySlicePreferringNil(moreOptions.UIDMap), - GIDMap: copySlicePreferringNil(moreOptions.GIDMap), + UIDMap: copySlicePreferringNil(moreOptions.IDMappingOptions.UIDMap), + GIDMap: copySlicePreferringNil(moreOptions.IDMappingOptions.GIDMap), BigDataNames: []string{}, location: r.pickStoreLocation(moreOptions.Volatile, writeable), } @@ -1641,7 +1644,10 @@ func (r *layerStore) create(id string, parentLayer *Layer, names []string, mount } } - idMappings := idtools.NewIDMappingsFromMaps(moreOptions.UIDMap, moreOptions.GIDMap) + idMappings := idtools.NewIDMappingsFromMaps(moreOptions.IDMappingOptions.UIDMap, moreOptions.IDMappingOptions.GIDMap) + if moreOptions.IDMappingOptions.HostUIDMapping && moreOptions.IDMappingOptions.HostGIDMapping { + idMappings = &idtools.IDMappings{} + } opts := drivers.CreateOpts{ MountLabel: mountLabel, StorageOpt: options, @@ -2597,7 +2603,7 @@ func (r *layerStore) stageWithUnlockedStore(sl *maybeStagedLayerExtraction, pare result, err := applyDiff(layerOptions, sl.diff, f, func(payload io.Reader) (int64, error) { cleanup, stagedLayer, size, err := sl.staging.StartStagingDiffToApply(parent, drivers.ApplyDiffOpts{ Diff: payload, - Mappings: idtools.NewIDMappingsFromMaps(layerOptions.UIDMap, layerOptions.GIDMap), + Mappings: idtools.NewIDMappingsFromMaps(layerOptions.IDMappingOptions.UIDMap, layerOptions.IDMappingOptions.GIDMap), // MountLabel is not supported for the unlocked extraction, see the comment in (*store).PutLayer() MountLabel: "", }) diff --git a/vendor/go.podman.io/storage/store.go b/vendor/go.podman.io/storage/store.go index 36ffbafe49f..ef087957bd7 100644 --- a/vendor/go.podman.io/storage/store.go +++ b/vendor/go.podman.io/storage/store.go @@ -633,13 +633,39 @@ type AutoUserNsOptions = types.AutoUserNsOptions type IDMappingOptions = types.IDMappingOptions +// LayerIDMappingOptions are the on-disk ID mappings for a layer. +// +// Unlike the caller-facing IDMappingOptions (which expresses what mapping +// the caller wants), these record how files are actually stored. The two +// may differ: when the graph driver supports shifting, no chown +// occurs so HostUIDMapping/HostGIDMapping are true and UIDMap/GIDMap +// are empty, even though the caller requested a non-trivial mapping. +// The caller's requested mapping is still honored at mount time via +// the Container's UIDMap/GIDMap. +type LayerIDMappingOptions struct { + // HostUIDMapping is true when files in this layer are stored with host + // UIDs. + HostUIDMapping bool + // HostGIDMapping is true when files in this layer are stored with host + // GIDs. See HostUIDMapping for details. + HostGIDMapping bool + // UIDMap is the on-disk UID mapping: it records the chown that was + // applied to the layer's files at creation time. Empty when + // HostUIDMapping is true. + UIDMap []idtools.IDMap + // GIDMap is the on-disk GID mapping: it records the chown that was + // applied to the layer's files at creation time. Empty when + // HostGIDMapping is true. + GIDMap []idtools.IDMap +} + // LayerOptions is used for passing options to a Store's CreateLayer() and PutLayer() methods. type LayerOptions struct { // IDMappingOptions specifies the type of ID mapping which should be // used for this layer. If nothing is specified, the layer will // inherit settings from its parent layer or, if it has no parent // layer, the Store object. - types.IDMappingOptions + IDMappingOptions LayerIDMappingOptions // TemplateLayer is the ID of a layer whose contents will be used to // initialize this layer. If set, it should be a child of the layer // which we want to use as the parent of the new layer. @@ -708,10 +734,18 @@ type ImageBigDataOption struct { // ContainerOptions is used for passing options to a Store's CreateContainer() method. type ContainerOptions struct { - // IDMappingOptions specifies the type of ID mapping which should be - // used for this container's layer. If nothing is specified, the - // container's layer will inherit settings from the image's top layer - // or, if it is not being created based on an image, the Store object. + // IDMappingOptions specifies the caller's desired ID mapping for the + // container's user namespace. + // + // These express what the caller wants, not what ends up on disk. + // The store records them in the Container and uses them at mount + // time. How the layer's files are stored depends on whether the + // driver supports shifting: if it does, no chown occurs and the + // mapping is applied at mount time; otherwise files are chowned at + // layer creation time. + // + // If nothing is specified, mappings are inherited from the image's top + // layer or, if no image, from the Store's defaults. types.IDMappingOptions LabelOpts []string // Flags is a set of named flags and their values to store with the container. @@ -1518,14 +1552,14 @@ func populateLayerOptions(s *store, rlstore rwLayerStore, rlstores []roLayerStor options.BigData = slices.Clone(lOptions.BigData) options.Flags = copyMapPreferringNil(lOptions.Flags) } - if options.HostUIDMapping { - options.UIDMap = nil + if options.IDMappingOptions.HostUIDMapping { + options.IDMappingOptions.UIDMap = nil } - if options.HostGIDMapping { - options.GIDMap = nil + if options.IDMappingOptions.HostGIDMapping { + options.IDMappingOptions.GIDMap = nil } - uidMap := options.UIDMap - gidMap := options.GIDMap + uidMap := options.IDMappingOptions.UIDMap + gidMap := options.IDMappingOptions.GIDMap if parent != "" { var err error parentLayer, unlock, err = getParentLayer(rlstore, rlstores, parent) @@ -1546,26 +1580,26 @@ func populateLayerOptions(s *store, rlstore rwLayerStore, rlstores []roLayerStor return nil, nil, unlock, ErrParentIsContainer } } - if !options.HostUIDMapping && len(options.UIDMap) == 0 { + if !options.IDMappingOptions.HostUIDMapping && len(options.IDMappingOptions.UIDMap) == 0 { uidMap = parentLayer.UIDMap } - if !options.HostGIDMapping && len(options.GIDMap) == 0 { + if !options.IDMappingOptions.HostGIDMapping && len(options.IDMappingOptions.GIDMap) == 0 { gidMap = parentLayer.GIDMap } } else { - if !options.HostUIDMapping && len(options.UIDMap) == 0 { + if !options.IDMappingOptions.HostUIDMapping && len(options.IDMappingOptions.UIDMap) == 0 { uidMap = s.uidMap } - if !options.HostGIDMapping && len(options.GIDMap) == 0 { + if !options.IDMappingOptions.HostGIDMapping && len(options.IDMappingOptions.GIDMap) == 0 { gidMap = s.gidMap } } if s.canUseShifting(uidMap, gidMap) { - options.IDMappingOptions = types.IDMappingOptions{HostUIDMapping: true, HostGIDMapping: true, UIDMap: nil, GIDMap: nil} + options.IDMappingOptions = LayerIDMappingOptions{HostUIDMapping: true, HostGIDMapping: true, UIDMap: nil, GIDMap: nil} } else { - options.IDMappingOptions = types.IDMappingOptions{ - HostUIDMapping: options.HostUIDMapping, - HostGIDMapping: options.HostGIDMapping, + options.IDMappingOptions = LayerIDMappingOptions{ + HostUIDMapping: options.IDMappingOptions.HostUIDMapping, + HostGIDMapping: options.IDMappingOptions.HostGIDMapping, UIDMap: copySlicePreferringNil(uidMap), GIDMap: copySlicePreferringNil(gidMap), } @@ -1856,14 +1890,14 @@ func (s *store) imageTopLayerForMapping(image *Image, ristore roImageStore, rlst // mappings, and register it as an alternate top layer in the image. var layerOptions LayerOptions if s.canUseShifting(options.UIDMap, options.GIDMap) { - layerOptions.IDMappingOptions = types.IDMappingOptions{ + layerOptions.IDMappingOptions = LayerIDMappingOptions{ HostUIDMapping: true, HostGIDMapping: true, UIDMap: nil, GIDMap: nil, } } else { - layerOptions.IDMappingOptions = types.IDMappingOptions{ + layerOptions.IDMappingOptions = LayerIDMappingOptions{ HostUIDMapping: options.HostUIDMapping, HostGIDMapping: options.HostGIDMapping, UIDMap: copySlicePreferringNil(options.UIDMap), @@ -2008,20 +2042,12 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat // But in transient store mode, all container layers are volatile. Volatile: options.Volatile || s.transientStore, } - if s.canUseShifting(uidMap, gidMap) { - layerOptions.IDMappingOptions = types.IDMappingOptions{ - HostUIDMapping: true, - HostGIDMapping: true, - UIDMap: nil, - GIDMap: nil, - } - } else { - layerOptions.IDMappingOptions = types.IDMappingOptions{ - HostUIDMapping: idMappingsOptions.HostUIDMapping, - HostGIDMapping: idMappingsOptions.HostGIDMapping, - UIDMap: copySlicePreferringNil(uidMap), - GIDMap: copySlicePreferringNil(gidMap), - } + useHostMapping := idMappingsOptions.HostUIDMapping || s.canUseShifting(uidMap, gidMap) + layerOptions.IDMappingOptions = LayerIDMappingOptions{ + HostUIDMapping: useHostMapping, + HostGIDMapping: useHostMapping, + UIDMap: copySlicePreferringNil(uidMap), + GIDMap: copySlicePreferringNil(gidMap), } if options.Flags == nil { options.Flags = make(map[string]any) @@ -3074,10 +3100,6 @@ func (s *store) Mount(id, mountLabel string) (string, error) { if err != nil { return "", err } - if options.UidMaps != nil || options.GidMaps != nil { - options.DisableShifting = !s.canUseShifting(options.UidMaps, options.GidMaps) - } - if err := rlstore.startWriting(); err != nil { return "", err } diff --git a/vendor/go.podman.io/storage/types/idmappings.go b/vendor/go.podman.io/storage/types/idmappings.go index e53ec229c31..4ed73b88dda 100644 --- a/vendor/go.podman.io/storage/types/idmappings.go +++ b/vendor/go.podman.io/storage/types/idmappings.go @@ -28,21 +28,34 @@ type AutoUserNsOptions struct { AdditionalGIDMappings []idtools.IDMap } -// IDMappingOptions are used for specifying how ID mapping should be set up for -// a layer or container. +// IDMappingOptions specifies the caller's desired UID/GID mapping for a +// layer or container. +// +// These options express what the caller wants, the mapping that the +// container's user namespace should use. They do not describe what is +// stored on disk. Depending on the graph driver, the store may apply +// the mapping at layer creation time (by chowning files) or defer it to +// mount time (using idmapped mounts or fuse-overlayfs options), but +// that distinction is transparent to the caller. +// +// The resolution order for the effective UID/GID maps is: +// 1. If HostUIDMapping/HostGIDMapping is true, no mapping is used (the +// corresponding UIDMap/GIDMap is ignored and treated as empty). +// 2. If UIDMap/GIDMap contain at least one entry, those mappings are used. +// 3. Otherwise, if the layer has a parent, the parent's mappings are inherited. +// 4. Otherwise, the Store-level default mappings are used. type IDMappingOptions struct { - // UIDMap and GIDMap are used for setting up a layer's root filesystem - // for use inside of a user namespace where ID mapping is being used. - // If HostUIDMapping/HostGIDMapping is true, no mapping of the - // respective type will be used. Otherwise, if UIDMap and/or GIDMap - // contain at least one mapping, one or both will be used. By default, - // if neither of those conditions apply, if the layer has a parent - // layer, the parent layer's mapping will be used, and if it does not - // have a parent layer, the mapping which was passed to the Store - // object when it was initialized will be used. + // HostUIDMapping indicates that no UID mapping should be applied. + // When true, UIDMap is ignored and files are accessed with host UIDs. HostUIDMapping bool + // HostGIDMapping indicates that no GID mapping should be applied. + // When true, GIDMap is ignored and files are accessed with host GIDs. HostGIDMapping bool - UIDMap []idtools.IDMap + // UIDMap defines the UID mappings for the user namespace. + // Only used when HostUIDMapping is false. + UIDMap []idtools.IDMap + // GIDMap defines the GID mappings for the user namespace. + // Only used when HostGIDMapping is false. GIDMap []idtools.IDMap AutoUserNs bool AutoUserNsOpts AutoUserNsOptions diff --git a/vendor/go.podman.io/storage/userns.go b/vendor/go.podman.io/storage/userns.go index 86ca8b59384..38047dba2f0 100644 --- a/vendor/go.podman.io/storage/userns.go +++ b/vendor/go.podman.io/storage/userns.go @@ -187,7 +187,7 @@ outer: } layerOptions := &LayerOptions{ - IDMappingOptions: types.IDMappingOptions{ + IDMappingOptions: LayerIDMappingOptions{ HostUIDMapping: true, HostGIDMapping: true, UIDMap: nil, diff --git a/vendor/modules.txt b/vendor/modules.txt index 6b64c576a5e..ef405184bf9 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -735,7 +735,7 @@ go.podman.io/buildah/pkg/sshagent go.podman.io/buildah/pkg/util go.podman.io/buildah/pkg/volumes go.podman.io/buildah/util -# go.podman.io/common v0.67.2-0.20260506114327-35c76125c5b5 +# go.podman.io/common v0.67.2-0.20260506125647-380549a2bd33 ## explicit; go 1.25.6 go.podman.io/common/internal go.podman.io/common/libimage @@ -878,7 +878,7 @@ go.podman.io/image/v5/transports go.podman.io/image/v5/transports/alltransports go.podman.io/image/v5/types go.podman.io/image/v5/version -# go.podman.io/storage v1.62.1-0.20260506114327-35c76125c5b5 +# go.podman.io/storage v1.62.1-0.20260506114327-35c76125c5b5 => github.com/giuseppe/container-libs/storage v0.0.0-20260506143911-d06e746b86ab ## explicit; go 1.25.0 go.podman.io/storage go.podman.io/storage/drivers @@ -1182,3 +1182,4 @@ tags.cncf.io/container-device-interface/pkg/parser # tags.cncf.io/container-device-interface/specs-go v1.1.0 ## explicit; go 1.19 tags.cncf.io/container-device-interface/specs-go +# go.podman.io/storage => github.com/giuseppe/container-libs/storage v0.0.0-20260506143911-d06e746b86ab