Skip to content

Commit 8a030d6

Browse files
committed
Update overlay snapshotter to support multiple uid/gid mappings
Signed-off-by: Henry Wang <[email protected]>
1 parent 168ec21 commit 8a030d6

File tree

2 files changed

+314
-192
lines changed

2 files changed

+314
-192
lines changed

plugins/snapshots/overlay/overlay.go

Lines changed: 21 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/containerd/containerd/v2/core/mount"
3030
"github.com/containerd/containerd/v2/core/snapshots"
3131
"github.com/containerd/containerd/v2/core/snapshots/storage"
32+
"github.com/containerd/containerd/v2/internal/userns"
3233
"github.com/containerd/containerd/v2/plugins/snapshots/overlay/overlayutils"
3334
"github.com/containerd/continuity/fs"
3435
"github.com/containerd/log"
@@ -424,41 +425,6 @@ func (o *snapshotter) getCleanupDirectories(ctx context.Context) ([]string, erro
424425
return cleanup, nil
425426
}
426427

427-
func validateIDMapping(mapping string) error {
428-
var (
429-
hostID int
430-
ctrID int
431-
length int
432-
)
433-
434-
if _, err := fmt.Sscanf(mapping, "%d:%d:%d", &ctrID, &hostID, &length); err != nil {
435-
return err
436-
}
437-
// Almost impossible, but snapshots.WithLabels doesn't check it
438-
if ctrID < 0 || hostID < 0 || length < 0 {
439-
return fmt.Errorf("invalid mapping \"%d:%d:%d\"", ctrID, hostID, length)
440-
}
441-
if ctrID != 0 {
442-
return fmt.Errorf("container mapping of 0 is only supported")
443-
}
444-
return nil
445-
}
446-
447-
func hostID(mapping string) (int, error) {
448-
var (
449-
hostID int
450-
ctrID int
451-
length int
452-
)
453-
if err := validateIDMapping(mapping); err != nil {
454-
return -1, fmt.Errorf("invalid mapping: %w", err)
455-
}
456-
if _, err := fmt.Sscanf(mapping, "%d:%d:%d", &ctrID, &hostID, &length); err != nil {
457-
return -1, err
458-
}
459-
return hostID, nil
460-
}
461-
462428
func (o *snapshotter) createSnapshot(ctx context.Context, kind snapshots.Kind, key, parent string, opts []snapshots.Opt) (_ []mount.Mount, err error) {
463429
var (
464430
s storage.Snapshot
@@ -499,22 +465,35 @@ func (o *snapshotter) createSnapshot(ctx context.Context, kind snapshots.Kind, k
499465
return fmt.Errorf("failed to get snapshot info: %w", err)
500466
}
501467

502-
mappedUID := -1
503-
mappedGID := -1
468+
var (
469+
mappedUID, mappedGID = -1, -1
470+
uidmapLabel, gidmapLabel string
471+
needsRemap = false
472+
)
504473
// NOTE: if idmapped mounts' supported by hosted kernel there may be
505474
// no parents at all, so overlayfs will not work and snapshotter
506475
// will use bind mount. To be able to create file objects inside the
507476
// rootfs -- just chown this only bound directory according to provided
508477
// {uid,gid}map. In case of one/multiple parents -- chown upperdir.
509478
if v, ok := info.Labels[snapshots.LabelSnapshotUIDMapping]; ok {
510-
if mappedUID, err = hostID(v); err != nil {
511-
return fmt.Errorf("failed to parse UID mapping: %w", err)
512-
}
479+
uidmapLabel = v
480+
needsRemap = true
513481
}
514482
if v, ok := info.Labels[snapshots.LabelSnapshotGIDMapping]; ok {
515-
if mappedGID, err = hostID(v); err != nil {
516-
return fmt.Errorf("failed to parse GID mapping: %w", err)
483+
gidmapLabel = v
484+
needsRemap = true
485+
}
486+
487+
if needsRemap {
488+
var idMap userns.IDMap
489+
if err = idMap.Unmarshal(uidmapLabel, gidmapLabel); err != nil {
490+
return fmt.Errorf("failed to unmarshal snapshot ID mapped labels: %w", err)
491+
}
492+
root, err := idMap.RootPair()
493+
if err != nil {
494+
return fmt.Errorf("failed to find root pair: %w", err)
517495
}
496+
mappedUID, mappedGID = int(root.Uid), int(root.Gid)
518497
}
519498

520499
if mappedUID == -1 || mappedGID == -1 {

0 commit comments

Comments
 (0)