From 407654c1a9de07982342947c9613330846a2daa0 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Tue, 23 Jun 2020 17:42:45 +0200 Subject: [PATCH] set correct uid/gid on volumes When setting up the volumes for a container, make sure that new volumes are created with the correct uid/gid which we're looking up in the container config. Fixes: #5698 Signed-off-by: Valentin Rothberg --- libpod/container.go | 14 ++++++++++++-- libpod/runtime_ctr.go | 10 +++++++++- test/e2e/run_userns_test.go | 27 +++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/libpod/container.go b/libpod/container.go index c852496760..d98bbaee87 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -1141,8 +1141,13 @@ func (c *Container) IDMappings() (storage.IDMappingOptions, error) { // RootUID returns the root user mapping from container func (c *Container) RootUID() int { + return c.findUID(0) +} + +// findUID returns the UID mapping of the specified uid or 0 if it couldn't be found. +func (c *Container) findUID(uid int) int { for _, uidmap := range c.config.IDMappings.UIDMap { - if uidmap.ContainerID == 0 { + if uidmap.ContainerID == uid { return uidmap.HostID } } @@ -1151,8 +1156,13 @@ func (c *Container) RootUID() int { // RootGID returns the root user mapping from container func (c *Container) RootGID() int { + return c.findGID(0) +} + +// findUID returns the GID mapping of the specified gid or 0 if it couldn't be found. +func (c *Container) findGID(gid int) int { for _, gidmap := range c.config.IDMappings.GIDMap { - if gidmap.ContainerID == 0 { + if gidmap.ContainerID == gid { return gidmap.HostID } } diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 0431861b53..94ad7f95df 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -8,6 +8,7 @@ import ( "strings" "time" + "github.com/containers/buildah/pkg/chrootuser" "github.com/containers/common/pkg/config" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/events" @@ -308,8 +309,15 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai logrus.Debugf("Creating new volume %s for container", vol.Name) + // Get the uid/gid of the container user to create the volume + // with the correct uid/gid. See github.com/containers/libpod/issues/5698. + uid, gid, _, err := chrootuser.GetUser(ctr.state.Mountpoint, ctr.config.User) + if err != nil { + return nil, errors.Wrapf(err, "error created named volume %q", vol.Name) + } + // The volume does not exist, so we need to create it. - volOptions := []VolumeCreateOption{WithVolumeName(vol.Name), WithVolumeUID(ctr.RootUID()), WithVolumeGID(ctr.RootGID())} + volOptions := []VolumeCreateOption{WithVolumeName(vol.Name), WithVolumeUID(int(uid)), WithVolumeGID(int(gid))} if isAnonymous { volOptions = append(volOptions, withSetAnon()) } diff --git a/test/e2e/run_userns_test.go b/test/e2e/run_userns_test.go index 5b9a99daae..216e067681 100644 --- a/test/e2e/run_userns_test.go +++ b/test/e2e/run_userns_test.go @@ -238,4 +238,31 @@ var _ = Describe("Podman UserNS support", func() { ok, _ := session.GrepString("4998") Expect(ok).To(BeTrue()) }) + + It("podman --user with volume", func() { + tests := []struct { + uid, gid, arg, vol string + }{ + {"0", "0", "0:0", "vol-0"}, + {"1000", "0", "1000", "vol-1"}, + {"1000", "1000", "1000:1000", "vol-2"}, + } + + for _, tt := range tests { + session := podmanTest.Podman([]string{"run", "-d", "--user", tt.arg, "--mount", "type=volume,src=" + tt.vol + ",dst=/home/user", "alpine", "top"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + inspectUID := podmanTest.Podman([]string{"volume", "inspect", "--format", "{{ .UID }}", tt.vol}) + inspectUID.WaitWithDefaultTimeout() + Expect(inspectUID.ExitCode()).To(Equal(0)) + Expect(inspectUID.OutputToString()).To(Equal(tt.uid)) + + // Make sure we're defaulting to 0. + inspectGID := podmanTest.Podman([]string{"volume", "inspect", "--format", "{{ .GID }}", tt.vol}) + inspectGID.WaitWithDefaultTimeout() + Expect(inspectGID.ExitCode()).To(Equal(0)) + Expect(inspectGID.OutputToString()).To(Equal(tt.gid)) + } + }) })