From d4ebf2eebaa7428dbff908509d5b4c3238b8fe34 Mon Sep 17 00:00:00 2001
From: Justin Chadwell <me@jedevc.com>
Date: Thu, 17 Aug 2023 13:39:00 +0100
Subject: [PATCH] solver: fix possible race for provenance ResolveImageConfig

ResolveImageConfig can be called concurrently - for example, by
dockerfile2llb during conversion, we loop through each stage and resolve
the base image for that stage.

In the case that two calls to ResolveImageConfig finish at roughly the
same time, we can hit an edge case where we attempt to modify the
bridge's image records at the same time.

To fix this, we just need to use the bridge's mutex to prevent
concurrent access here.

This should fix the following stack trace found in CI:

    sandbox.go:144: goroutine 1079 [running]:
    sandbox.go:144: github.com/moby/buildkit/solver/llbsolver.(*provenanceBridge).ResolveImageConfig(0xc000431e00, {0x1c2b040?, 0xc0008e5b30?}, {0xc00094ba00?, 0xc0003728f0?}, {0x0, 0xc0006cb580, {0x19ba868, 0x7}, {0xc0008f7500, ...}, ...})
    sandbox.go:144: 	/src/solver/llbsolver/provenance.go:139 +0x1fb
    sandbox.go:144: github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb.toDispatchState.func3.1()
    sandbox.go:144: 	/src/frontend/dockerfile/dockerfile2llb/convert.go:405 +0x5fe
    sandbox.go:144: golang.org/x/sync/errgroup.(*Group).Go.func1()
    sandbox.go:144: 	/src/vendor/golang.org/x/sync/errgroup/errgroup.go:75 +0x64
    sandbox.go:144: created by golang.org/x/sync/errgroup.(*Group).Go
    sandbox.go:144: 	/src/vendor/golang.org/x/sync/errgroup/errgroup.go:72 +0xa5
    --- FAIL: TestIntegration/TestNoCache/worker=oci-rootless/frontend=builtin (4.45s)

No other explanation for this failure makes sense - `b` cannot be `nil`
at this point, since a call to `b.llbBridge.ResolveImageConfig` has just
succeeded (also because that would be very strange).

Signed-off-by: Justin Chadwell <me@jedevc.com>
(cherry picked from commit c08f767e2602711f6ad1e4a9986587b16a94533e)
Signed-off-by: Justin Chadwell <me@jedevc.com>
---
 solver/llbsolver/provenance.go | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/solver/llbsolver/provenance.go b/solver/llbsolver/provenance.go
index 9138d6d9f88fa..26abf78d1c6c8 100644
--- a/solver/llbsolver/provenance.go
+++ b/solver/llbsolver/provenance.go
@@ -137,12 +137,14 @@ func (b *provenanceBridge) ResolveImageConfig(ctx context.Context, ref string, o
 		return "", "", nil, err
 	}
 
+	b.mu.Lock()
 	b.images = append(b.images, provenance.ImageSource{
 		Ref:      ref,
 		Platform: opt.Platform,
 		Digest:   dgst,
 		Local:    opt.ResolverType == llb.ResolverTypeOCILayout,
 	})
+	b.mu.Unlock()
 	return ref, dgst, config, nil
 }