From 494f5bd3c9b4c24249ac8af712bc718a05ab63a2 Mon Sep 17 00:00:00 2001 From: David Trudgian Date: Mon, 21 Nov 2022 09:46:10 +0000 Subject: [PATCH] fix: correct uid/gid non-root mapping Ensure e2e tests for oci actions use user profile. Set uid/gid mappings explicitly. We need to do this anyone, going forward, but here it works around: https://github.com/containers/crun/issues/1072 Signed-off-by: Edita Kizinevic --- e2e/actions/oci.go | 2 +- pkg/ocibundle/native/bundle_linux.go | 93 +++++++++++++++++++++++++++- 2 files changed, 92 insertions(+), 3 deletions(-) diff --git a/e2e/actions/oci.go b/e2e/actions/oci.go index 67d51e38f3..bd811021b4 100644 --- a/e2e/actions/oci.go +++ b/e2e/actions/oci.go @@ -84,7 +84,7 @@ func (c actionTests) actionOciRun(t *testing.T) { c.env.RunApptainer( t, e2e.AsSubtest(tt.name), - e2e.WithProfile(e2e.OCIRootProfile), + e2e.WithProfile(e2e.OCIUserProfile), e2e.WithCommand("run"), // While we don't support args we are entering a /bin/sh interactively. e2e.ConsoleRun(e2e.ConsoleSendLine("exit")), diff --git a/pkg/ocibundle/native/bundle_linux.go b/pkg/ocibundle/native/bundle_linux.go index 72d3a5bddc..52ec40358b 100644 --- a/pkg/ocibundle/native/bundle_linux.go +++ b/pkg/ocibundle/native/bundle_linux.go @@ -20,6 +20,7 @@ import ( apexlog "github.com/apex/log" "github.com/apptainer/apptainer/internal/pkg/build/oci" "github.com/apptainer/apptainer/internal/pkg/cache" + "github.com/apptainer/apptainer/internal/pkg/fakeroot" "github.com/apptainer/apptainer/internal/pkg/runtime/engine/config/oci/generate" "github.com/apptainer/apptainer/pkg/ocibundle" "github.com/apptainer/apptainer/pkg/ocibundle/tools" @@ -160,7 +161,9 @@ func (b *Bundle) Create(ctx context.Context, ociConfig *specs.Spec) error { b.setProcessArgs(g) // TODO - Handle custom env and user b.setProcessEnv(g) - b.setProcessUser(g) + if err := b.setProcessUser(g); err != nil { + return err + } return b.writeConfig(g) } @@ -170,14 +173,100 @@ func (b *Bundle) Path() string { return b.bundlePath } -func (b *Bundle) setProcessUser(g *generate.Generator) { +func (b *Bundle) setProcessUser(g *generate.Generator) error { // Set non-root uid/gid per Apptainer defaults uid := uint32(os.Getuid()) if uid != 0 { gid := uint32(os.Getgid()) g.Config.Process.User.UID = uid g.Config.Process.User.GID = gid + // Get user's configured subuid & subgid ranges + subuidRange, err := fakeroot.GetIDRange(fakeroot.SubUIDFile, uid) + if err != nil { + return err + } + // We must be able to map at least 0->65535 inside the container + if subuidRange.Size < 65536 { + return fmt.Errorf("subuid range size (%d) must be at least 65536", subuidRange.Size) + } + subgidRange, err := fakeroot.GetIDRange(fakeroot.SubGIDFile, uid) + if err != nil { + return err + } + if subgidRange.Size <= gid { + return fmt.Errorf("subuid range size (%d) must be at least 65536", subgidRange.Size) + } + + // Preserve own uid container->host, map everything else to subuid range. + if uid < 65536 { + g.Config.Linux.UIDMappings = []specs.LinuxIDMapping{ + { + ContainerID: 0, + HostID: subuidRange.HostID, + Size: uid, + }, + { + ContainerID: uid, + HostID: uid, + Size: 1, + }, + { + ContainerID: uid + 1, + HostID: subuidRange.HostID + uid, + Size: subuidRange.Size - uid, + }, + } + } else { + g.Config.Linux.UIDMappings = []specs.LinuxIDMapping{ + { + ContainerID: 0, + HostID: subuidRange.HostID, + Size: 65536, + }, + { + ContainerID: uid, + HostID: uid, + Size: 1, + }, + } + } + + // Preserve own gid container->host, map everything else to subgid range. + if gid < 65536 { + g.Config.Linux.GIDMappings = []specs.LinuxIDMapping{ + { + ContainerID: 0, + HostID: subgidRange.HostID, + Size: gid, + }, + { + ContainerID: gid, + HostID: gid, + Size: 1, + }, + { + ContainerID: gid + 1, + HostID: subgidRange.HostID + gid, + Size: subgidRange.Size - gid, + }, + } + } else { + g.Config.Linux.GIDMappings = []specs.LinuxIDMapping{ + { + ContainerID: 0, + HostID: subgidRange.HostID, + Size: 65536, + }, + { + ContainerID: gid, + HostID: gid, + Size: 1, + }, + } + } + g.Config.Linux.Namespaces = append(g.Config.Linux.Namespaces, specs.LinuxNamespace{Type: "user"}) } + return nil } func (b *Bundle) setProcessEnv(g *generate.Generator) {