Skip to content

Commit a853d8a

Browse files
committed
storage: overlay: only unmount storage home if needed
If the storage home directory is a mountpoint, `mount.MakePrivate()` changes the existing mountpoint instead of creating a new bind mount of the storage home onto itself. In this case, attempting to unmount the storage home upon cleanup will remove the externally created mountpoint, thus breaking the pre-existing system configuration. Since it is not easily possible to detect whether a given mountpoint is a self-bind-mount, instead remember whether we ended up performing one and only attempt to unmount it if we did. This should be considered a hack because it leaks the implementation details of `mount.MakePrivate()` (i.e. the fact that a new bind mount is only created if the target is not already a mountpoint). Fixes: containers/podman#27012 Signed-off-by: Ivan Shapovalov <[email protected]>
1 parent 58b82c9 commit a853d8a

File tree

1 file changed

+16
-1
lines changed

1 file changed

+16
-1
lines changed

storage/drivers/overlay/overlay.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ type Driver struct {
138138
stagingDirsLocks map[string]*staging_lockfile.StagingLockFile
139139

140140
supportsIDMappedMounts *bool
141+
142+
homeNeedsUnmount bool
141143
}
142144

143145
type additionalLayerStore struct {
@@ -421,7 +423,16 @@ func Init(home string, options graphdriver.Options) (graphdriver.Driver, error)
421423
}
422424
}
423425

426+
var homeNeedsUnmount bool
424427
if !opts.skipMountHome {
428+
// mount.MakePrivate() will either bind the home directory onto itself
429+
// or make the existing mountpoint private if it is already a mountpoint.
430+
// Upon shutdown, we must ensure that we do not remove any mountpoint
431+
// that was not created by us.
432+
// XXX: this leaks implementation details of mount.MakePrivate()
433+
if mounted, err := mount.Mounted(home); err != nil {
434+
homeNeedsUnmount = !mounted
435+
}
425436
if err := mount.MakePrivate(home); err != nil {
426437
return nil, fmt.Errorf("overlay: failed to make mount private: %w", err)
427438
}
@@ -445,6 +456,7 @@ func Init(home string, options graphdriver.Options) (graphdriver.Driver, error)
445456
options: *opts,
446457
stagingDirsLocksMutex: sync.Mutex{},
447458
stagingDirsLocks: make(map[string]*staging_lockfile.StagingLockFile),
459+
homeNeedsUnmount: homeNeedsUnmount,
448460
}
449461

450462
d.naiveDiff = graphdriver.NewNaiveDiffDriver(d, graphdriver.NewNaiveLayerIDMapUpdater(d))
@@ -863,7 +875,10 @@ func (d *Driver) Cleanup() error {
863875
if anyPresent {
864876
return nil
865877
}
866-
return mount.Unmount(d.home)
878+
if d.homeNeedsUnmount {
879+
return mount.Unmount(d.home)
880+
}
881+
return nil
867882
}
868883

869884
// pruneStagingDirectories cleans up any staging directory that was leaked.

0 commit comments

Comments
 (0)