summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@pm.me>2020-02-10 13:37:38 -0500
committerMatthew Heon <mheon@redhat.com>2020-02-12 10:58:42 -0500
commitc140ecdc9b416ab4efd4d21d14acd63b6adbdd42 (patch)
treef8f14e2f0f5ef65e4545a1e3c7a97631bf6574c9
parente57253d06841d7a128ef760f8c47acf4b59157df (diff)
downloadpodman-c140ecdc9b416ab4efd4d21d14acd63b6adbdd42.tar.gz
podman-c140ecdc9b416ab4efd4d21d14acd63b6adbdd42.tar.bz2
podman-c140ecdc9b416ab4efd4d21d14acd63b6adbdd42.zip
Do not copy up when volume is not empty
When Docker performs a copy up, it first verifies that the volume being copied into is empty; thus, for volumes that have been modified elsewhere (e.g. manually copying into then), the copy up will not be performed at all. Duplicate this behavior in Podman by checking if the volume is empty before copying. Furthermore, move setting copyup to false further up. This will prevent a potential race where copy up could happen more than once if Podman was killed after some files had been copied but before the DB was updated. This resolves CVE-2020-1726. Signed-off-by: Matthew Heon <matthew.heon@pm.me>
-rw-r--r--libpod/container_internal.go28
-rw-r--r--test/e2e/run_volume_test.go24
2 files changed, 46 insertions, 6 deletions
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 78ec09f29..216bbe669 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -1383,18 +1383,34 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string)
}
if vol.state.NeedsCopyUp {
logrus.Debugf("Copying up contents from container %s to volume %s", c.ID(), vol.Name())
+
+ // Set NeedsCopyUp to false immediately, so we don't try this
+ // again when there are already files copied.
+ vol.state.NeedsCopyUp = false
+ if err := vol.save(); err != nil {
+ return nil, err
+ }
+
+ // If the volume is not empty, we should not copy up.
+ volMount := vol.MountPoint()
+ contents, err := ioutil.ReadDir(volMount)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error listing contents of volume %s mountpoint when copying up from container %s", vol.Name(), c.ID())
+ }
+ if len(contents) > 0 {
+ // The volume is not empty. It was likely modified
+ // outside of Podman. For safety, let's not copy up into
+ // it. Fixes CVE-2020-1726.
+ return vol, nil
+ }
+
srcDir, err := securejoin.SecureJoin(mountpoint, v.Dest)
if err != nil {
return nil, errors.Wrapf(err, "error calculating destination path to copy up container %s volume %s", c.ID(), vol.Name())
}
- if err := c.copyWithTarFromImage(srcDir, vol.MountPoint()); err != nil && !os.IsNotExist(err) {
+ if err := c.copyWithTarFromImage(srcDir, volMount); err != nil && !os.IsNotExist(err) {
return nil, errors.Wrapf(err, "error copying content from container %s into volume %s", c.ID(), vol.Name())
}
-
- vol.state.NeedsCopyUp = false
- if err := vol.save(); err != nil {
- return nil, err
- }
}
return vol, nil
}
diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go
index 0c2389e40..46c27dc2e 100644
--- a/test/e2e/run_volume_test.go
+++ b/test/e2e/run_volume_test.go
@@ -397,4 +397,28 @@ var _ = Describe("Podman run with volumes", func() {
volMount.WaitWithDefaultTimeout()
Expect(volMount.ExitCode()).To(Not(Equal(0)))
})
+
+ It("Podman fix for CVE-2020-1726", func() {
+ volName := "testVol"
+ volCreate := podmanTest.Podman([]string{"volume", "create", volName})
+ volCreate.WaitWithDefaultTimeout()
+ Expect(volCreate.ExitCode()).To(Equal(0))
+
+ volPath := podmanTest.Podman([]string{"volume", "inspect", "--format", "{{.Mountpoint}}", volName})
+ volPath.WaitWithDefaultTimeout()
+ Expect(volPath.ExitCode()).To(Equal(0))
+ path := volPath.OutputToString()
+
+ fileName := "thisIsATestFile"
+ file, err := os.Create(filepath.Join(path, fileName))
+ Expect(err).To(BeNil())
+ defer file.Close()
+
+ runLs := podmanTest.Podman([]string{"run", "-t", "-i", "--rm", "-v", fmt.Sprintf("%v:/etc/ssl", volName), ALPINE, "ls", "-1", "/etc/ssl"})
+ runLs.WaitWithDefaultTimeout()
+ Expect(runLs.ExitCode()).To(Equal(0))
+ outputArr := runLs.OutputToStringArray()
+ Expect(len(outputArr)).To(Equal(1))
+ Expect(strings.Contains(outputArr[0], fileName)).To(BeTrue())
+ })
})