fix(safeio): normalize NT relative access masks

This commit is contained in:
2026-08-18 13:11:40 +02:00
parent 36592634bb
commit 81077e59d3
2 changed files with 31 additions and 4 deletions
@@ -178,6 +178,7 @@ func openWindowsRelativeObjectWithShareMode(
if parent == 0 || !validPrivateLeafName(name) {
return 0, ErrUnsafeFile
}
access = normalizeWindowsNTDesiredAccess(access)
objectName, err := windows.NewNTUnicodeString(name)
if err != nil {
return 0, ErrUnsafeFile
@@ -203,10 +204,8 @@ func openWindowsRelativeObjectWithShareMode(
attributes,
&status,
&allocationSize,
// NtCreateFile expects zero here for the retained open/create contract. The
// Win32 FILE_ATTRIBUTE_NORMAL flag is not a valid NT FileAttributes value
// for this RootDirectory-relative call and produces STATUS_INVALID_PARAMETER
// on the Windows runner.
// NtCreateFile supplies the normal attribute default when this is zero; no
// explicit creation attribute is needed for these retained open/create calls.
0,
shareMode,
disposition,
@@ -222,6 +221,24 @@ func openWindowsRelativeObjectWithShareMode(
return handle, nil
}
func normalizeWindowsNTDesiredAccess(access uint32) uint32 {
if access&uint32(windows.GENERIC_ALL) != 0 {
const fileSpecificAll = uint32(0x1ff)
access = access&^uint32(windows.GENERIC_ALL) |
uint32(windows.STANDARD_RIGHTS_REQUIRED|windows.SYNCHRONIZE) | fileSpecificAll
}
if access&uint32(windows.GENERIC_READ) != 0 {
access = access&^uint32(windows.GENERIC_READ) | uint32(windows.FILE_GENERIC_READ)
}
if access&uint32(windows.GENERIC_WRITE) != 0 {
access = access&^uint32(windows.GENERIC_WRITE) | uint32(windows.FILE_GENERIC_WRITE)
}
if access&uint32(windows.GENERIC_EXECUTE) != 0 {
access = access&^uint32(windows.GENERIC_EXECUTE) | uint32(windows.FILE_GENERIC_EXECUTE)
}
return access
}
func privateWindowsDirectoryInfo(handle windows.Handle) (windows.ByHandleFileInformation, error) {
var info windows.ByHandleFileInformation
if handle == 0 || windows.GetFileInformationByHandle(handle, &info) != nil ||
@@ -70,6 +70,16 @@ func TestOwnerOnlyDACLAcceptsWindowsFullControlMask(t *testing.T) {
}
}
func TestWindowsNTDesiredAccessMapsGenericBits(t *testing.T) {
if got, want := normalizeWindowsNTDesiredAccess(windows.GENERIC_READ), uint32(windows.FILE_GENERIC_READ); got != want {
t.Fatalf("normalized generic read access = %#x, want %#x", got, want)
}
want := uint32(windows.FILE_GENERIC_READ | windows.WRITE_DAC | windows.WRITE_OWNER)
if got := normalizeWindowsNTDesiredAccess(windows.GENERIC_READ | windows.WRITE_DAC | windows.WRITE_OWNER); got != want {
t.Fatalf("normalized protected read access = %#x, want %#x", got, want)
}
}
func TestOwnerOnlyDACLNativeShape(t *testing.T) {
directory := filepath.Join(t.TempDir(), "auth")
if err := os.Mkdir(directory, 0o700); err != nil {