From eae788724abceb68cb856d35fbd824a47ffa8b66 Mon Sep 17 00:00:00 2001 From: Avi Deitcher Date: Mon, 21 Jul 2025 23:14:59 +0300 Subject: [PATCH] check lock when reading cache provider index (#4147) Signed-off-by: Avi Deitcher --- src/cmd/linuxkit/cache/find.go | 2 +- src/cmd/linuxkit/cache/image.go | 2 +- src/cmd/linuxkit/cache/provider.go | 14 ++++++++++++++ src/cmd/linuxkit/cache/resolvabledescriptor.go | 2 +- src/cmd/linuxkit/cache/write.go | 2 +- 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/cmd/linuxkit/cache/find.go b/src/cmd/linuxkit/cache/find.go index 7e9757bee..200790930 100644 --- a/src/cmd/linuxkit/cache/find.go +++ b/src/cmd/linuxkit/cache/find.go @@ -83,7 +83,7 @@ func (p *Provider) findIndex(imageName string) (v1.ImageIndex, error) { // FindDescriptor get the first descriptor pointed to by the image reference, whether tagged or digested func (p *Provider) FindDescriptor(ref *reference.Spec) (*v1.Descriptor, error) { - index, err := p.cache.ImageIndex() + index, err := p.Index() // if there is no root index, we are broken if err != nil { return nil, fmt.Errorf("invalid image cache: %v", err) diff --git a/src/cmd/linuxkit/cache/image.go b/src/cmd/linuxkit/cache/image.go index 0cf199c97..5b4ac1251 100644 --- a/src/cmd/linuxkit/cache/image.go +++ b/src/cmd/linuxkit/cache/image.go @@ -14,7 +14,7 @@ func ListImages(dir string) (map[string]string, error) { } func (p *Provider) List() (map[string]string, error) { - ii, err := p.cache.ImageIndex() + ii, err := p.Index() if err != nil { return nil, err } diff --git a/src/cmd/linuxkit/cache/provider.go b/src/cmd/linuxkit/cache/provider.go index da0b6b969..d9b2ff812 100644 --- a/src/cmd/linuxkit/cache/provider.go +++ b/src/cmd/linuxkit/cache/provider.go @@ -7,6 +7,7 @@ import ( "github.com/containerd/containerd/v2/core/content" "github.com/containerd/containerd/v2/plugins/content/local" + v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/google/go-containerregistry/pkg/v1/layout" "github.com/linuxkit/linuxkit/src/cmd/linuxkit/util" log "github.com/sirupsen/logrus" @@ -37,6 +38,19 @@ func NewProvider(dir string) (*Provider, error) { return p, nil } +// Index returns the root image index for the cache. +// All attempts to read the index *must* use this function, so that it will lock the cache to prevent concurrent access. +// The underlying library writes modifications directly to the index, +// so not only must ensure that that only one process is writing at a time, but that no one is reading +// while we are writing, to avoid corruption. +func (p *Provider) Index() (v1.ImageIndex, error) { + if p.Lock() != nil { + return nil, fmt.Errorf("unable to lock cache %s", p.dir) + } + defer p.Unlock() + return p.cache.ImageIndex() +} + // Lock locks the cache directory to prevent concurrent access func (p *Provider) Lock() error { // if the lock is already set, we do not need to do anything diff --git a/src/cmd/linuxkit/cache/resolvabledescriptor.go b/src/cmd/linuxkit/cache/resolvabledescriptor.go index b28c91725..74624b01f 100644 --- a/src/cmd/linuxkit/cache/resolvabledescriptor.go +++ b/src/cmd/linuxkit/cache/resolvabledescriptor.go @@ -51,7 +51,7 @@ func (l layoutIndex) Digest() (v1.Hash, error) { // a given imageName. func (p *Provider) FindRoot(imageName string) (ResolvableDescriptor, error) { matcher := match.Name(imageName) - rootIndex, err := p.cache.ImageIndex() + rootIndex, err := p.Index() // of there is no root index, we are broken if err != nil { return nil, fmt.Errorf("invalid image cache: %v", err) diff --git a/src/cmd/linuxkit/cache/write.go b/src/cmd/linuxkit/cache/write.go index 83da2775e..4ab44c606 100644 --- a/src/cmd/linuxkit/cache/write.go +++ b/src/cmd/linuxkit/cache/write.go @@ -239,7 +239,7 @@ func (p *Provider) IndexWrite(ref *reference.Spec, descriptors ...v1.Descriptor) return errors.New("cannot create index without any manifests") } - ii, err := p.cache.ImageIndex() + ii, err := p.Index() if err != nil { return fmt.Errorf("unable to get root index: %v", err) }