Skip to content

Commit

Permalink
When superceding mounts, check for opposite types
Browse files Browse the repository at this point in the history
When we supercede low-priority mounts and volumes (image volumes,
and volumes sourced from --volumes-from) with higher-priority
ones (the --volume and --mount flags), we always replaced
lower-priority mounts of the same type (e.g. a user mount to
/tmp/test1 would supercede a volumes-from mount to the same
destination). However, we did not supercede the opposite type - a
named volume from image volumes at /tmp/test1 would be allowed to
remain and create a conflict, preventing container creation.

Solve this by destroying opposite types before merging (we can't
do it in the same loop, as then named volumes, which go second,
might trample changes made by mounts).

Fixes containers#3174

Signed-off-by: Matthew Heon <[email protected]>
  • Loading branch information
mheon committed May 21, 2019
1 parent 773b9ac commit 57e38e9
Showing 1 changed file with 25 additions and 11 deletions.
36 changes: 25 additions & 11 deletions pkg/spec/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,29 @@ func (config *CreateConfig) parseVolumes(runtime *libpod.Runtime) ([]spec.Mount,
unifiedMounts[initMount.Destination] = initMount
}

// Before superceding, we need to find volume mounts which conflict with
// named volumes, and vice versa.
// We'll delete the conflicts here as we supercede.
for dest := range unifiedMounts {
if _, ok := baseVolumes[dest]; ok {
delete(baseVolumes, dest)
}
}
for dest := range unifiedVolumes {
if _, ok := baseMounts[dest]; ok {
delete(baseMounts, dest)
}
}

// Supercede volumes-from/image volumes with unified volumes from above.
// This is an unconditional replacement.
for dest, mount := range unifiedMounts {
baseMounts[dest] = mount
}
for dest, volume := range unifiedVolumes {
baseVolumes[dest] = volume
}

// If requested, add tmpfs filesystems for read-only containers.
// Need to keep track of which we created, so we don't modify options
// for them later...
Expand All @@ -146,14 +169,14 @@ func (config *CreateConfig) parseVolumes(runtime *libpod.Runtime) ([]spec.Mount,
if config.ReadOnlyRootfs && config.ReadOnlyTmpfs {
options := []string{"rw", "rprivate", "nosuid", "nodev", "tmpcopyup", "size=65536k"}
for dest := range readonlyTmpfs {
if _, ok := unifiedMounts[dest]; ok {
if _, ok := baseMounts[dest]; ok {
continue
}
localOpts := options
if dest == "/run" {
localOpts = append(localOpts, "noexec")
}
unifiedMounts[dest] = spec.Mount{
baseMounts[dest] = spec.Mount{
Destination: dest,
Type: "tmpfs",
Source: "tmpfs",
Expand All @@ -163,15 +186,6 @@ func (config *CreateConfig) parseVolumes(runtime *libpod.Runtime) ([]spec.Mount,
}
}

// Supercede volumes-from/image volumes with unified volumes from above.
// This is an unconditional replacement.
for dest, mount := range unifiedMounts {
baseMounts[dest] = mount
}
for dest, volume := range unifiedVolumes {
baseVolumes[dest] = volume
}

// Check for conflicts between named volumes and mounts
for dest := range baseMounts {
if _, ok := baseVolumes[dest]; ok {
Expand Down

0 comments on commit 57e38e9

Please sign in to comment.