buildstep: keep a check ask's cache layer out of every step's reach, move through an os.Root, and layer the build cache alone

Review of 62a50eb: the layer lay in the workspace, which every step binds read-write,
so a change's command could swap a kept directory for a symlink and the move, run
outside the sandbox, would write into the shared cache (ADR 0541 §2). The layer now
lies beside the workspace (Workspaces.CacheLayer, removed by Release and Sweep),
Command refuses a layer within reach of the workspace, a writable directory or a
cache, and every move goes through an os.Root on the layer and keeps no symlink. Only
LayerCaches (the build cache) are layered; a module cache keeps its throwaway layer
(issue 1921).
This commit is contained in:
2026-10-29 01:04:20 +01:00
parent 62a50ebcf8
commit 979f2cd718
6 changed files with 180 additions and 50 deletions
+10 -2
View File
@@ -124,7 +124,7 @@ func TestIsolatedRunsEachCommandThroughBubblewrap(t *testing.T) {
if err := os.MkdirAll(shared, 0o700); err != nil {
t.Fatal(err)
}
layer := filepath.Join(root, "ws", "cachelayer")
layer := filepath.Join(root, "ws1.cachelayer")
var mu sync.Mutex
uppers := map[string]bool{}
gate := make(chan struct{})
@@ -141,7 +141,15 @@ func TestIsolatedRunsEachCommandThroughBubblewrap(t *testing.T) {
os.WriteFile(filepath.Join(up, "ab", args[len(args)-1]+"-d"), []byte("compiled"), 0o600)
return forgekey.Ran{}
}
run := Isolated(writer, Isolation{Workspace: filepath.Join(root, "ws"), Caches: []string{shared}, CacheLayer: layer})
// A symlink in the kept layer (none is ever kept; planted here) leads no move outside the layer: the kept directory
// replaces it, and the shared cache it points to stays unchanged.
if err := os.MkdirAll(keptLayer(layer, 0), 0o700); err != nil {
t.Fatal(err)
}
if err := os.Symlink(shared, filepath.Join(keptLayer(layer, 0), "ab")); err != nil {
t.Fatal(err)
}
run := Isolated(writer, Isolation{Workspace: filepath.Join(root, "ws1"), Caches: []string{shared}, CacheLayer: layer, LayerCaches: []string{shared}})
var wg sync.WaitGroup
for _, pkg := range []string{"one", "two"} {
wg.Add(1)