content: ensure root directory exists before checking fs-verity support

Currently, fs-verity support detection fails on fresh containerd
installations because the content store root directory
(io.containerd.content.v1.content) doesn't exist yet. This directory
is only created when pulling images, causing checker to
always be false on new hosts.

The IsSupported() function attempts to create a temporary directory
within rootPath to test fs-verity support, but fails when rootPath
doesn't exist, returning an error that is silently ignored.

Fix this by ensuring the root directory exists before performing
the fs-verity support check in NewLabeledStore().

Signed-off-by: ningmingxiao <ning.mingxiao@zte.com.cn>
This commit is contained in:
ningmingxiao
2025-10-26 22:39:28 +08:00
committed by Mike Brown
parent eb888dce45
commit 5f0f0dcaac
2 changed files with 53 additions and 5 deletions

View File

@@ -18,8 +18,10 @@ package local
import (
"context"
"errors"
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
"strconv"
@@ -84,8 +86,18 @@ func NewStore(root string) (content.Store, error) {
// require labels and should use `NewStore`. `NewLabeledStore` is primarily
// useful for tests or standalone implementations.
func NewLabeledStore(root string, ls LabelStore) (content.Store, error) {
supported, _ := fsverity.IsSupported(root)
if _, err := os.Stat(root); err != nil {
if !errors.Is(err, fs.ErrNotExist) {
return nil, fmt.Errorf("failed to stat %q: %w", root, err)
}
if err := os.MkdirAll(root, 0755); err != nil {
return nil, fmt.Errorf("failed to mkdir %q: %w", root, err)
}
}
supported, err := fsverity.IsSupported(root)
if err != nil {
log.L.WithError(err).WithField("path", root).Warnf("failed check for fsverity support")
}
s := &store{
root: root,
ls: ls,

View File

@@ -25,6 +25,7 @@ import (
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"reflect"
"runtime"
@@ -94,15 +95,50 @@ func (mls *memoryLabelStore) Update(d digest.Digest, update map[string]string) (
func TestContent(t *testing.T) {
testsuite.ContentSuite(t, "fs", func(ctx context.Context, root string) (context.Context, content.Store, func() error, error) {
cs, err := NewLabeledStore(root, newMemoryLabelStore())
if err != nil {
return nil, nil, nil, err
}
assert.NoError(t, err)
return ctx, cs, func() error {
return nil
}, nil
})
}
func TestContentRootDir(t *testing.T) {
// test dir exist
dirExist := t.TempDir()
_, err := NewLabeledStore(dirExist, newMemoryLabelStore())
assert.NoError(t, err)
// test dir doesn't exist
dir := filepath.Join(t.TempDir(), "test_dir001")
_, err = NewLabeledStore(dir, newMemoryLabelStore())
assert.NoError(t, err)
_, err = os.Stat(dir)
assert.NoError(t, err)
}
func TestInvalidPermissionRootDir(t *testing.T) {
// test dir permissions are invalid
if os.Getuid() != 0 {
t.Skip("skipping test that requires root")
}
_, err := exec.LookPath("chattr")
if err != nil {
t.Skip("skipping test that requires chattr command")
}
dirBadPermission := t.TempDir()
cmd := exec.Command("chattr", "+i", dirBadPermission)
_, err = cmd.CombinedOutput()
assert.NoError(t, err)
defer func() {
cmd := exec.Command("chattr", "-i", dirBadPermission)
_, err = cmd.CombinedOutput()
assert.NoError(t, err)
}()
_, err = fsverity.IsSupported(dirBadPermission)
if err == nil {
t.Fatal(fmt.Errorf("err can't be nil"))
}
}
func TestContentWriter(t *testing.T) {
ctx, tmpdir, cs, cleanup := contentStoreEnv(t)
defer cleanup()