mirror of
https://github.com/containers/podman.git
synced 2025-07-15 03:02:52 +08:00
Fix permissions on initially created named volumes
Permission of volume should match the directory it is being mounted on. Fixes: https://github.com/containers/podman/issues/10188 Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
@ -1062,7 +1062,7 @@ func (c *Container) init(ctx context.Context, retainRetries bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range c.config.NamedVolumes {
|
for _, v := range c.config.NamedVolumes {
|
||||||
if err := c.chownVolume(v.Name); err != nil {
|
if err := c.fixVolumePermissions(v); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1681,64 +1681,6 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string)
|
|||||||
return vol, nil
|
return vol, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chown the specified volume if necessary.
|
|
||||||
func (c *Container) chownVolume(volumeName string) error {
|
|
||||||
vol, err := c.runtime.state.Volume(volumeName)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "error retrieving named volume %s for container %s", volumeName, c.ID())
|
|
||||||
}
|
|
||||||
|
|
||||||
vol.lock.Lock()
|
|
||||||
defer vol.lock.Unlock()
|
|
||||||
|
|
||||||
// The volume may need a copy-up. Check the state.
|
|
||||||
if err := vol.update(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: For now, I've disabled chowning volumes owned by non-Podman
|
|
||||||
// drivers. This may be safe, but it's really going to be a case-by-case
|
|
||||||
// thing, I think - safest to leave disabled now and re-enable later if
|
|
||||||
// there is a demand.
|
|
||||||
if vol.state.NeedsChown && !vol.UsesVolumeDriver() {
|
|
||||||
vol.state.NeedsChown = false
|
|
||||||
|
|
||||||
uid := int(c.config.Spec.Process.User.UID)
|
|
||||||
gid := int(c.config.Spec.Process.User.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)
|
|
||||||
newPair, err := mappings.ToHost(p)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "error mapping user %d:%d", uid, gid)
|
|
||||||
}
|
|
||||||
uid = newPair.UID
|
|
||||||
gid = newPair.GID
|
|
||||||
}
|
|
||||||
|
|
||||||
vol.state.UIDChowned = uid
|
|
||||||
vol.state.GIDChowned = gid
|
|
||||||
|
|
||||||
if err := vol.save(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
mountPoint, err := vol.MountPoint()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := os.Lchown(mountPoint, uid, gid); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleanupStorage unmounts and cleans up the container's root filesystem
|
// cleanupStorage unmounts and cleans up the container's root filesystem
|
||||||
func (c *Container) cleanupStorage() error {
|
func (c *Container) cleanupStorage() error {
|
||||||
if !c.state.Mounted {
|
if !c.state.Mounted {
|
||||||
|
@ -2426,3 +2426,77 @@ func (c *Container) createSecretMountDir() error {
|
|||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix ownership and permissions of the specified volume if necessary.
|
||||||
|
func (c *Container) fixVolumePermissions(v *ContainerNamedVolume) error {
|
||||||
|
vol, err := c.runtime.state.Volume(v.Name)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "error retrieving named volume %s for container %s", v.Name, c.ID())
|
||||||
|
}
|
||||||
|
|
||||||
|
vol.lock.Lock()
|
||||||
|
defer vol.lock.Unlock()
|
||||||
|
|
||||||
|
// The volume may need a copy-up. Check the state.
|
||||||
|
if err := vol.update(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: For now, I've disabled chowning volumes owned by non-Podman
|
||||||
|
// drivers. This may be safe, but it's really going to be a case-by-case
|
||||||
|
// thing, I think - safest to leave disabled now and re-enable later if
|
||||||
|
// there is a demand.
|
||||||
|
if vol.state.NeedsChown && !vol.UsesVolumeDriver() {
|
||||||
|
vol.state.NeedsChown = false
|
||||||
|
|
||||||
|
uid := int(c.config.Spec.Process.User.UID)
|
||||||
|
gid := int(c.config.Spec.Process.User.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)
|
||||||
|
newPair, err := mappings.ToHost(p)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "error mapping user %d:%d", uid, gid)
|
||||||
|
}
|
||||||
|
uid = newPair.UID
|
||||||
|
gid = newPair.GID
|
||||||
|
}
|
||||||
|
|
||||||
|
vol.state.UIDChowned = uid
|
||||||
|
vol.state.GIDChowned = gid
|
||||||
|
|
||||||
|
if err := vol.save(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mountPoint, err := vol.MountPoint()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.Lchown(mountPoint, uid, gid); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the new volume matches the permissions of the target directory.
|
||||||
|
// https://github.com/containers/podman/issues/10188
|
||||||
|
st, err := os.Lstat(filepath.Join(c.state.Mountpoint, v.Dest))
|
||||||
|
if err == nil {
|
||||||
|
if err := os.Chmod(mountPoint, st.Mode()|0111); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
stat := st.Sys().(*syscall.Stat_t)
|
||||||
|
atime := time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec))
|
||||||
|
if err := os.Chtimes(mountPoint, atime, st.ModTime()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if !os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -57,3 +57,8 @@ func (c *Container) reloadNetwork() error {
|
|||||||
func (c *Container) getUserOverrides() *lookup.Overrides {
|
func (c *Container) getUserOverrides() *lookup.Overrides {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix ownership and permissions of the specified volume if necessary.
|
||||||
|
func (c *Container) fixVolumePermissions(v *ContainerNamedVolume) error {
|
||||||
|
return define.ErrNotImplemented
|
||||||
|
}
|
||||||
|
@ -904,6 +904,18 @@ USER bin`, BB)
|
|||||||
Expect(session.ExitCode()).To(Equal(100))
|
Expect(session.ExitCode()).To(Equal(100))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman run with named volume", func() {
|
||||||
|
session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "stat", "-c", "%a %Y", "/var/tmp"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
perms := session.OutputToString()
|
||||||
|
|
||||||
|
session = podmanTest.Podman([]string{"run", "--rm", "-v", "test:/var/tmp", ALPINE, "stat", "-c", "%a %Y", "/var/tmp"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
Expect(session.OutputToString()).To(Equal(perms))
|
||||||
|
})
|
||||||
|
|
||||||
It("podman run with built-in volume image", func() {
|
It("podman run with built-in volume image", func() {
|
||||||
session := podmanTest.Podman([]string{"run", "--rm", redis, "ls"})
|
session := podmanTest.Podman([]string{"run", "--rm", redis, "ls"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
|
Reference in New Issue
Block a user