fix(safeio): normalize NT relative access masks
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user