fix(safeio): retain private file parent handles

This commit is contained in:
2026-08-18 08:51:59 +02:00
parent 0b77d1e850
commit e7a7f4f066
11 changed files with 359 additions and 212 deletions
@@ -159,3 +159,65 @@ func TestPrivateDirectoryCreationUsesThePinnedParentAfterAncestorSwap(t *testing
})
}
}
func TestCreateCanonicalNewPrivateFileUsesPinnedParentAfterAncestorSwap(t *testing.T) {
temporaryRoot, err := filepath.EvalSymlinks(os.TempDir())
if err != nil {
t.Fatal(err)
}
root, err := os.MkdirTemp(temporaryRoot, "tht-safeio-private-file-openat-")
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { _ = os.RemoveAll(root) })
parent := filepath.Join(root, "parent")
if err := os.Mkdir(parent, 0o700); err != nil {
t.Fatal(err)
}
if err := ProtectPrivateDirectory(parent); err != nil {
t.Fatal(err)
}
outside := filepath.Join(root, "outside")
if err := os.Mkdir(outside, 0o700); err != nil {
t.Fatal(err)
}
path := filepath.Join(parent, "archive.zip")
movedParent := parent + "-original"
swapped := false
restoreHook := SetPrivateDirectoryTestHookForTest(func(stage string) {
if stage != "after-canonical-private-file-parent-open" || swapped {
return
}
if err := os.Rename(parent, movedParent); err != nil {
t.Fatal(err)
}
if err := os.Symlink(outside, parent); err != nil {
t.Fatal(err)
}
swapped = true
})
t.Cleanup(restoreHook)
file, err := CreateCanonicalNewPrivateFile(path)
if err != nil {
t.Fatal(err)
}
if _, err := file.Write([]byte("staged")); err != nil {
_ = file.Close()
t.Fatal(err)
}
if err := file.Close(); err != nil {
t.Fatal(err)
}
if !swapped {
t.Fatal("private file creator did not retain the parent before creation")
}
created := filepath.Join(movedParent, "archive.zip")
if err := ValidatePrivateRegular(created); err != nil {
t.Fatalf("pinned-parent private file validation = %v", err)
}
if _, err := os.Lstat(filepath.Join(outside, "archive.zip")); !errors.Is(err, os.ErrNotExist) {
t.Fatalf("outside target was mutated: %v", err)
}
}