From a4bd292f6f4c7abe99e9dfcb9c74449727b5b577 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 fc3f9d7e0e..c36f59dcf6 100644 --- a/drivers/overlay/overlay.go +++ b/drivers/overlay/overlay.go @@ -947,6 +947,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 } @@ -1183,6 +1192,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 {