Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions pkg/csi/materializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"encoding/json"
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
"sort"
Expand Down Expand Up @@ -201,6 +202,9 @@ func (m *Materializer) materialize(d digest.Digest) error {
m.logf("materializing %s failed after %s: %v", d, time.Since(start).Round(time.Millisecond), err)
return fmt.Errorf("pull %s: %w", d, err)
}
if err := readableByAll(tmp); err != nil {
return err
}
if err := os.Rename(tmp, dir); err != nil {
if isDir(dir) { // published by someone else meanwhile; same content
return nil
Expand Down Expand Up @@ -401,3 +405,30 @@ func (m *Materializer) busy(d digest.Digest) bool {
n, err := m.users(d)
return err != nil || n > 0
}

// readableByAll lets every user read the files of an artifact and list its directories (#62).
// The plugin runs as root and keeps each file's mode from the manifest, so a 0600 file would be
// unreadable for an engine that runs as another user; the volume is a read-only bind, so reading
// is all a pod gets.
func readableByAll(root string) error {
return filepath.WalkDir(root, func(p string, e fs.DirEntry, err error) error {
if err != nil {
return err
}
if e.Type()&fs.ModeSymlink != 0 {
return nil
}
fi, err := e.Info()
if err != nil {
return err
}
want := fi.Mode().Perm() | 0o444
if e.IsDir() {
want |= 0o111
}
if want == fi.Mode().Perm() {
return nil
}
return os.Chmod(p, want)
})
}
40 changes: 40 additions & 0 deletions pkg/csi/materializer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"context"
"errors"
"io/fs"
"math/rand"
"os"
"path/filepath"
Expand Down Expand Up @@ -291,3 +292,42 @@ func TestLeases(t *testing.T) {
}
sameTree(t, f.srcA, dir)
}

// Files stored with mode 0600 become readable by everyone once materialized (#62).
func TestMaterializedFilesAreReadableByAll(t *testing.T) {
ctx := context.Background()
f := newFixture(t)
src := t.TempDir()
if err := os.WriteFile(filepath.Join(src, "model-00001.safetensors"), random(5, 1<<20), 0o600); err != nil {
t.Fatal(err)
}
if err := os.MkdirAll(filepath.Join(src, "private"), 0o700); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(src, "private", "params.bin"), random(6, 4096), 0o600); err != nil {
t.Fatal(err)
}
d, _, err := f.s.Push(ctx, src, store.PushOptions{})
if err != nil {
t.Fatal(err)
}
m, _ := newMaterializer(t, f)
dir, err := m.Ensure(ctx, d)
if err != nil {
t.Fatal(err)
}
sameTree(t, src, dir)
for _, p := range []string{"model-00001.safetensors", "private", "private/params.bin"} {
fi, err := os.Stat(filepath.Join(dir, p))
if err != nil {
t.Fatal(err)
}
want := fs.FileMode(0o444)
if fi.IsDir() {
want = 0o555
}
if fi.Mode().Perm()&want != want {
t.Errorf("%s: mode %v, want at least %v", p, fi.Mode().Perm(), want)
}
}
}
Loading