Ensure manually-created volumes have correct ownership
As part of a fix for an earlier bug (#5698) we added the ability for Podman to chown volumes to correctly match the user running in the container, even in adverse circumstances (where we don't know the right UID/GID until very late in the process). However, we only did this for volumes created automatically by a `podman run` or `podman create`. Volumes made by `podman volume create` do not get this chown, so their permissions may not be correct. I've looked, and I don't think there's a good reason not to do this chwon for all volumes the first time the container is started. I would prefer to do this as part of volume copy-up, but I don't think that's really possible (copy-up happens earlier in the process and we don't have a spec). There is a small chance, as things stand, that a copy-up happens for one container and then a chown for a second, unrelated container, but the odds of this are astronomically small (we'd need a very close race between two starting containers). Fixes #9608 Signed-off-by: Matthew Heon <mheon@redhat.com>
This commit is contained in:
		
							parent
							
								
									5325957d53
								
							
						
					
					
						commit
						452decf8a4
					
				|  | @ -1627,19 +1627,6 @@ func WithVolumeGID(gid int) VolumeCreateOption { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // WithVolumeNeedsChown sets the NeedsChown flag for the volume.
 |  | ||||||
| func WithVolumeNeedsChown() VolumeCreateOption { |  | ||||||
| 	return func(volume *Volume) error { |  | ||||||
| 		if volume.valid { |  | ||||||
| 			return define.ErrVolumeFinalized |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		volume.state.NeedsChown = true |  | ||||||
| 
 |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // withSetAnon sets a bool notifying libpod that this volume is anonymous and
 | // withSetAnon sets a bool notifying libpod that this volume is anonymous and
 | ||||||
| // should be removed when containers using it are removed and volumes are
 | // should be removed when containers using it are removed and volumes are
 | ||||||
| // specified for removal.
 | // specified for removal.
 | ||||||
|  |  | ||||||
|  | @ -392,7 +392,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai | ||||||
| 		logrus.Debugf("Creating new volume %s for container", vol.Name) | 		logrus.Debugf("Creating new volume %s for container", vol.Name) | ||||||
| 
 | 
 | ||||||
| 		// The volume does not exist, so we need to create it.
 | 		// The volume does not exist, so we need to create it.
 | ||||||
| 		volOptions := []VolumeCreateOption{WithVolumeName(vol.Name), WithVolumeUID(ctr.RootUID()), WithVolumeGID(ctr.RootGID()), WithVolumeNeedsChown()} | 		volOptions := []VolumeCreateOption{WithVolumeName(vol.Name), WithVolumeUID(ctr.RootUID()), WithVolumeGID(ctr.RootGID())} | ||||||
| 		if isAnonymous { | 		if isAnonymous { | ||||||
| 			volOptions = append(volOptions, withSetAnon()) | 			volOptions = append(volOptions, withSetAnon()) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -17,6 +17,7 @@ func newVolume(runtime *Runtime) *Volume { | ||||||
| 	volume.config.Labels = make(map[string]string) | 	volume.config.Labels = make(map[string]string) | ||||||
| 	volume.config.Options = make(map[string]string) | 	volume.config.Options = make(map[string]string) | ||||||
| 	volume.state.NeedsCopyUp = true | 	volume.state.NeedsCopyUp = true | ||||||
|  | 	volume.state.NeedsChown = true | ||||||
| 	return volume | 	return volume | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -643,4 +643,30 @@ VOLUME /test/` | ||||||
| 		found, _ = session.GrepString("888:888") | 		found, _ = session.GrepString("888:888") | ||||||
| 		Expect(found).Should(BeTrue()) | 		Expect(found).Should(BeTrue()) | ||||||
| 	}) | 	}) | ||||||
|  | 
 | ||||||
|  | 	It("volume permissions after run", func() { | ||||||
|  | 		imgName := "testimg" | ||||||
|  | 		dockerfile := `FROM fedora-minimal | ||||||
|  | RUN useradd -m testuser -u 1005 | ||||||
|  | USER testuser` | ||||||
|  | 		podmanTest.BuildImage(dockerfile, imgName, "false") | ||||||
|  | 
 | ||||||
|  | 		testString := "testuser testuser" | ||||||
|  | 
 | ||||||
|  | 		test1 := podmanTest.Podman([]string{"run", "-v", "testvol1:/test", imgName, "bash", "-c", "ls -al /test | grep -v root | grep -v total"}) | ||||||
|  | 		test1.WaitWithDefaultTimeout() | ||||||
|  | 		Expect(test1.ExitCode()).To(Equal(0)) | ||||||
|  | 		Expect(strings.Contains(test1.OutputToString(), testString)).To(BeTrue()) | ||||||
|  | 
 | ||||||
|  | 		volName := "testvol2" | ||||||
|  | 		vol := podmanTest.Podman([]string{"volume", "create", volName}) | ||||||
|  | 		vol.WaitWithDefaultTimeout() | ||||||
|  | 		Expect(vol.ExitCode()).To(Equal(0)) | ||||||
|  | 
 | ||||||
|  | 		test2 := podmanTest.Podman([]string{"run", "-v", fmt.Sprintf("%s:/test", volName), imgName, "bash", "-c", "ls -al /test | grep -v root | grep -v total"}) | ||||||
|  | 		test2.WaitWithDefaultTimeout() | ||||||
|  | 		Expect(test2.ExitCode()).To(Equal(0)) | ||||||
|  | 		Expect(strings.Contains(test2.OutputToString(), testString)).To(BeTrue()) | ||||||
|  | 
 | ||||||
|  | 	}) | ||||||
| }) | }) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue