]> Cypherpunks repositories - gostls13.git/commitdiff
internal/syscall/windows: add NtCreateFile
authorDamien Neil <dneil@google.com>
Fri, 4 Oct 2024 21:23:54 +0000 (14:23 -0700)
committerQuim Muntal <quimmuntal@gmail.com>
Mon, 7 Oct 2024 18:34:43 +0000 (18:34 +0000)
Mostly copied from x/sys/windows.

This adds a various related types and functions,
but the purpose is to give access to NtCreateFile,
which can be used as an equivalent to openat.

For #67002

Change-Id: I04e6f630445a55c2000c9c323ce8dcdc7fc0d0e0
Reviewed-on: https://go-review.googlesource.com/c/go/+/617377
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
src/internal/syscall/windows/string_windows.go [new file with mode: 0644]
src/internal/syscall/windows/syscall_windows.go
src/internal/syscall/windows/types_windows.go
src/internal/syscall/windows/zsyscall_windows.go

diff --git a/src/internal/syscall/windows/string_windows.go b/src/internal/syscall/windows/string_windows.go
new file mode 100644 (file)
index 0000000..eb6893d
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package windows
+
+import "syscall"
+
+// NTUnicodeString is a UTF-16 string for NT native APIs, corresponding to UNICODE_STRING.
+type NTUnicodeString struct {
+       Length        uint16
+       MaximumLength uint16
+       Buffer        *uint16
+}
+
+// NewNTUnicodeString returns a new NTUnicodeString structure for use with native
+// NT APIs that work over the NTUnicodeString type. Note that most Windows APIs
+// do not use NTUnicodeString, and instead UTF16PtrFromString should be used for
+// the more common *uint16 string type.
+func NewNTUnicodeString(s string) (*NTUnicodeString, error) {
+       s16, err := syscall.UTF16FromString(s)
+       if err != nil {
+               return nil, err
+       }
+       n := uint16(len(s16) * 2)
+       // https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdmsec/nf-wdmsec-wdmlibrtlinitunicodestringex
+       return &NTUnicodeString{
+               Length:        n - 2, // subtract 2 bytes for the NUL terminator
+               MaximumLength: n,
+               Buffer:        &s16[0],
+       }, nil
+}
index b8168678c3c361101ed2e9a96893ae67b28cf087..2849376dd1947c71291238214b1965816d0908c6 100644 (file)
@@ -502,3 +502,21 @@ func QueryPerformanceCounter() int64 // Implemented in runtime package.
 func QueryPerformanceFrequency() int64 // Implemented in runtime package.
 
 //sys   GetModuleHandle(modulename *uint16) (handle syscall.Handle, err error) = kernel32.GetModuleHandleW
+
+// NTStatus corresponds with NTSTATUS, error values returned by ntdll.dll and
+// other native functions.
+type NTStatus uint32
+
+func (s NTStatus) Errno() syscall.Errno {
+       return rtlNtStatusToDosErrorNoTeb(s)
+}
+
+func langID(pri, sub uint16) uint32 { return uint32(sub)<<10 | uint32(pri) }
+
+func (s NTStatus) Error() string {
+       return s.Errno().Error()
+}
+
+// NT Native APIs
+//sys   NtCreateFile(handle *syscall.Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, allocationSize *int64, attributes uint32, share uint32, disposition uint32, options uint32, eabuffer uintptr, ealength uint32) (ntstatus error) = ntdll.NtCreateFile
+//sys   rtlNtStatusToDosErrorNoTeb(ntstatus NTStatus) (ret syscall.Errno) = ntdll.RtlNtStatusToDosErrorNoTeb
index 126e07b8834cab5db864a8e4b247d4d5df283bbf..0421c3a35a1700bd1294023dee57d847abbc0930 100644 (file)
@@ -4,9 +4,175 @@
 
 package windows
 
+import "syscall"
+
 // Socket related.
 const (
        TCP_KEEPIDLE  = 0x03
        TCP_KEEPCNT   = 0x10
        TCP_KEEPINTVL = 0x11
 )
