diff --git a/libpod/container_internal_common.go b/libpod/container_internal_common.go index 64bd8a5f8c9e..02820ecbfadf 100644 --- a/libpod/container_internal_common.go +++ b/libpod/container_internal_common.go @@ -2865,7 +2865,22 @@ func (c *Container) fixVolumePermissions(v *ContainerNamedVolume) error { st, err := os.Lstat(filepath.Join(c.state.Mountpoint, v.Dest)) if err == nil { if stat, ok := st.Sys().(*syscall.Stat_t); ok { - if err := idtools.SafeLchown(mountPoint, int(stat.Uid), int(stat.Gid)); err != nil { + uid, gid := int(stat.Uid), int(stat.Gid) + + if c.config.IDMappings.UIDMap != nil { + p := idtools.IDPair{ + UID: uid, + GID: gid, + } + mappings := idtools.NewIDMappingsFromMaps(c.config.IDMappings.UIDMap, c.config.IDMappings.GIDMap) + newUID, newGID, err := mappings.ToContainer(p) + if err != nil { + return fmt.Errorf("mapping user %d:%d: %w", uid, gid, err) + } + uid, gid = newUID, newGID + } + + if err := idtools.SafeLchown(mountPoint, uid, gid); err != nil { return err } } diff --git a/test/e2e/run_userns_test.go b/test/e2e/run_userns_test.go index 7bf1fe594cbf..311a6f1c4127 100644 --- a/test/e2e/run_userns_test.go +++ b/test/e2e/run_userns_test.go @@ -105,6 +105,22 @@ var _ = Describe("Podman UserNS support", func() { Expect(session.OutputToString()).To(ContainSubstring("#0:0#")) }) + It("podman uidmapping and gidmapping with an idmapped volume on existing directory", func() { + SkipIfRunc(podmanTest, "Test not supported yet with runc (issue 17433, wontfix)") + SkipOnOSVersion("fedora", "36") + // The directory /mnt already exists in the image + session := podmanTest.Podman([]string{"run", "--uidmap=0:1:500", "--gidmap=0:200:5000", "-v", "my-foo-volume:/mnt:Z,idmap", "alpine", "stat", "-c", "#%u:%g#", "/mnt"}) + session.WaitWithDefaultTimeout() + if strings.Contains(session.ErrorToString(), "Operation not permitted") { + Skip("not sufficiently privileged") + } + if strings.Contains(session.ErrorToString(), "Invalid argument") { + Skip("the file system doesn't support idmapped mounts") + } + Expect(session).Should(ExitCleanly()) + Expect(session.OutputToString()).To(ContainSubstring("#0:0#")) + }) + It("podman uidmapping and gidmapping --net=host", func() { session := podmanTest.Podman([]string{"run", "--net=host", "--uidmap=0:1:5000", "--gidmap=0:200:5000", "alpine", "echo", "hello"}) session.WaitWithDefaultTimeout()