c8d: "unremap" the user namespace on commit

We remap the snapshot when we create a container, we have to to the
inverse when we commit the container into an image

Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
This commit is contained in:
Djordje Lukic 2023-11-08 12:23:55 +01:00
parent a7acfffea6
commit d06af368ad
No known key found for this signature in database
3 changed files with 69 additions and 5 deletions

View file

@ -16,6 +16,7 @@ import (
cerrdefs "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/images"
"github.com/containerd/containerd/leases"
"github.com/containerd/containerd/mount"
"github.com/containerd/containerd/rootfs"
"github.com/containerd/containerd/snapshots"
"github.com/containerd/log"
@ -90,7 +91,7 @@ func (i *ImageService) CommitImage(ctx context.Context, cc backend.CommitConfig)
if diffLayerDesc != nil {
rootfsID := identity.ChainID(imageConfig.RootFS.DiffIDs).String()
if err := applyDiffLayer(ctx, rootfsID, parentImage, sn, differ, *diffLayerDesc); err != nil {
if err := i.applyDiffLayer(ctx, rootfsID, cc.ContainerID, sn, differ, *diffLayerDesc); err != nil {
return "", fmt.Errorf("failed to apply diff: %w", err)
}
@ -291,13 +292,19 @@ func createDiff(ctx context.Context, name string, sn snapshots.Snapshotter, cs c
}
// applyDiffLayer will apply diff layer content created by createDiff into the snapshotter.
func applyDiffLayer(ctx context.Context, name string, baseImg imagespec.DockerOCIImage, sn snapshots.Snapshotter, differ diff.Applier, diffDesc ocispec.Descriptor) (retErr error) {
func (i *ImageService) applyDiffLayer(ctx context.Context, name string, containerID string, sn snapshots.Snapshotter, differ diff.Applier, diffDesc ocispec.Descriptor) (retErr error) {
var (
key = uniquePart() + "-" + name
parent = identity.ChainID(baseImg.RootFS.DiffIDs).String()
mounts []mount.Mount
err error
)
mount, err := sn.Prepare(ctx, key, parent)
info, err := sn.Stat(ctx, containerID)
if err != nil {
return err
}
mounts, err = sn.Prepare(ctx, key, info.Parent)
if err != nil {
return fmt.Errorf("failed to prepare snapshot: %w", err)
}
@ -312,16 +319,46 @@ func applyDiffLayer(ctx context.Context, name string, baseImg imagespec.DockerOC
}
}()
if _, err = differ.Apply(ctx, diffDesc, mount); err != nil {
if _, err = differ.Apply(ctx, diffDesc, mounts); err != nil {
return err
}
if !i.idMapping.Empty() {
// The rootfs of the container is remapped if an id mapping exists, we
// need to "unremap" it before committing the snapshot
rootPair := i.idMapping.RootPair()
usernsID := fmt.Sprintf("%s-%d-%d", key, rootPair.UID, rootPair.GID)
remappedID := usernsID + remapSuffix
if err = sn.Commit(ctx, name+"-pre", key); err != nil {
if cerrdefs.IsAlreadyExists(err) {
return nil
}
return err
}
mounts, err = sn.Prepare(ctx, remappedID, name+"-pre")
if err != nil {
return err
}
if err := i.unremapRootFS(ctx, mounts); err != nil {
return err
}
if err := sn.Commit(ctx, name, remappedID); err != nil {
return err
}
key = remappedID
}
if err = sn.Commit(ctx, name, key); err != nil {
if cerrdefs.IsAlreadyExists(err) {
return nil
}
return err
}
return nil
}

View file

@ -67,3 +67,25 @@ func (i *ImageService) remapRootFS(ctx context.Context, mounts []mount.Mount) er
})
})
}
func (i *ImageService) unremapRootFS(ctx context.Context, mounts []mount.Mount) error {
return mount.WithTempMount(ctx, mounts, func(root string) error {
return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
stat := info.Sys().(*syscall.Stat_t)
if stat == nil {
return fmt.Errorf("cannot get underlying data for %s", path)
}
uid, gid, err := i.idMapping.ToContainer(idtools.Identity{UID: int(stat.Uid), GID: int(stat.Gid)})
if err != nil {
return err
}
return os.Lchown(path, uid, gid)
})
})
}

View file

@ -3,9 +3,14 @@ package containerd
import (
"context"
"github.com/containerd/containerd/mount"
"github.com/containerd/containerd/snapshots"
)
func (i *ImageService) remapSnapshot(ctx context.Context, snapshotter snapshots.Snapshotter, id string, parentSnapshot string) error {
return nil
}
func (i *ImageService) unremapRootFS(ctx context.Context, mounts []mount.Mount) error {
return nil
}