diff --git a/docs/ISOLATION_OPERATION_LEASE_SECURITY.md b/docs/ISOLATION_OPERATION_LEASE_SECURITY.md index 16eb9d65d8..d24d70484d 100644 --- a/docs/ISOLATION_OPERATION_LEASE_SECURITY.md +++ b/docs/ISOLATION_OPERATION_LEASE_SECURITY.md @@ -39,9 +39,12 @@ The utility adds `AcquireRoot` and `TryAcquireRoot` for an `os.Root` plus a loca name. They reject nonlocal names and nonregular lock files, preserve file bytes and modes, and never reopen a filename by concatenating `Root.Name()`. -Relative opens follow the opened directory after a rename. Outside symlinks are -refused by `os.Root`. Closing the directory handle does not release an admitted -file lease. Existing path APIs keep their global-path and wait-budget contracts. +Relative child-directory opens follow the opened directory after a rename. +Windows may forbid renaming a directory opened directly with os.OpenRoot; +the result owner uses a child handle. Outside symlinks are refused by os.Root. + +Closing the directory handle does not release an admitted file lease. +Existing path APIs keep their global-path and wait-budget contracts. ## Lifecycle coverage diff --git a/internal/base/filelock/root_test.go b/internal/base/filelock/root_test.go index 19509624fc..d61cd7f67e 100644 --- a/internal/base/filelock/root_test.go +++ b/internal/base/filelock/root_test.go @@ -178,7 +178,13 @@ func TestRootedLockFollowsTheOpenedDirectoryAfterRename(t *testing.T) { if err := os.Mkdir(dir, 0o700); err != nil { t.Fatal(err) } - root, err := os.OpenRoot(dir) + parentRoot, err := os.OpenRoot(parent) + if err != nil { + t.Fatal(err) + } + defer parentRoot.Close() + // Match resultLockRoot: a relative child handle permits Windows rename. + root, err := parentRoot.OpenRoot("original") if err != nil { t.Fatal(err) }