//go:build windows && admin // +build windows,admin package safefile import ( "os" "path/filepath" "syscall" "testing" "github.com/Microsoft/hcsshim/internal/winapi" ) func TestOpenRelative(t *testing.T) { badroot, err := tempRoot(t) if err != nil { t.Fatal(err) } root, err := tempRoot(t) if err != nil { t.Fatal(err) } // Create a file f, err := OpenRelative("foo", root, 0, syscall.FILE_SHARE_READ, winapi.FILE_CREATE, 0) if err != nil { t.Fatal(err) } f.Close() // Create a directory err = MkdirRelative("dir", root) if err != nil { t.Fatal(err) } // Create a directory stack err = MkdirAllRelative("dir/and/then/some/subdir", root) if err != nil { t.Fatal(err) } // Create a file in the bad root f, err = os.Create(filepath.Join(badroot.Name(), "badfile")) if err != nil { t.Fatal(err) } f.Close() // Create a directory symlink to the bad root err = os.Symlink(badroot.Name(), filepath.Join(root.Name(), "dsymlink")) if err != nil { t.Fatal(err) } // Create a file symlink to the bad file err = os.Symlink(filepath.Join(badroot.Name(), "badfile"), filepath.Join(root.Name(), "symlink")) if err != nil { t.Fatal(err) } // Make sure opens cannot happen through the symlink f, err = OpenRelative("dsymlink/foo", root, 0, syscall.FILE_SHARE_READ, winapi.FILE_CREATE, 0) if err == nil { f.Close() t.Fatal("created file in wrong tree!") } t.Log(err) // Make sure directory stacks cannot pass through a symlink err = MkdirAllRelative("dsymlink/and/then/some/subdir", root) if err == nil { t.Fatal("created a directory tree through a symlink") } t.Log(err) // Check again using EnsureNotReparsePointRelative err = EnsureNotReparsePointRelative("dsymlink", root) if err == nil { t.Fatal("reparse check should have failed") } t.Log(err) // Make sure links work err = LinkRelative("foo", root, "hardlink", root) if err != nil { t.Fatal(err) } // Even inside directories err = LinkRelative("foo", root, "dir/bar", root) if err != nil { t.Fatal(err) } // Make sure links cannot happen through the symlink err = LinkRelative("foo", root, "dsymlink/hardlink", root) if err == nil { f.Close() t.Fatal("created link in wrong tree!") } t.Log(err) // In either direction err = LinkRelative("dsymlink/badfile", root, "bar", root) if err == nil { f.Close() t.Fatal("created link in wrong tree!") } t.Log(err) // Make sure remove cannot happen through the symlink err = RemoveRelative("symlink/badfile", root) if err == nil { t.Fatal("remove in wrong tree!") } // Remove the symlink err = RemoveAllRelative("symlink", root) if err != nil { t.Fatal(err) } // Make sure it's not possible to escape with .. (NT doesn't support .. at the kernel level) f, err = OpenRelative("..", root, syscall.GENERIC_READ, syscall.FILE_SHARE_READ, winapi.FILE_OPEN, 0) if err == nil { f.Close() t.Fatal("escaped the directory") } t.Log(err) // Should not have touched the other directory if _, err = os.Lstat(filepath.Join(badroot.Name(), "badfile")); err != nil { t.Fatal(err) } }