From 006af1c98efe13864f548c9a5e223e2dd8ef45d3 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..d147e2593c 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 _, err := system.Lstat(dir); err == nil { + logrus.Warnf("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 {