+
+const (
+       FILE_READ_DATA        = 0x00000001
+       FILE_READ_ATTRIBUTES  = 0x00000080
+       FILE_READ_EA          = 0x00000008
+       FILE_WRITE_DATA       = 0x00000002
+       FILE_WRITE_ATTRIBUTES = 0x00000100
+       FILE_WRITE_EA         = 0x00000010
+       FILE_APPEND_DATA      = 0x00000004
+       FILE_EXECUTE          = 0x00000020
+
+       FILE_GENERIC_READ    = STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE
+       FILE_GENERIC_WRITE   = STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE
+       FILE_GENERIC_EXECUTE = STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE
+
+       FILE_LIST_DIRECTORY = 0x00000001
+       FILE_TRAVERSE       = 0x00000020
+
+       FILE_SHARE_READ                      = 0x00000001
+       FILE_SHARE_WRITE                     = 0x00000002
+       FILE_SHARE_DELETE                    = 0x00000004
+       FILE_ATTRIBUTE_READONLY              = 0x00000001
+       FILE_ATTRIBUTE_HIDDEN                = 0x00000002
+       FILE_ATTRIBUTE_SYSTEM                = 0x00000004
+       FILE_ATTRIBUTE_DIRECTORY             = 0x00000010
+       FILE_ATTRIBUTE_ARCHIVE               = 0x00000020
+       FILE_ATTRIBUTE_DEVICE                = 0x00000040
+       FILE_ATTRIBUTE_NORMAL                = 0x00000080
+       FILE_ATTRIBUTE_TEMPORARY             = 0x00000100
+       FILE_ATTRIBUTE_SPARSE_FILE           = 0x00000200
+       FILE_ATTRIBUTE_REPARSE_POINT         = 0x00000400
+       FILE_ATTRIBUTE_COMPRESSED            = 0x00000800
+       FILE_ATTRIBUTE_OFFLINE               = 0x00001000
+       FILE_ATTRIBUTE_NOT_CONTENT_INDEXED   = 0x00002000
+       FILE_ATTRIBUTE_ENCRYPTED             = 0x00004000
+       FILE_ATTRIBUTE_INTEGRITY_STREAM      = 0x00008000
+       FILE_ATTRIBUTE_VIRTUAL               = 0x00010000
+       FILE_ATTRIBUTE_NO_SCRUB_DATA         = 0x00020000
+       FILE_ATTRIBUTE_RECALL_ON_OPEN        = 0x00040000
+       FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS = 0x00400000
+
+       INVALID_FILE_ATTRIBUTES = 0xffffffff
+)
+
+// https://learn.microsoft.com/en-us/windows/win32/secauthz/access-mask
+type ACCESS_MASK uint32
+
+// Constants for type ACCESS_MASK
+const (
+       DELETE                   = 0x00010000
+       READ_CONTROL             = 0x00020000
+       WRITE_DAC                = 0x00040000
+       WRITE_OWNER              = 0x00080000
+       SYNCHRONIZE              = 0x00100000
+       STANDARD_RIGHTS_REQUIRED = 0x000F0000
+       STANDARD_RIGHTS_READ     = READ_CONTROL
+       STANDARD_RIGHTS_WRITE    = READ_CONTROL
+       STANDARD_RIGHTS_EXECUTE  = READ_CONTROL
+       STANDARD_RIGHTS_ALL      = 0x001F0000
+       SPECIFIC_RIGHTS_ALL      = 0x0000FFFF
+       ACCESS_SYSTEM_SECURITY   = 0x01000000
+       MAXIMUM_ALLOWED          = 0x02000000
+       GENERIC_READ             = 0x80000000
+       GENERIC_WRITE            = 0x40000000
+       GENERIC_EXECUTE          = 0x20000000
+       GENERIC_ALL              = 0x10000000
+)
+
+// https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_acl
+type ACL struct {
+       AclRevision byte
+       Sbz1        byte
+       AclSize     uint16
+       AceCount    uint16
+       Sbz2        uint16
+}
+
+// https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_io_status_block
+type IO_STATUS_BLOCK struct {
+       Status      NTStatus
+       Information uintptr
+}
+
+// https://learn.microsoft.com/en-us/windows/win32/api/ntdef/ns-ntdef-_object_attributes
+type OBJECT_ATTRIBUTES struct {
+       Length             uint32
+       RootDirectory      syscall.Handle
+       ObjectName         *NTUnicodeString
+       Attributes         uint32
+       SecurityDescriptor *SECURITY_DESCRIPTOR
+       SecurityQoS        *SECURITY_QUALITY_OF_SERVICE
+}
+
+// Values for the Attributes member of OBJECT_ATTRIBUTES.
+const (
+       OBJ_INHERIT                       = 0x00000002
+       OBJ_PERMANENT                     = 0x00000010
+       OBJ_EXCLUSIVE                     = 0x00000020
+       OBJ_CASE_INSENSITIVE              = 0x00000040
+       OBJ_OPENIF                        = 0x00000080
+       OBJ_OPENLINK                      = 0x00000100
+       OBJ_KERNEL_HANDLE                 = 0x00000200
+       OBJ_FORCE_ACCESS_CHECK            = 0x00000400
+       OBJ_IGNORE_IMPERSONATED_DEVICEMAP = 0x00000800
+       OBJ_DONT_REPARSE                  = 0x00001000
+       OBJ_VALID_ATTRIBUTES              = 0x00001FF2
+)
+
+// https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_security_descriptor
+type SECURITY_DESCRIPTOR struct {
+       revision byte
+       sbz1     byte
+       control  SECURITY_DESCRIPTOR_CONTROL
+       owner    *syscall.SID
+       group    *syscall.SID
+       sacl     *ACL
+       dacl     *ACL
+}
+
+// https://learn.microsoft.com/en-us/windows-hardware/drivers/ifs/security-descriptor-control
+type SECURITY_DESCRIPTOR_CONTROL uint16
+
+// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-security_quality_of_service
+type SECURITY_QUALITY_OF_SERVICE struct {
+       Length              uint32
+       ImpersonationLevel  uint32 // type SECURITY_IMPERSONATION_LEVEL
+       ContextTrackingMode byte   // type SECURITY_CONTEXT_TRACKING_MODE
+       EffectiveOnly       byte
+}
+
+const (
+       // CreateDisposition flags for NtCreateFile and NtCreateNamedPipeFile.
+       FILE_SUPERSEDE           = 0x00000000
+       FILE_OPEN                = 0x00000001
+       FILE_CREATE              = 0x00000002
+       FILE_OPEN_IF             = 0x00000003
+       FILE_OVERWRITE           = 0x00000004
+       FILE_OVERWRITE_IF        = 0x00000005
+       FILE_MAXIMUM_DISPOSITION = 0x00000005
+
+       // CreateOptions flags for NtCreateFile and NtCreateNamedPipeFile.
+       FILE_DIRECTORY_FILE            = 0x00000001
+       FILE_WRITE_THROUGH             = 0x00000002
+       FILE_SEQUENTIAL_ONLY           = 0x00000004
+       FILE_NO_INTERMEDIATE_BUFFERING = 0x00000008
+       FILE_SYNCHRONOUS_IO_ALERT      = 0x00000010
+       FILE_SYNCHRONOUS_IO_NONALERT   = 0x00000020
+       FILE_NON_DIRECTORY_FILE        = 0x00000040
+       FILE_CREATE_TREE_CONNECTION    = 0x00000080
+       FILE_COMPLETE_IF_OPLOCKED      = 0x00000100
+       FILE_NO_EA_KNOWLEDGE           = 0x00000200
+       FILE_OPEN_REMOTE_INSTANCE      = 0x00000400
+       FILE_RANDOM_ACCESS             = 0x00000800
+       FILE_DELETE_ON_CLOSE           = 0x00001000
+       FILE_OPEN_BY_FILE_ID           = 0x00002000
+       FILE_OPEN_FOR_BACKUP_INTENT    = 0x00004000
+       FILE_NO_COMPRESSION            = 0x00008000
+       FILE_OPEN_REQUIRING_OPLOCK     = 0x00010000
+       FILE_DISALLOW_EXCLUSIVE        = 0x00020000
+       FILE_RESERVE_OPFILTER          = 0x00100000
+       FILE_OPEN_REPARSE_POINT        = 0x00200000
+       FILE_OPEN_NO_RECALL            = 0x00400000
+       FILE_OPEN_FOR_FREE_SPACE_QUERY = 0x00800000
+)
index 07627bb6caf905a5c221c325744af32333a2f3ed..711ebd679a27e7e91dedad118411a118f0e921c3 100644 (file)
@@ -88,7 +88,9 @@ var (
        procNetUserAdd                        = modnetapi32.NewProc("NetUserAdd")
        procNetUserDel                        = modnetapi32.NewProc("NetUserDel")
        procNetUserGetLocalGroups             = modnetapi32.NewProc("NetUserGetLocalGroups")
+       procNtCreateFile                      = modntdll.NewProc("NtCreateFile")
        procRtlGetVersion                     = modntdll.NewProc("RtlGetVersion")
+       procRtlNtStatusToDosErrorNoTeb        = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb")
        procGetProcessMemoryInfo              = modpsapi.NewProc("GetProcessMemoryInfo")
        procCreateEnvironmentBlock            = moduserenv.NewProc("CreateEnvironmentBlock")
        procDestroyEnvironmentBlock           = moduserenv.NewProc("DestroyEnvironmentBlock")
@@ -439,11 +441,25 @@ func NetUserGetLocalGroups(serverName *uint16, userName *uint16, level uint32, f
        return
 }
 
+func NtCreateFile(handle *syscall.Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, allocationSize *int64, attributes uint32, share uint32, disposition uint32, options uint32, eabuffer uintptr, ealength uint32) (ntstatus error) {
+       r0, _, _ := syscall.Syscall12(procNtCreateFile.Addr(), 11, uintptr(unsafe.Pointer(handle)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(unsafe.Pointer(allocationSize)), uintptr(attributes), uintptr(share), uintptr(disposition), uintptr(options), uintptr(eabuffer), uintptr(ealength), 0)
+       if r0 != 0 {
+               ntstatus = NTStatus(r0)
+       }
+       return
+}
+
 func rtlGetVersion(info *_OSVERSIONINFOW) {
        syscall.Syscall(procRtlGetVersion.Addr(), 1, uintptr(unsafe.Pointer(info)), 0, 0)
        return
 }
 
+func rtlNtStatusToDosErrorNoTeb(ntstatus NTStatus) (ret syscall.Errno) {
+       r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(ntstatus), 0, 0)
+       ret = syscall.Errno(r0)
+       return
+}
+
 func GetProcessMemoryInfo(handle syscall.Handle, memCounters *PROCESS_MEMORY_COUNTERS, cb uint32) (err error) {
        r1, _, e1 := syscall.Syscall(procGetProcessMemoryInfo.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(memCounters)), uintptr(cb))
        if r1 == 0 {