diff --git a/src/runtime/export_windows_test.go b/src/runtime/export_windows_test.go index d9cf753463940..d4b1e1fad32e4 100644 --- a/src/runtime/export_windows_test.go +++ b/src/runtime/export_windows_test.go @@ -21,7 +21,3 @@ func NumberOfProcessors() int32 { stdcall1(_GetSystemInfo, uintptr(unsafe.Pointer(&info))) return int32(info.dwnumberofprocessors) } - -func LoadLibraryExStatus() (useEx, haveEx, haveFlags bool) { - return useLoadLibraryEx, _LoadLibraryExW != nil, _AddDllDirectory != nil -} diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index 60741f321ffb6..62be6350bddf5 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -37,8 +37,8 @@ const ( //go:cgo_import_dynamic runtime._GetSystemInfo GetSystemInfo%1 "kernel32.dll" //go:cgo_import_dynamic runtime._GetThreadContext GetThreadContext%2 "kernel32.dll" //go:cgo_import_dynamic runtime._SetThreadContext SetThreadContext%2 "kernel32.dll" +//go:cgo_import_dynamic runtime._LoadLibraryExW LoadLibraryExW%3 "kernel32.dll" //go:cgo_import_dynamic runtime._LoadLibraryW LoadLibraryW%1 "kernel32.dll" -//go:cgo_import_dynamic runtime._LoadLibraryA LoadLibraryA%1 "kernel32.dll" //go:cgo_import_dynamic runtime._PostQueuedCompletionStatus PostQueuedCompletionStatus%4 "kernel32.dll" //go:cgo_import_dynamic runtime._ResumeThread ResumeThread%1 "kernel32.dll" //go:cgo_import_dynamic runtime._SetConsoleCtrlHandler SetConsoleCtrlHandler%2 "kernel32.dll" @@ -88,8 +88,8 @@ var ( _GetSystemTimeAsFileTime, _GetThreadContext, _SetThreadContext, + _LoadLibraryExW, _LoadLibraryW, - _LoadLibraryA, _PostQueuedCompletionStatus, _QueryPerformanceCounter, _QueryPerformanceFrequency, @@ -116,10 +116,7 @@ var ( // Following syscalls are only available on some Windows PCs. // We will load syscalls, if available, before using them. - _AddDllDirectory, _AddVectoredContinueHandler, - _LoadLibraryExA, - _LoadLibraryExW, _ stdFunction // Use RtlGenRandom to generate cryptographically random data. @@ -146,6 +143,15 @@ var ( _ stdFunction ) +var ( + advapi32dll = [...]uint16{'a', 'd', 'v', 'a', 'p', 'i', '3', '2', '.', 'd', 'l', 'l', 0} + kernel32dll = [...]uint16{'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0} + ntdlldll = [...]uint16{'n', 't', 'd', 'l', 'l', '.', 'd', 'l', 'l', 0} + powrprofdll = [...]uint16{'p', 'o', 'w', 'r', 'p', 'r', 'o', 'f', '.', 'd', 'l', 'l', 0} + winmmdll = [...]uint16{'w', 'i', 'n', 'm', 'm', '.', 'd', 'l', 'l', 0} + ws2_32dll = [...]uint16{'w', 's', '2', '_', '3', '2', '.', 'd', 'l', 'l', 0} +) + // Function to be called by windows CreateThread // to start new os thread. func tstart_stdcall(newm *m) @@ -225,46 +231,35 @@ const _MAX_PATH = 260 // https://docs.microsoft.com/en-us/windows/win32/fileio/m var sysDirectory [_MAX_PATH + 1]byte var sysDirectoryLen uintptr -func windowsLoadSystemLib(name []byte) uintptr { - if sysDirectoryLen == 0 { - l := stdcall2(_GetSystemDirectoryA, uintptr(unsafe.Pointer(&sysDirectory[0])), uintptr(len(sysDirectory)-1)) - if l == 0 || l > uintptr(len(sysDirectory)-1) { - throw("Unable to determine system directory") - } - sysDirectory[l] = '\\' - sysDirectoryLen = l + 1 - } - if useLoadLibraryEx { - return stdcall3(_LoadLibraryExA, uintptr(unsafe.Pointer(&name[0])), 0, _LOAD_LIBRARY_SEARCH_SYSTEM32) - } else { - absName := append(sysDirectory[:sysDirectoryLen], name...) - return stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&absName[0]))) +func initSysDirectory() { + l := stdcall2(_GetSystemDirectoryA, uintptr(unsafe.Pointer(&sysDirectory[0])), uintptr(len(sysDirectory)-1)) + if l == 0 || l > uintptr(len(sysDirectory)-1) { + throw("Unable to determine system directory") } + sysDirectory[l] = '\\' + sysDirectoryLen = l + 1 +} + +func windowsLoadSystemLib(name []uint16) uintptr { + return stdcall3(_LoadLibraryExW, uintptr(unsafe.Pointer(&name[0])), 0, _LOAD_LIBRARY_SEARCH_SYSTEM32) } const haveCputicksAsm = GOARCH == "386" || GOARCH == "amd64" func loadOptionalSyscalls() { - var kernel32dll = []byte("kernel32.dll\000") - k32 := stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&kernel32dll[0]))) + k32 := windowsLoadSystemLib(kernel32dll[:]) if k32 == 0 { throw("kernel32.dll not found") } - _AddDllDirectory = windowsFindfunc(k32, []byte("AddDllDirectory\000")) _AddVectoredContinueHandler = windowsFindfunc(k32, []byte("AddVectoredContinueHandler\000")) - _LoadLibraryExA = windowsFindfunc(k32, []byte("LoadLibraryExA\000")) - _LoadLibraryExW = windowsFindfunc(k32, []byte("LoadLibraryExW\000")) - useLoadLibraryEx = (_LoadLibraryExW != nil && _LoadLibraryExA != nil && _AddDllDirectory != nil) - var advapi32dll = []byte("advapi32.dll\000") - a32 := windowsLoadSystemLib(advapi32dll) + a32 := windowsLoadSystemLib(advapi32dll[:]) if a32 == 0 { throw("advapi32.dll not found") } _RtlGenRandom = windowsFindfunc(a32, []byte("SystemFunction036\000")) - var ntdll = []byte("ntdll.dll\000") - n32 := windowsLoadSystemLib(ntdll) + n32 := windowsLoadSystemLib(ntdlldll[:]) if n32 == 0 { throw("ntdll.dll not found") } @@ -279,8 +274,7 @@ func loadOptionalSyscalls() { } } - var winmmdll = []byte("winmm.dll\000") - m32 := windowsLoadSystemLib(winmmdll) + m32 := windowsLoadSystemLib(winmmdll[:]) if m32 == 0 { throw("winmm.dll not found") } @@ -290,8 +284,7 @@ func loadOptionalSyscalls() { throw("timeBegin/EndPeriod not found") } - var ws232dll = []byte("ws2_32.dll\000") - ws232 := windowsLoadSystemLib(ws232dll) + ws232 := windowsLoadSystemLib(ws2_32dll[:]) if ws232 == 0 { throw("ws2_32.dll not found") } @@ -315,7 +308,7 @@ func monitorSuspendResume() { context uintptr } - powrprof := windowsLoadSystemLib([]byte("powrprof.dll\000")) + powrprof := windowsLoadSystemLib(powrprofdll[:]) if powrprof == 0 { return // Running on Windows 7, where we don't need it anyway. } @@ -389,22 +382,6 @@ const ( // in sys_windows_386.s and sys_windows_amd64.s: func getlasterror() uint32 -// When loading DLLs, we prefer to use LoadLibraryEx with -// LOAD_LIBRARY_SEARCH_* flags, if available. LoadLibraryEx is not -// available on old Windows, though, and the LOAD_LIBRARY_SEARCH_* -// flags are not available on some versions of Windows without a -// security patch. -// -// https://msdn.microsoft.com/en-us/library/ms684179(v=vs.85).aspx says: -// "Windows 7, Windows Server 2008 R2, Windows Vista, and Windows -// Server 2008: The LOAD_LIBRARY_SEARCH_* flags are available on -// systems that have KB2533623 installed. To determine whether the -// flags are available, use GetProcAddress to get the address of the -// AddDllDirectory, RemoveDllDirectory, or SetDefaultDllDirectories -// function. If GetProcAddress succeeds, the LOAD_LIBRARY_SEARCH_* -// flags can be used with LoadLibraryEx." -var useLoadLibraryEx bool - var timeBeginPeriodRetValue uint32 // osRelaxMinNS indicates that sysmon shouldn't osRelax if the next @@ -555,6 +532,7 @@ func osinit() { initHighResTimer() timeBeginPeriodRetValue = osRelax(false) + initSysDirectory() initLongPathSupport() ncpu = getproccount() diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go index 76036ad098e37..947f68510c1af 100644 --- a/src/runtime/syscall_windows.go +++ b/src/runtime/syscall_windows.go @@ -413,36 +413,23 @@ func callbackWrap(a *callbackArgs) { const _LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800 -// When available, this function will use LoadLibraryEx with the filename -// parameter and the important SEARCH_SYSTEM32 argument. But on systems that -// do not have that option, absoluteFilepath should contain a fallback -// to the full path inside of system32 for use with vanilla LoadLibrary. -// //go:linkname syscall_loadsystemlibrary syscall.loadsystemlibrary //go:nosplit //go:cgo_unsafe_args -func syscall_loadsystemlibrary(filename *uint16, absoluteFilepath *uint16) (handle, err uintptr) { +func syscall_loadsystemlibrary(filename *uint16) (handle, err uintptr) { lockOSThread() c := &getg().m.syscall - - if useLoadLibraryEx { - c.fn = getLoadLibraryEx() - c.n = 3 - args := struct { - lpFileName *uint16 - hFile uintptr // always 0 - flags uint32 - }{filename, 0, _LOAD_LIBRARY_SEARCH_SYSTEM32} - c.args = uintptr(noescape(unsafe.Pointer(&args))) - } else { - c.fn = getLoadLibrary() - c.n = 1 - c.args = uintptr(noescape(unsafe.Pointer(&absoluteFilepath))) - } + c.fn = getLoadLibraryEx() + c.n = 3 + args := struct { + lpFileName *uint16 + hFile uintptr // always 0 + flags uint32 + }{filename, 0, _LOAD_LIBRARY_SEARCH_SYSTEM32} + c.args = uintptr(noescape(unsafe.Pointer(&args))) cgocall(asmstdcallAddr, unsafe.Pointer(c)) KeepAlive(filename) - KeepAlive(absoluteFilepath) handle = c.r1 if handle == 0 { err = c.err diff --git a/src/runtime/syscall_windows_test.go b/src/runtime/syscall_windows_test.go index abc28387e605e..b49da32384145 100644 --- a/src/runtime/syscall_windows_test.go +++ b/src/runtime/syscall_windows_test.go @@ -1164,10 +1164,7 @@ uintptr_t cfunc(void) { dll, err = syscall.LoadDLL(name) if err == nil { dll.Release() - if wantLoadLibraryEx() { - t.Fatalf("Bad: insecure load of DLL by base name %q before sysdll registration: %v", name, err) - } - t.Skip("insecure load of DLL, but expected") + t.Fatalf("Bad: insecure load of DLL by base name %q before sysdll registration: %v", name, err) } } @@ -1213,24 +1210,6 @@ func TestBigStackCallbackSyscall(t *testing.T) { } } -// wantLoadLibraryEx reports whether we expect LoadLibraryEx to work for tests. -func wantLoadLibraryEx() bool { - return testenv.Builder() != "" && (runtime.GOARCH == "amd64" || runtime.GOARCH == "386") -} - -func TestLoadLibraryEx(t *testing.T) { - use, have, flags := runtime.LoadLibraryExStatus() - if use { - return // success. - } - if wantLoadLibraryEx() { - t.Fatalf("Expected LoadLibraryEx+flags to be available. (LoadLibraryEx=%v; flags=%v)", - have, flags) - } - t.Skipf("LoadLibraryEx not usable, but not expected. (LoadLibraryEx=%v; flags=%v)", - have, flags) -} - var ( modwinmm = syscall.NewLazyDLL("winmm.dll") modkernel32 = syscall.NewLazyDLL("kernel32.dll") diff --git a/src/syscall/dll_windows.go b/src/syscall/dll_windows.go index 34b481d6e6354..78c8b0169a4e8 100644 --- a/src/syscall/dll_windows.go +++ b/src/syscall/dll_windows.go @@ -44,7 +44,7 @@ func Syscall18(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a func SyscallN(trap uintptr, args ...uintptr) (r1, r2 uintptr, err Errno) func loadlibrary(filename *uint16) (handle uintptr, err Errno) -func loadsystemlibrary(filename *uint16, absoluteFilepath *uint16) (handle uintptr, err Errno) +func loadsystemlibrary(filename *uint16) (handle uintptr, err Errno) func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err Errno) // A DLL implements access to a single DLL. @@ -53,26 +53,6 @@ type DLL struct { Handle Handle } -// We use this for computing the absolute path for system DLLs on systems -// where SEARCH_SYSTEM32 is not available. -var systemDirectoryPrefix string - -func init() { - n := uint32(MAX_PATH) - for { - b := make([]uint16, n) - l, e := getSystemDirectory(&b[0], n) - if e != nil { - panic("Unable to determine system directory: " + e.Error()) - } - if l <= n { - systemDirectoryPrefix = UTF16ToString(b[:l]) + "\\" - break - } - n = l - } -} - // LoadDLL loads the named DLL file into memory. // // If name is not an absolute path and is not a known system DLL used by @@ -89,11 +69,7 @@ func LoadDLL(name string) (*DLL, error) { var h uintptr var e Errno if sysdll.IsSystemDLL[name] { - absoluteFilepathp, err := UTF16PtrFromString(systemDirectoryPrefix + name) - if err != nil { - return nil, err - } - h, e = loadsystemlibrary(namep, absoluteFilepathp) + h, e = loadsystemlibrary(namep) } else { h, e = loadlibrary(namep) } diff --git a/src/syscall/security_windows.go b/src/syscall/security_windows.go index 67102b69297ac..00dc920974456 100644 --- a/src/syscall/security_windows.go +++ b/src/syscall/security_windows.go @@ -290,7 +290,6 @@ type Tokenprimarygroup struct { //sys OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken //sys GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation //sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW -//sys getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW // An access token contains the security information for a logon session. // The system creates an access token when a user logs on, and every diff --git a/src/syscall/zsyscall_windows.go b/src/syscall/zsyscall_windows.go index 61d89f146048c..9190ec8b20f2f 100644 --- a/src/syscall/zsyscall_windows.go +++ b/src/syscall/zsyscall_windows.go @@ -866,15 +866,6 @@ func GetStdHandle(stdhandle int) (handle Handle, err error) { return } -func getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { - r0, _, e1 := Syscall(procGetSystemDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0) - len = uint32(r0) - if len == 0 { - err = errnoErr(e1) - } - return -} - func GetSystemTimeAsFileTime(time *Filetime) { Syscall(procGetSystemTimeAsFileTime.Addr(), 1, uintptr(unsafe.Pointer(time)), 0, 0) return