From 4b5e4c5ad9d07c09e2ae960d84a5c4cd81a97c33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20Trma=C4=8D?= Date: Thu, 17 Feb 2022 18:53:04 +0100 Subject: [PATCH] Don't blindly reuse state from a previous layer when re-creating it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have reports in the wild of a layer store where two symbolic links in linkDir point to the same layer. That could only happen when calling Driver.create with a previously-used layer ID (which happens all the time because pulls use deterministic layer IDs), without fully deleting the previous version of the layer (so far, we don't know how that has happened). To avoid such situations, don't just leave whatever was in the layer directory laying around; try to remove any pre-existing contents, as well as the symbolic link in linkDir, if any. Signed-off-by: Miloslav Trmač --- drivers/overlay/overlay.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/overlay/overlay.go b/drivers/overlay/overlay.go index 5b19e4de30..24a449b590 100644 --- a/drivers/overlay/overlay.go +++ b/drivers/overlay/overlay.go @@ -918,6 +918,15 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, disable d.locker.Lock(id) defer d.locker.Unlock(id) + if st, err := system.Lstat(dir); err == nil { + logrus.Warning("Trying to create a layer %#v while directory %q already exists; removing it first", id, dir) + // Don’t just os.RemoveAll(dir) here; removeLocked also removes the link in linkDir, + // so that we can’t end up with two symlinks in linkDir pointing to the same layer. + if err := d.removeLocked(id); err != nil { + return errors.Wrapf(err, "removing a pre-existing layer directory %q", dir) + } + } + if err := idtools.MkdirAllAndChownNew(dir, 0700, idPair); err != nil { return err } @@ -1154,6 +1163,10 @@ func (d *Driver) Remove(id string) error { d.locker.Lock(id) defer d.locker.Unlock(id) + return d.removeLocked(id) +} + +func (d *Driver) removeLocked(id string) error { dir := d.dir(id) lid, err := ioutil.ReadFile(path.Join(dir, "link")) if err == nil {