libpod: correctly map UID/GID for existing dirs

if the target mount path already exists and the container uses a user
namespace, correctly map the target UID/GID to the host values before
attempting a chown.

Closes: https://github.com/containers/podman/issues/21608

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano
2024-02-12 10:54:21 +01:00
parent 6d107a26fb
commit c29fde2656
2 changed files with 32 additions and 1 deletions

View File

@ -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
}
}

View File

@ -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()