fix(brainfs): refuse an in-brain file swapped in behind a symlink; in-brain test targets (#157)
Review round 1 on PR #168: - ReadRegular/ReadRegularMax Lstat the path, then open it again by path; os.Root follows an in-root final symlink even with O_NOFOLLOW, so a symlink to another brain file swapped in between was read (8k-109k raw/ leaks in RebuildIndex, LoadInventory, IndexDoc). The opened handle must now be the same file as the Lstat (os.SameFile). This covers every ReadRegular caller, slices 1-3 included. - Every symlink test pointed outside the brain, which os.Root refuses on its own. Each now has an in-brain case too: a static in-brain link per reader, AssertNoLeakFrom with an in-brain target, and brainfs unit tests for ReadDirRegular and the in-brain swap. - brainfstest: swap links are relative (os.Root refuses every absolute link, so an absolute in-brain target tested nothing), and each swapper has its own temp name (two swappers on one path deadlocked on each other's FIFO). - IndexDoc indexes only a clean wiki/ or knowledge/ path (callers pass caller-supplied paths). - Rule 9: TestLoadInventoryReturnsErrNotRegularForASymlinkedTypeDir now asserts the error; the backfill test says it aborts on a symlinked root. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,8 @@ import (
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/mathiasbq/hyperguild/ingestion/internal/brainfs"
|
||||
"github.com/mathiasbq/hyperguild/ingestion/internal/graph"
|
||||
@@ -48,6 +50,12 @@ func IndexDoc(ctx context.Context, store Store, brainDir, relPath string) error
|
||||
if relPath == "" {
|
||||
return nil
|
||||
}
|
||||
// Callers pass caller-supplied paths (brain_tunnel, brain_update): index
|
||||
// only a clean path under wiki/ or knowledge/.
|
||||
if path.Clean(relPath) != relPath || !filepath.IsLocal(relPath) ||
|
||||
(!strings.HasPrefix(relPath, "wiki/") && !strings.HasPrefix(relPath, "knowledge/")) {
|
||||
return fmt.Errorf("index %q: not a clean wiki/ or knowledge/ path", relPath)
|
||||
}
|
||||
bfs, err := brainfs.Open(brainDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open brain: %w", err)
|
||||
|
||||
Reference in New Issue
Block a user