Add patch files
This commit is contained in:
159
patches/0001-Switch-ProcessPrng-back-to-RtlGenRandom.patch
Normal file
159
patches/0001-Switch-ProcessPrng-back-to-RtlGenRandom.patch
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
From f1f146d4534fc925bceffe523852fe2261841008 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vorapol Rinsatitnon <vorapol.r@pm.me>
|
||||||
|
Date: Sat, 21 Sep 2024 23:56:11 +1000
|
||||||
|
Subject: [PATCH] Switch ProcessPrng back to RtlGenRandom (revert 693def1)
|
||||||
|
|
||||||
|
---
|
||||||
|
src/crypto/rand/rand.go | 2 +-
|
||||||
|
src/crypto/rand/rand_windows.go | 7 +++--
|
||||||
|
.../syscall/windows/syscall_windows.go | 2 +-
|
||||||
|
.../syscall/windows/zsyscall_windows.go | 7 ++---
|
||||||
|
src/runtime/os_windows.go | 30 ++++++++++++-------
|
||||||
|
5 files changed, 29 insertions(+), 19 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/crypto/rand/rand.go b/src/crypto/rand/rand.go
|
||||||
|
index d16d7a1..cdfeb06 100644
|
||||||
|
--- a/src/crypto/rand/rand.go
|
||||||
|
+++ b/src/crypto/rand/rand.go
|
||||||
|
@@ -16,7 +16,7 @@ import "io"
|
||||||
|
// - On macOS and iOS, Reader uses arc4random_buf(3).
|
||||||
|
// - On OpenBSD and NetBSD, Reader uses getentropy(2).
|
||||||
|
// - On other Unix-like systems, Reader reads from /dev/urandom.
|
||||||
|
-// - On Windows, Reader uses the ProcessPrng API.
|
||||||
|
+// - On Windows, Reader uses the RtlGenRandom API.
|
||||||
|
// - On js/wasm, Reader uses the Web Crypto API.
|
||||||
|
// - On wasip1/wasm, Reader uses random_get from wasi_snapshot_preview1.
|
||||||
|
var Reader io.Reader
|
||||||
|
diff --git a/src/crypto/rand/rand_windows.go b/src/crypto/rand/rand_windows.go
|
||||||
|
index 7380f1f..6c0655c 100644
|
||||||
|
--- a/src/crypto/rand/rand_windows.go
|
||||||
|
+++ b/src/crypto/rand/rand_windows.go
|
||||||
|
@@ -15,8 +15,11 @@ func init() { Reader = &rngReader{} }
|
||||||
|
|
||||||
|
type rngReader struct{}
|
||||||
|
|
||||||
|
-func (r *rngReader) Read(b []byte) (int, error) {
|
||||||
|
- if err := windows.ProcessPrng(b); err != nil {
|
||||||
|
+func (r *rngReader) Read(b []byte) (n int, err error) {
|
||||||
|
+ // RtlGenRandom only returns 1<<32-1 bytes at a time. We only read at
|
||||||
|
+ // most 1<<31-1 bytes at a time so that this works the same on 32-bit
|
||||||
|
+ // and 64-bit systems.
|
||||||
|
+ if err := batched(windows.RtlGenRandom, 1<<31-1)(b); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return len(b), nil
|
||||||
|
diff --git a/src/internal/syscall/windows/syscall_windows.go b/src/internal/syscall/windows/syscall_windows.go
|
||||||
|
index cc26a50..b0b5a64 100644
|
||||||
|
--- a/src/internal/syscall/windows/syscall_windows.go
|
||||||
|
+++ b/src/internal/syscall/windows/syscall_windows.go
|
||||||
|
@@ -414,7 +414,7 @@ func ErrorLoadingGetTempPath2() error {
|
||||||
|
//sys DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock
|
||||||
|
//sys CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle syscall.Handle, err error) = kernel32.CreateEventW
|
||||||
|
|
||||||
|
-//sys ProcessPrng(buf []byte) (err error) = bcryptprimitives.ProcessPrng
|
||||||
|
+//sys RtlGenRandom(buf []byte) (err error) = advapi32.SystemFunction036
|
||||||
|
|
||||||
|
type FILE_ID_BOTH_DIR_INFO struct {
|
||||||
|
NextEntryOffset uint32
|
||||||
|
diff --git a/src/internal/syscall/windows/zsyscall_windows.go b/src/internal/syscall/windows/zsyscall_windows.go
|
||||||
|
index 414ad26..062641c 100644
|
||||||
|
--- a/src/internal/syscall/windows/zsyscall_windows.go
|
||||||
|
+++ b/src/internal/syscall/windows/zsyscall_windows.go
|
||||||
|
@@ -38,7 +38,6 @@ func errnoErr(e syscall.Errno) error {
|
||||||
|
|
||||||
|
var (
|
||||||
|
modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll"))
|
||||||
|
- modbcryptprimitives = syscall.NewLazyDLL(sysdll.Add("bcryptprimitives.dll"))
|
||||||
|
modiphlpapi = syscall.NewLazyDLL(sysdll.Add("iphlpapi.dll"))
|
||||||
|
modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll"))
|
||||||
|
modnetapi32 = syscall.NewLazyDLL(sysdll.Add("netapi32.dll"))
|
||||||
|
@@ -57,7 +56,7 @@ var (
|
||||||
|
procQueryServiceStatus = modadvapi32.NewProc("QueryServiceStatus")
|
||||||
|
procRevertToSelf = modadvapi32.NewProc("RevertToSelf")
|
||||||
|
procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation")
|
||||||
|
- procProcessPrng = modbcryptprimitives.NewProc("ProcessPrng")
|
||||||
|
+ procSystemFunction036 = modadvapi32.NewProc("SystemFunction036")
|
||||||
|
procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses")
|
||||||
|
procCreateEventW = modkernel32.NewProc("CreateEventW")
|
||||||
|
procGetACP = modkernel32.NewProc("GetACP")
|
||||||
|
@@ -183,12 +182,12 @@ func SetTokenInformation(tokenHandle syscall.Token, tokenInformationClass uint32
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
-func ProcessPrng(buf []byte) (err error) {
|
||||||
|
+func RtlGenRandom(buf []byte) (err error) {
|
||||||
|
var _p0 *byte
|
||||||
|
if len(buf) > 0 {
|
||||||
|
_p0 = &buf[0]
|
||||||
|
}
|
||||||
|
- r1, _, e1 := syscall.Syscall(procProcessPrng.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), 0)
|
||||||
|
+ r1, _, e1 := syscall.Syscall(procSystemFunction036.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), 0)
|
||||||
|
if r1 == 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go
|
||||||
|
index 4aabc29..0273580 100644
|
||||||
|
--- a/src/runtime/os_windows.go
|
||||||
|
+++ b/src/runtime/os_windows.go
|
||||||
|
@@ -127,8 +127,15 @@ var (
|
||||||
|
_WriteFile,
|
||||||
|
_ stdFunction
|
||||||
|
|
||||||
|
- // Use ProcessPrng to generate cryptographically random data.
|
||||||
|
- _ProcessPrng stdFunction
|
||||||
|
+ // Use RtlGenRandom to generate cryptographically random data.
|
||||||
|
+ // This approach has been recommended by Microsoft (see issue
|
||||||
|
+ // 15589 for details).
|
||||||
|
+ // The RtlGenRandom is not listed in advapi32.dll, instead
|
||||||
|
+ // RtlGenRandom function can be found by searching for SystemFunction036.
|
||||||
|
+ // Also some versions of Mingw cannot link to SystemFunction036
|
||||||
|
+ // when building executable as Cgo. So load SystemFunction036
|
||||||
|
+ // manually during runtime startup.
|
||||||
|
+ _RtlGenRandom stdFunction
|
||||||
|
|
||||||
|
// Load ntdll.dll manually during startup, otherwise Mingw
|
||||||
|
// links wrong printf function to cgo executable (see issue
|
||||||
|
@@ -146,10 +153,11 @@ var (
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
- bcryptprimitivesdll = [...]uint16{'b', 'c', 'r', 'y', 'p', 't', 'p', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', 's', '.', '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}
|
||||||
|
+ advapi32dll = [...]uint16{'a', 'd', 'v', 'a', 'p', 'i', '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
|
||||||
|
@@ -263,11 +271,11 @@ func windows_QueryPerformanceFrequency() int64 {
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadOptionalSyscalls() {
|
||||||
|
- bcryptPrimitives := windowsLoadSystemLib(bcryptprimitivesdll[:])
|
||||||
|
- if bcryptPrimitives == 0 {
|
||||||
|
- throw("bcryptprimitives.dll not found")
|
||||||
|
+ a32 := windowsLoadSystemLib(advapi32dll[:])
|
||||||
|
+ if a32 == 0 {
|
||||||
|
+ throw("advapi32.dll not found")
|
||||||
|
}
|
||||||
|
- _ProcessPrng = windowsFindfunc(bcryptPrimitives, []byte("ProcessPrng\000"))
|
||||||
|
+ _RtlGenRandom = windowsFindfunc(a32, []byte("SystemFunction036\000"))
|
||||||
|
|
||||||
|
n32 := windowsLoadSystemLib(ntdlldll[:])
|
||||||
|
if n32 == 0 {
|
||||||
|
@@ -500,7 +508,7 @@ func osinit() {
|
||||||
|
//go:nosplit
|
||||||
|
func readRandom(r []byte) int {
|
||||||
|
n := 0
|
||||||
|
- if stdcall2(_ProcessPrng, uintptr(unsafe.Pointer(&r[0])), uintptr(len(r)))&0xff != 0 {
|
||||||
|
+ if stdcall2(_RtlGenRandom, uintptr(unsafe.Pointer(&r[0])), uintptr(len(r)))&0xff != 0 {
|
||||||
|
n = len(r)
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
--
|
||||||
|
2.47.0
|
||||||
|
|
||||||
2456
patches/0002-Restore-GOPATH-mode-get.patch
Normal file
2456
patches/0002-Restore-GOPATH-mode-get.patch
Normal file
File diff suppressed because it is too large
Load Diff
211
patches/0003-Restore-related-GOPATH-mode-go-get-functions.patch
Normal file
211
patches/0003-Restore-related-GOPATH-mode-go-get-functions.patch
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
From 3593bfc89de341818aefadf365ca615b78a8c958 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vorapol Rinsatitnon <vorapol.r@pm.me>
|
||||||
|
Date: Sun, 22 Sep 2024 00:34:20 +1000
|
||||||
|
Subject: [PATCH] Restore related GOPATH-mode go get functions
|
||||||
|
|
||||||
|
---
|
||||||
|
src/cmd/go/internal/load/pkg.go | 59 +++++++++++++++++++++++++++++++++
|
||||||
|
src/cmd/go/internal/par/work.go | 38 +++++++++++++++++++++
|
||||||
|
src/cmd/go/internal/vcs/vcs.go | 39 +++++++++++++++++++---
|
||||||
|
3 files changed, 132 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go
|
||||||
|
index 7c402b4..cb38b53 100644
|
||||||
|
--- a/src/cmd/go/internal/load/pkg.go
|
||||||
|
+++ b/src/cmd/go/internal/load/pkg.go
|
||||||
|
@@ -604,6 +604,51 @@ func (sp *ImportStack) shorterThan(t []string) bool {
|
||||||
|
// we return the same pointer each time.
|
||||||
|
var packageCache = map[string]*Package{}
|
||||||
|
|
||||||
|
+// ClearPackageCache clears the in-memory package cache and the preload caches.
|
||||||
|
+// It is only for use by GOPATH-based "go get".
|
||||||
|
+// TODO(jayconrod): When GOPATH-based "go get" is removed, delete this function.
|
||||||
|
+func ClearPackageCache() {
|
||||||
|
+ clear(packageCache)
|
||||||
|
+ resolvedImportCache.Clear()
|
||||||
|
+ packageDataCache.Clear()
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+// ClearPackageCachePartial clears packages with the given import paths from the
|
||||||
|
+// in-memory package cache and the preload caches. It is only for use by
|
||||||
|
+// GOPATH-based "go get".
|
||||||
|
+// TODO(jayconrod): When GOPATH-based "go get" is removed, delete this function.
|
||||||
|
+func ClearPackageCachePartial(args []string) {
|
||||||
|
+ shouldDelete := make(map[string]bool)
|
||||||
|
+ for _, arg := range args {
|
||||||
|
+ shouldDelete[arg] = true
|
||||||
|
+ if p := packageCache[arg]; p != nil {
|
||||||
|
+ delete(packageCache, arg)
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ resolvedImportCache.DeleteIf(func(key importSpec) bool {
|
||||||
|
+ return shouldDelete[key.path]
|
||||||
|
+ })
|
||||||
|
+ packageDataCache.DeleteIf(func(key string) bool {
|
||||||
|
+ return shouldDelete[key]
|
||||||
|
+ })
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+// ReloadPackageNoFlags is like LoadImport but makes sure
|
||||||
|
+// not to use the package cache.
|
||||||
|
+// It is only for use by GOPATH-based "go get".
|
||||||
|
+// TODO(rsc): When GOPATH-based "go get" is removed, delete this function.
|
||||||
|
+func ReloadPackageNoFlags(arg string, stk *ImportStack) *Package {
|
||||||
|
+ p := packageCache[arg]
|
||||||
|
+ if p != nil {
|
||||||
|
+ delete(packageCache, arg)
|
||||||
|
+ resolvedImportCache.DeleteIf(func(key importSpec) bool {
|
||||||
|
+ return key.path == p.ImportPath
|
||||||
|
+ })
|
||||||
|
+ packageDataCache.Delete(p.ImportPath)
|
||||||
|
+ }
|
||||||
|
+ return LoadPackage(context.TODO(), PackageOpts{}, arg, base.Cwd(), stk, nil, 0)
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
// dirToImportPath returns the pseudo-import path we use for a package
|
||||||
|
// outside the Go path. It begins with _/ and then contains the full path
|
||||||
|
// to the directory. If the package lives in c:\home\gopher\my\pkg then
|
||||||
|
@@ -655,6 +700,20 @@ const (
|
||||||
|
cmdlinePkgLiteral
|
||||||
|
)
|
||||||
|
|
||||||
|
+// LoadImport scans the directory named by path, which must be an import path,
|
||||||
|
+// but possibly a local import path (an absolute file system path or one beginning
|
||||||
|
+// with ./ or ../). A local relative path is interpreted relative to srcDir.
|
||||||
|
+// It returns a *Package describing the package found in that directory.
|
||||||
|
+// LoadImport does not set tool flags and should only be used by
|
||||||
|
+// this package, as part of a bigger load operation, and by GOPATH-based "go get".
|
||||||
|
+// TODO(rsc): When GOPATH-based "go get" is removed, unexport this function.
|
||||||
|
+// The returned PackageError, if any, describes why parent is not allowed
|
||||||
|
+// to import the named package, with the error referring to importPos.
|
||||||
|
+// The PackageError can only be non-nil when parent is not nil.
|
||||||
|
+func LoadImport(ctx context.Context, opts PackageOpts, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) (*Package, *PackageError) {
|
||||||
|
+ return loadImport(ctx, opts, nil, path, srcDir, parent, stk, importPos, mode)
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
// LoadPackage does Load import, but without a parent package load contezt
|
||||||
|
func LoadPackage(ctx context.Context, opts PackageOpts, path, srcDir string, stk *ImportStack, importPos []token.Position, mode int) *Package {
|
||||||
|
p, err := loadImport(ctx, opts, nil, path, srcDir, nil, stk, importPos, mode)
|
||||||
|
diff --git a/src/cmd/go/internal/par/work.go b/src/cmd/go/internal/par/work.go
|
||||||
|
index 881b51b..3f1e69a 100644
|
||||||
|
--- a/src/cmd/go/internal/par/work.go
|
||||||
|
+++ b/src/cmd/go/internal/par/work.go
|
||||||
|
@@ -180,3 +180,41 @@ func (c *Cache[K, V]) Get(key K) (V, bool) {
|
||||||
|
}
|
||||||
|
return e.result, true
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+// Clear removes all entries in the cache.
|
||||||
|
+//
|
||||||
|
+// Concurrent calls to Get may return old values. Concurrent calls to Do
|
||||||
|
+// may return old values or store results in entries that have been deleted.
|
||||||
|
+//
|
||||||
|
+// TODO(jayconrod): Delete this after the package cache clearing functions
|
||||||
|
+// in internal/load have been removed.
|
||||||
|
+func (c *Cache[K, V]) Clear() {
|
||||||
|
+ c.m.Clear()
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+// Delete removes an entry from the map. It is safe to call Delete for an
|
||||||
|
+// entry that does not exist. Delete will return quickly, even if the result
|
||||||
|
+// for a key is still being computed; the computation will finish, but the
|
||||||
|
+// result won't be accessible through the cache.
|
||||||
|
+//
|
||||||
|
+// TODO(jayconrod): Delete this after the package cache clearing functions
|
||||||
|
+// in internal/load have been removed.
|
||||||
|
+func (c *Cache[K, V]) Delete(key K) {
|
||||||
|
+ c.m.Delete(key)
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+// DeleteIf calls pred for each key in the map. If pred returns true for a key,
|
||||||
|
+// DeleteIf removes the corresponding entry. If the result for a key is
|
||||||
|
+// still being computed, DeleteIf will remove the entry without waiting for
|
||||||
|
+// the computation to finish. The result won't be accessible through the cache.
|
||||||
|
+//
|
||||||
|
+// TODO(jayconrod): Delete this after the package cache clearing functions
|
||||||
|
+// in internal/load have been removed.
|
||||||
|
+func (c *Cache[K, V]) DeleteIf(pred func(key K) bool) {
|
||||||
|
+ c.m.Range(func(key, _ any) bool {
|
||||||
|
+ if key := key.(K); pred(key) {
|
||||||
|
+ c.Delete(key)
|
||||||
|
+ }
|
||||||
|
+ return true
|
||||||
|
+ })
|
||||||
|
+}
|
||||||
|
diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go
|
||||||
|
index 19a6a5e..044d02e 100644
|
||||||
|
--- a/src/cmd/go/internal/vcs/vcs.go
|
||||||
|
+++ b/src/cmd/go/internal/vcs/vcs.go
|
||||||
|
@@ -1013,11 +1013,11 @@ var defaultGOVCS = govcsConfig{
|
||||||
|
{"public", []string{"git", "hg"}},
|
||||||
|
}
|
||||||
|
|
||||||
|
-// checkGOVCS checks whether the policy defined by the environment variable
|
||||||
|
+// CheckGOVCS checks whether the policy defined by the environment variable
|
||||||
|
// GOVCS allows the given vcs command to be used with the given repository
|
||||||
|
// root path. Note that root may not be a real package or module path; it's
|
||||||
|
// the same as the root path in the go-import meta tag.
|
||||||
|
-func checkGOVCS(vcs *Cmd, root string) error {
|
||||||
|
+func CheckGOVCS(vcs *Cmd, root string) error {
|
||||||
|
if vcs == vcsMod {
|
||||||
|
// Direct module (proxy protocol) fetches don't
|
||||||
|
// involve an external version control system
|
||||||
|
@@ -1045,6 +1045,37 @@ func checkGOVCS(vcs *Cmd, root string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
+// CheckNested checks for an incorrectly-nested VCS-inside-VCS
|
||||||
|
+// situation for dir, checking parents up until srcRoot.
|
||||||
|
+func CheckNested(vcs *Cmd, dir, srcRoot string) error {
|
||||||
|
+ if len(dir) <= len(srcRoot) || dir[len(srcRoot)] != filepath.Separator {
|
||||||
|
+ return fmt.Errorf("directory %q is outside source root %q", dir, srcRoot)
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ otherDir := dir
|
||||||
|
+ for len(otherDir) > len(srcRoot) {
|
||||||
|
+ for _, otherVCS := range vcsList {
|
||||||
|
+ if isVCSRoot(otherDir, otherVCS.RootNames) {
|
||||||
|
+ // Allow expected vcs in original dir.
|
||||||
|
+ if otherDir == dir && otherVCS == vcs {
|
||||||
|
+ continue
|
||||||
|
+ }
|
||||||
|
+ // Otherwise, we have one VCS inside a different VCS.
|
||||||
|
+ return fmt.Errorf("directory %q uses %s, but parent %q uses %s", dir, vcs.Cmd, otherDir, otherVCS.Cmd)
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Move to parent.
|
||||||
|
+ newDir := filepath.Dir(otherDir)
|
||||||
|
+ if len(newDir) >= len(otherDir) {
|
||||||
|
+ // Shouldn't happen, but just in case, stop.
|
||||||
|
+ break
|
||||||
|
+ }
|
||||||
|
+ otherDir = newDir
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return nil
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
// RepoRoot describes the repository root for a tree of source code.
|
||||||
|
type RepoRoot struct {
|
||||||
|
Repo string // repository URL, including scheme
|
||||||
|
@@ -1160,7 +1191,7 @@ func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths
|
||||||
|
if vcs == nil {
|
||||||
|
return nil, fmt.Errorf("unknown version control system %q", match["vcs"])
|
||||||
|
}
|
||||||
|
- if err := checkGOVCS(vcs, match["root"]); err != nil {
|
||||||
|
+ if err := CheckGOVCS(vcs, match["root"]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var repoURL string
|
||||||
|
@@ -1349,7 +1380,7 @@ func repoRootForImportDynamic(importPath string, mod ModuleMode, security web.Se
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- if err := checkGOVCS(vcs, mmi.Prefix); err != nil {
|
||||||
|
+ if err := CheckGOVCS(vcs, mmi.Prefix); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.47.0
|
||||||
|
|
||||||
307
patches/0004-Add-back-LoadLibraryA-fallback.patch
Normal file
307
patches/0004-Add-back-LoadLibraryA-fallback.patch
Normal file
@@ -0,0 +1,307 @@
|
|||||||
|
From 4945989aba36baee4cdc72e61bdc4484c81d9ea0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vorapol Rinsatitnon <vorapol.r@pm.me>
|
||||||
|
Date: Fri, 27 Sep 2024 04:05:44 +1000
|
||||||
|
Subject: [PATCH] Add back LoadLibraryA fallback
|
||||||
|
|
||||||
|
---
|
||||||
|
src/runtime/export_windows_test.go | 4 ++
|
||||||
|
src/runtime/os_windows.go | 60 ++++++++++++++++++++++++++++-
|
||||||
|
src/runtime/syscall_windows.go | 17 +++++++-
|
||||||
|
src/runtime/syscall_windows_test.go | 23 ++++++++++-
|
||||||
|
src/syscall/dll_windows.go | 28 +++++++++++++-
|
||||||
|
src/syscall/security_windows.go | 1 +
|
||||||
|
src/syscall/zsyscall_windows.go | 10 +++++
|
||||||
|
7 files changed, 136 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/runtime/export_windows_test.go b/src/runtime/export_windows_test.go
|
||||||
|
index 4880e62..8bfff0b 100644
|
||||||
|
--- a/src/runtime/export_windows_test.go
|
||||||
|
+++ b/src/runtime/export_windows_test.go
|
||||||
|
@@ -36,3 +36,7 @@ func NewContextStub() *ContextStub {
|
||||||
|
ctx.set_fp(getcallerfp())
|
||||||
|
return &ContextStub{ctx}
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+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 0273580..c76df9d 100644
|
||||||
|
--- a/src/runtime/os_windows.go
|
||||||
|
+++ b/src/runtime/os_windows.go
|
||||||
|
@@ -41,6 +41,7 @@ const (
|
||||||
|
//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._QueryPerformanceCounter QueryPerformanceCounter%1 "kernel32.dll"
|
||||||
|
//go:cgo_import_dynamic runtime._QueryPerformanceFrequency QueryPerformanceFrequency%1 "kernel32.dll"
|
||||||
|
@@ -74,6 +75,7 @@ var (
|
||||||
|
// Following syscalls are available on every Windows PC.
|
||||||
|
// All these variables are set by the Windows executable
|
||||||
|
// loader before the Go program starts.
|
||||||
|
+ _AddDllDirectory,
|
||||||
|
_AddVectoredContinueHandler,
|
||||||
|
_AddVectoredExceptionHandler,
|
||||||
|
_CloseHandle,
|
||||||
|
@@ -99,6 +101,7 @@ var (
|
||||||
|
_SetThreadContext,
|
||||||
|
_LoadLibraryExW,
|
||||||
|
_LoadLibraryW,
|
||||||
|
+ _LoadLibraryA,
|
||||||
|
_PostQueuedCompletionStatus,
|
||||||
|
_QueryPerformanceCounter,
|
||||||
|
_QueryPerformanceFrequency,
|
||||||
|
@@ -157,7 +160,6 @@ var (
|
||||||
|
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
|
||||||
|
@@ -253,7 +255,36 @@ func windows_GetSystemDirectory() string {
|
||||||
|
}
|
||||||
|
|
||||||
|
func windowsLoadSystemLib(name []uint16) uintptr {
|
||||||
|
- return stdcall3(_LoadLibraryExW, uintptr(unsafe.Pointer(&name[0])), 0, _LOAD_LIBRARY_SEARCH_SYSTEM32)
|
||||||
|
+ if useLoadLibraryEx {
|
||||||
|
+ return stdcall3(_LoadLibraryExW, uintptr(unsafe.Pointer(&name[0])), 0, _LOAD_LIBRARY_SEARCH_SYSTEM32)
|
||||||
|
+ } else {
|
||||||
|
+ var nameBytes [_MAX_PATH]byte
|
||||||
|
+ n := len(name)
|
||||||
|
+ if n > len(nameBytes) {
|
||||||
|
+ n = len(nameBytes)
|
||||||
|
+ }
|
||||||
|
+ for i := 0; i < n && name[i] != 0; i++ {
|
||||||
|
+ nameBytes[i] = byte(name[i])
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // Construct the full path
|
||||||
|
+ var fullPath [_MAX_PATH]byte
|
||||||
|
+ copy(fullPath[:], sysDirectory[:sysDirectoryLen])
|
||||||
|
+ pathLen := sysDirectoryLen
|
||||||
|
+ for i := 0; i < len(nameBytes) && nameBytes[i] != 0 && pathLen < _MAX_PATH; i++ {
|
||||||
|
+ fullPath[pathLen] = nameBytes[i]
|
||||||
|
+ pathLen++
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // Ensure null-termination
|
||||||
|
+ if pathLen < _MAX_PATH {
|
||||||
|
+ fullPath[pathLen] = 0
|
||||||
|
+ } else {
|
||||||
|
+ fullPath[_MAX_PATH-1] = 0
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&fullPath[0])))
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname windows_QueryPerformanceCounter internal/syscall/windows.QueryPerformanceCounter
|
||||||
|
@@ -271,6 +302,15 @@ func windows_QueryPerformanceFrequency() int64 {
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadOptionalSyscalls() {
|
||||||
|
+ var kernel32dll = []byte("kernel32.dll\000")
|
||||||
|
+ k32 := stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&kernel32dll[0])))
|
||||||
|
+ if k32 == 0 {
|
||||||
|
+ throw("kernel32.dll not found")
|
||||||
|
+ }
|
||||||
|
+ _AddDllDirectory = windowsFindfunc(k32, []byte("AddDllDirectory\000"))
|
||||||
|
+ _LoadLibraryExW = windowsFindfunc(k32, []byte("LoadLibraryExW\000"))
|
||||||
|
+ useLoadLibraryEx = (_LoadLibraryExW != nil && _AddDllDirectory != nil)
|
||||||
|
+
|
||||||
|
a32 := windowsLoadSystemLib(advapi32dll[:])
|
||||||
|
if a32 == 0 {
|
||||||
|
throw("advapi32.dll not found")
|
||||||
|
@@ -365,6 +405,22 @@ 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
|
||||||
|
diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go
|
||||||
|
index 69d720a..973fd9c 100644
|
||||||
|
--- a/src/runtime/syscall_windows.go
|
||||||
|
+++ b/src/runtime/syscall_windows.go
|
||||||
|
@@ -413,10 +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
|
||||||
|
-func syscall_loadsystemlibrary(filename *uint16) (handle, err uintptr) {
|
||||||
|
- handle, _, err = syscall_SyscallN(uintptr(unsafe.Pointer(_LoadLibraryExW)), uintptr(unsafe.Pointer(filename)), 0, _LOAD_LIBRARY_SEARCH_SYSTEM32)
|
||||||
|
+func syscall_loadsystemlibrary(filename *uint16, absoluteFilepath *uint16) (handle, err uintptr) {
|
||||||
|
+ if useLoadLibraryEx {
|
||||||
|
+ handle, _, err = syscall_SyscallN(uintptr(unsafe.Pointer(_LoadLibraryExW)), uintptr(unsafe.Pointer(filename)), 0, _LOAD_LIBRARY_SEARCH_SYSTEM32)
|
||||||
|
+ } else {
|
||||||
|
+ handle, _, err = syscall_SyscallN(
|
||||||
|
+ uintptr(unsafe.Pointer(_LoadLibraryW)),
|
||||||
|
+ uintptr(unsafe.Pointer(absoluteFilepath)),
|
||||||
|
+ )
|
||||||
|
+ }
|
||||||
|
KeepAlive(filename)
|
||||||
|
+ KeepAlive(absoluteFilepath)
|
||||||
|
if handle != 0 {
|
||||||
|
err = 0
|
||||||
|
}
|
||||||
|
diff --git a/src/runtime/syscall_windows_test.go b/src/runtime/syscall_windows_test.go
|
||||||
|
index 6a056c8..2c91cd9 100644
|
||||||
|
--- a/src/runtime/syscall_windows_test.go
|
||||||
|
+++ b/src/runtime/syscall_windows_test.go
|
||||||
|
@@ -1166,7 +1166,10 @@ uintptr_t cfunc(void) {
|
||||||
|
dll, err = syscall.LoadDLL(name)
|
||||||
|
if err == nil {
|
||||||
|
dll.Release()
|
||||||
|
- t.Fatalf("Bad: insecure load of DLL by base name %q before sysdll registration: %v", name, err)
|
||||||
|
+ 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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1212,6 +1215,24 @@ 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 81134cb..b3554d3 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) (handle uintptr, err Errno)
|
||||||
|
+func loadsystemlibrary(filename *uint16, absoluteFilepath *uint16) (handle uintptr, err Errno)
|
||||||
|
func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err Errno)
|
||||||
|
|
||||||
|
// A DLL implements access to a single DLL.
|
||||||
|
@@ -53,6 +53,26 @@ 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
|
||||||
|
@@ -69,7 +89,11 @@ func LoadDLL(name string) (*DLL, error) {
|
||||||
|
var h uintptr
|
||||||
|
var e Errno
|
||||||
|
if sysdll.IsSystemDLL[name] {
|
||||||
|
- h, e = loadsystemlibrary(namep)
|
||||||
|
+ absoluteFilepathp, err := UTF16PtrFromString(systemDirectoryPrefix + name)
|
||||||
|
+ if err != nil {
|
||||||
|
+ return nil, err
|
||||||
|
+ }
|
||||||
|
+ h, e = loadsystemlibrary(namep, absoluteFilepathp)
|
||||||
|
} else {
|
||||||
|
h, e = loadlibrary(namep)
|
||||||
|
}
|
||||||
|
diff --git a/src/syscall/security_windows.go b/src/syscall/security_windows.go
|
||||||
|
index 4e988c4..45b1908 100644
|
||||||
|
--- a/src/syscall/security_windows.go
|
||||||
|
+++ b/src/syscall/security_windows.go
|
||||||
|
@@ -290,6 +290,7 @@ 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 d8d8594..28369e3 100644
|
||||||
|
--- a/src/syscall/zsyscall_windows.go
|
||||||
|
+++ b/src/syscall/zsyscall_windows.go
|
||||||
|
@@ -128,6 +128,7 @@ var (
|
||||||
|
procGetShortPathNameW = modkernel32.NewProc("GetShortPathNameW")
|
||||||
|
procGetStartupInfoW = modkernel32.NewProc("GetStartupInfoW")
|
||||||
|
procGetStdHandle = modkernel32.NewProc("GetStdHandle")
|
||||||
|
+ procGetSystemDirectoryW = modkernel32.NewProc("GetSystemDirectoryW")
|
||||||
|
procGetSystemTimeAsFileTime = modkernel32.NewProc("GetSystemTimeAsFileTime")
|
||||||
|
procGetTempPathW = modkernel32.NewProc("GetTempPathW")
|
||||||
|
procGetTimeZoneInformation = modkernel32.NewProc("GetTimeZoneInformation")
|
||||||
|
@@ -870,6 +871,15 @@ 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
|
||||||
|
--
|
||||||
|
2.47.0
|
||||||
|
|
||||||
66
patches/0005-Add-Windows-7-console-handle-workaround.patch
Normal file
66
patches/0005-Add-Windows-7-console-handle-workaround.patch
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
From 60f9e8454df41affe07266e795f8a1d22567fd3e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vorapol Rinsatitnon <vorapol.r@pm.me>
|
||||||
|
Date: Sat, 5 Oct 2024 14:17:43 +1000
|
||||||
|
Subject: [PATCH] Add Windows 7 console handle workaround (revert 48042aa)
|
||||||
|
|
||||||
|
---
|
||||||
|
src/syscall/exec_windows.go | 29 ++++++++++++++++++++++++++++-
|
||||||
|
1 file changed, 28 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/syscall/exec_windows.go b/src/syscall/exec_windows.go
|
||||||
|
index 1220de4..815dfd6 100644
|
||||||
|
--- a/src/syscall/exec_windows.go
|
||||||
|
+++ b/src/syscall/exec_windows.go
|
||||||
|
@@ -317,6 +317,17 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ var maj, min, build uint32
|
||||||
|
+ rtlGetNtVersionNumbers(&maj, &min, &build)
|
||||||
|
+ isWin7 := maj < 6 || (maj == 6 && min <= 1)
|
||||||
|
+ // NT kernel handles are divisible by 4, with the bottom 3 bits left as
|
||||||
|
+ // a tag. The fully set tag correlates with the types of handles we're
|
||||||
|
+ // concerned about here. Except, the kernel will interpret some
|
||||||
|
+ // special handle values, like -1, -2, and so forth, so kernelbase.dll
|
||||||
|
+ // checks to see that those bottom three bits are checked, but that top
|
||||||
|
+ // bit is not checked.
|
||||||
|
+ isLegacyWin7ConsoleHandle := func(handle Handle) bool { return isWin7 && handle&0x10000003 == 3 }
|
||||||
|
+
|
||||||
|
p, _ := GetCurrentProcess()
|
||||||
|
parentProcess := p
|
||||||
|
if sys.ParentProcess != 0 {
|
||||||
|
@@ -325,7 +336,15 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
|
||||||
|
fd := make([]Handle, len(attr.Files))
|
||||||
|
for i := range attr.Files {
|
||||||
|
if attr.Files[i] > 0 {
|
||||||
|
- err := DuplicateHandle(p, Handle(attr.Files[i]), parentProcess, &fd[i], 0, true, DUPLICATE_SAME_ACCESS)
|
||||||
|
+ destinationProcessHandle := parentProcess
|
||||||
|
+
|
||||||
|
+ // On Windows 7, console handles aren't real handles, and can only be duplicated
|
||||||
|
+ // into the current process, not a parent one, which amounts to the same thing.
|
||||||
|
+ if parentProcess != p && isLegacyWin7ConsoleHandle(Handle(attr.Files[i])) {
|
||||||
|
+ destinationProcessHandle = p
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ err := DuplicateHandle(p, Handle(attr.Files[i]), destinationProcessHandle, &fd[i], 0, true, DUPLICATE_SAME_ACCESS)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
@@ -356,6 +375,14 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
|
||||||
|
|
||||||
|
fd = append(fd, sys.AdditionalInheritedHandles...)
|
||||||
|
|
||||||
|
+ // On Windows 7, console handles aren't real handles, so don't pass them
|
||||||
|
+ // through to PROC_THREAD_ATTRIBUTE_HANDLE_LIST.
|
||||||
|
+ for i := range fd {
|
||||||
|
+ if isLegacyWin7ConsoleHandle(fd[i]) {
|
||||||
|
+ fd[i] = 0
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
// The presence of a NULL handle in the list is enough to cause PROC_THREAD_ATTRIBUTE_HANDLE_LIST
|
||||||
|
// to treat the entire list as empty, so remove NULL handles.
|
||||||
|
j := 0
|
||||||
|
--
|
||||||
|
2.47.0
|
||||||
|
|
||||||
177
patches/0006-Add-sysSocket-fallback.patch
Normal file
177
patches/0006-Add-sysSocket-fallback.patch
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
From 0468b8b0addf825a274d81630087d62db495a562 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vorapol Rinsatitnon <vorapol.r@pm.me>
|
||||||
|
Date: Sat, 5 Oct 2024 14:27:19 +1000
|
||||||
|
Subject: [PATCH] Add sysSocket fallback (revert 7c1157f)
|
||||||
|
|
||||||
|
---
|
||||||
|
src/net/hook_windows.go | 1 +
|
||||||
|
src/net/internal/socktest/main_test.go | 2 +-
|
||||||
|
.../internal/socktest/main_windows_test.go | 22 ++++++++++++++
|
||||||
|
src/net/internal/socktest/sys_windows.go | 29 +++++++++++++++++++
|
||||||
|
src/net/main_windows_test.go | 3 ++
|
||||||
|
src/net/sock_windows.go | 14 +++++++++
|
||||||
|
src/syscall/exec_windows.go | 1 -
|
||||||
|
7 files changed, 70 insertions(+), 2 deletions(-)
|
||||||
|
create mode 100644 src/net/internal/socktest/main_windows_test.go
|
||||||
|
|
||||||
|
diff --git a/src/net/hook_windows.go b/src/net/hook_windows.go
|
||||||
|
index f7c5b5a..6b82be5 100644
|
||||||
|
--- a/src/net/hook_windows.go
|
||||||
|
+++ b/src/net/hook_windows.go
|
||||||
|
@@ -13,6 +13,7 @@ var (
|
||||||
|
hostsFilePath = windows.GetSystemDirectory() + "/Drivers/etc/hosts"
|
||||||
|
|
||||||
|
// Placeholders for socket system calls.
|
||||||
|
+ socketFunc func(int, int, int) (syscall.Handle, error) = syscall.Socket
|
||||||
|
wsaSocketFunc func(int32, int32, int32, *syscall.WSAProtocolInfo, uint32, uint32) (syscall.Handle, error) = windows.WSASocket
|
||||||
|
connectFunc func(syscall.Handle, syscall.Sockaddr) error = syscall.Connect
|
||||||
|
listenFunc func(syscall.Handle, int) error = syscall.Listen
|
||||||
|
diff --git a/src/net/internal/socktest/main_test.go b/src/net/internal/socktest/main_test.go
|
||||||
|
index 967ce67..0197feb 100644
|
||||||
|
--- a/src/net/internal/socktest/main_test.go
|
||||||
|
+++ b/src/net/internal/socktest/main_test.go
|
||||||
|
@@ -2,7 +2,7 @@
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
-//go:build !js && !plan9 && !wasip1 && !windows
|
||||||
|
+//go:build !js && !plan9 && !wasip1
|
||||||
|
|
||||||
|
package socktest_test
|
||||||
|
|
||||||
|
diff --git a/src/net/internal/socktest/main_windows_test.go b/src/net/internal/socktest/main_windows_test.go
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..df1cb97
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/net/internal/socktest/main_windows_test.go
|
||||||
|
@@ -0,0 +1,22 @@
|
||||||
|
+// Copyright 2015 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 socktest_test
|
||||||
|
+
|
||||||
|
+import "syscall"
|
||||||
|
+
|
||||||
|
+var (
|
||||||
|
+ socketFunc func(int, int, int) (syscall.Handle, error)
|
||||||
|
+ closeFunc func(syscall.Handle) error
|
||||||
|
+)
|
||||||
|
+
|
||||||
|
+func installTestHooks() {
|
||||||
|
+ socketFunc = sw.Socket
|
||||||
|
+ closeFunc = sw.Closesocket
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+func uninstallTestHooks() {
|
||||||
|
+ socketFunc = syscall.Socket
|
||||||
|
+ closeFunc = syscall.Closesocket
|
||||||
|
+}
|
||||||
|
diff --git a/src/net/internal/socktest/sys_windows.go b/src/net/internal/socktest/sys_windows.go
|
||||||
|
index 2f02446..2b89362 100644
|
||||||
|
--- a/src/net/internal/socktest/sys_windows.go
|
||||||
|
+++ b/src/net/internal/socktest/sys_windows.go
|
||||||
|
@@ -9,6 +9,35 @@ import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
+// Socket wraps syscall.Socket.
|
||||||
|
+func (sw *Switch) Socket(family, sotype, proto int) (s syscall.Handle, err error) {
|
||||||
|
+ sw.once.Do(sw.init)
|
||||||
|
+ so := &Status{Cookie: cookie(family, sotype, proto)}
|
||||||
|
+ sw.fmu.RLock()
|
||||||
|
+ f, _ := sw.fltab[FilterSocket]
|
||||||
|
+ sw.fmu.RUnlock()
|
||||||
|
+ af, err := f.apply(so)
|
||||||
|
+ if err != nil {
|
||||||
|
+ return syscall.InvalidHandle, err
|
||||||
|
+ }
|
||||||
|
+ s, so.Err = syscall.Socket(family, sotype, proto)
|
||||||
|
+ if err = af.apply(so); err != nil {
|
||||||
|
+ if so.Err == nil {
|
||||||
|
+ syscall.Closesocket(s)
|
||||||
|
+ }
|
||||||
|
+ return syscall.InvalidHandle, err
|
||||||
|
+ }
|
||||||
|
+ sw.smu.Lock()
|
||||||
|
+ defer sw.smu.Unlock()
|
||||||
|
+ if so.Err != nil {
|
||||||
|
+ sw.stats.getLocked(so.Cookie).OpenFailed++
|
||||||
|
+ return syscall.InvalidHandle, so.Err
|
||||||
|
+ }
|
||||||
|
+ nso := sw.addLocked(s, family, sotype, proto)
|
||||||
|
+ sw.stats.getLocked(nso.Cookie).Opened++
|
||||||
|
+ return s, nil
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
// WSASocket wraps [syscall.WSASocket].
|
||||||
|
func (sw *Switch) WSASocket(family, sotype, proto int32, protinfo *syscall.WSAProtocolInfo, group uint32, flags uint32) (s syscall.Handle, err error) {
|
||||||
|
sw.once.Do(sw.init)
|
||||||
|
diff --git a/src/net/main_windows_test.go b/src/net/main_windows_test.go
|
||||||
|
index bc024c0..07f21b7 100644
|
||||||
|
--- a/src/net/main_windows_test.go
|
||||||
|
+++ b/src/net/main_windows_test.go
|
||||||
|
@@ -8,6 +8,7 @@ import "internal/poll"
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Placeholders for saving original socket system calls.
|
||||||
|
+ origSocket = socketFunc
|
||||||
|
origWSASocket = wsaSocketFunc
|
||||||
|
origClosesocket = poll.CloseFunc
|
||||||
|
origConnect = connectFunc
|
||||||
|
@@ -17,6 +18,7 @@ var (
|
||||||
|
)
|
||||||
|
|
||||||
|
func installTestHooks() {
|
||||||
|
+ socketFunc = sw.Socket
|
||||||
|
wsaSocketFunc = sw.WSASocket
|
||||||
|
poll.CloseFunc = sw.Closesocket
|
||||||
|
connectFunc = sw.Connect
|
||||||
|
@@ -26,6 +28,7 @@ func installTestHooks() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func uninstallTestHooks() {
|
||||||
|
+ socketFunc = origSocket
|
||||||
|
wsaSocketFunc = origWSASocket
|
||||||
|
poll.CloseFunc = origClosesocket
|
||||||
|
connectFunc = origConnect
|
||||||
|
diff --git a/src/net/sock_windows.go b/src/net/sock_windows.go
|
||||||
|
index a519909..ebdf4c3 100644
|
||||||
|
--- a/src/net/sock_windows.go
|
||||||
|
+++ b/src/net/sock_windows.go
|
||||||
|
@@ -20,6 +20,20 @@ func maxListenerBacklog() int {
|
||||||
|
func sysSocket(family, sotype, proto int) (syscall.Handle, error) {
|
||||||
|
s, err := wsaSocketFunc(int32(family), int32(sotype), int32(proto),
|
||||||
|
nil, 0, windows.WSA_FLAG_OVERLAPPED|windows.WSA_FLAG_NO_HANDLE_INHERIT)
|
||||||
|
+ if err == nil {
|
||||||
|
+ return s, nil
|
||||||
|
+ }
|
||||||
|
+ // WSA_FLAG_NO_HANDLE_INHERIT flag is not supported on some
|
||||||
|
+ // old versions of Windows, see
|
||||||
|
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/ms742212(v=vs.85).aspx
|
||||||
|
+ // for details. Just use syscall.Socket, if windows.WSASocket failed.
|
||||||
|
+ // See ../syscall/exec_unix.go for description of ForkLock.
|
||||||
|
+ syscall.ForkLock.RLock()
|
||||||
|
+ s, err = socketFunc(family, sotype, proto)
|
||||||
|
+ if err == nil {
|
||||||
|
+ syscall.CloseOnExec(s)
|
||||||
|
+ }
|
||||||
|
+ syscall.ForkLock.RUnlock()
|
||||||
|
if err != nil {
|
||||||
|
return syscall.InvalidHandle, os.NewSyscallError("socket", err)
|
||||||
|
}
|
||||||
|
diff --git a/src/syscall/exec_windows.go b/src/syscall/exec_windows.go
|
||||||
|
index 815dfd6..d197380 100644
|
||||||
|
--- a/src/syscall/exec_windows.go
|
||||||
|
+++ b/src/syscall/exec_windows.go
|
||||||
|
@@ -14,7 +14,6 @@ import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
-// ForkLock is not used on Windows.
|
||||||
|
var ForkLock sync.RWMutex
|
||||||
|
|
||||||
|
// EscapeArg rewrites command line argument s as prescribed
|
||||||
|
--
|
||||||
|
2.47.0
|
||||||
|
|
||||||
82
patches/0007-Add-Windows-version-info-to-syscall.patch
Normal file
82
patches/0007-Add-Windows-version-info-to-syscall.patch
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
From d97201a53d5ec76fa81b091bc0d4d64f6ff6ff8c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vorapol Rinsatitnon <vorapol.r@pm.me>
|
||||||
|
Date: Sat, 5 Oct 2024 15:10:54 +1000
|
||||||
|
Subject: [PATCH] Add Windows version info to syscall
|
||||||
|
|
||||||
|
---
|
||||||
|
src/syscall/exec_windows.go | 7 ++++---
|
||||||
|
src/syscall/types_windows.go | 10 ++++++++++
|
||||||
|
src/syscall/zsyscall_windows.go | 7 +++++++
|
||||||
|
3 files changed, 21 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/syscall/exec_windows.go b/src/syscall/exec_windows.go
|
||||||
|
index d197380..f099a6f 100644
|
||||||
|
--- a/src/syscall/exec_windows.go
|
||||||
|
+++ b/src/syscall/exec_windows.go
|
||||||
|
@@ -316,9 +316,10 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- var maj, min, build uint32
|
||||||
|
- rtlGetNtVersionNumbers(&maj, &min, &build)
|
||||||
|
- isWin7 := maj < 6 || (maj == 6 && min <= 1)
|
||||||
|
+ info := _OSVERSIONINFOW{}
|
||||||
|
+ info.osVersionInfoSize = uint32(unsafe.Sizeof(info))
|
||||||
|
+ rtlGetVersion(&info)
|
||||||
|
+ isWin7 := info.majorVersion < 6 || (info.majorVersion == 6 && info.minorVersion <= 1)
|
||||||
|
// NT kernel handles are divisible by 4, with the bottom 3 bits left as
|
||||||
|
// a tag. The fully set tag correlates with the types of handles we're
|
||||||
|
// concerned about here. Except, the kernel will interpret some
|
||||||
|
diff --git a/src/syscall/types_windows.go b/src/syscall/types_windows.go
|
||||||
|
index 6743675..37d0eff 100644
|
||||||
|
--- a/src/syscall/types_windows.go
|
||||||
|
+++ b/src/syscall/types_windows.go
|
||||||
|
@@ -1169,3 +1169,13 @@ const (
|
||||||
|
)
|
||||||
|
|
||||||
|
const UNIX_PATH_MAX = 108 // defined in afunix.h
|
||||||
|
+
|
||||||
|
+// https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_osversioninfow
|
||||||
|
+type _OSVERSIONINFOW struct {
|
||||||
|
+ osVersionInfoSize uint32
|
||||||
|
+ majorVersion uint32
|
||||||
|
+ minorVersion uint32
|
||||||
|
+ buildNumber uint32
|
||||||
|
+ platformId uint32
|
||||||
|
+ csdVersion [128]uint16
|
||||||
|
+}
|
||||||
|
diff --git a/src/syscall/zsyscall_windows.go b/src/syscall/zsyscall_windows.go
|
||||||
|
index 28369e3..a47b090 100644
|
||||||
|
--- a/src/syscall/zsyscall_windows.go
|
||||||
|
+++ b/src/syscall/zsyscall_windows.go
|
||||||
|
@@ -43,6 +43,7 @@ var (
|
||||||
|
modkernel32 = NewLazyDLL(sysdll.Add("kernel32.dll"))
|
||||||
|
modmswsock = NewLazyDLL(sysdll.Add("mswsock.dll"))
|
||||||
|
modnetapi32 = NewLazyDLL(sysdll.Add("netapi32.dll"))
|
||||||
|
+ modntdll = NewLazyDLL(sysdll.Add("ntdll.dll"))
|
||||||
|
modsecur32 = NewLazyDLL(sysdll.Add("secur32.dll"))
|
||||||
|
modshell32 = NewLazyDLL(sysdll.Add("shell32.dll"))
|
||||||
|
moduserenv = NewLazyDLL(sysdll.Add("userenv.dll"))
|
||||||
|
@@ -169,6 +170,7 @@ var (
|
||||||
|
procNetGetJoinInformation = modnetapi32.NewProc("NetGetJoinInformation")
|
||||||
|
procNetUserGetInfo = modnetapi32.NewProc("NetUserGetInfo")
|
||||||
|
procGetUserNameExW = modsecur32.NewProc("GetUserNameExW")
|
||||||
|
+ procRtlGetVersion = modntdll.NewProc("RtlGetVersion")
|
||||||
|
procTranslateNameW = modsecur32.NewProc("TranslateNameW")
|
||||||
|
procCommandLineToArgvW = modshell32.NewProc("CommandLineToArgvW")
|
||||||
|
procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW")
|
||||||
|
@@ -1228,6 +1230,11 @@ func GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err er
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
+func rtlGetVersion(info *_OSVERSIONINFOW) {
|
||||||
|
+ Syscall(procRtlGetVersion.Addr(), 1, uintptr(unsafe.Pointer(info)), 0, 0)
|
||||||
|
+ return
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
func TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) {
|
||||||
|
r1, _, e1 := Syscall6(procTranslateNameW.Addr(), 5, uintptr(unsafe.Pointer(accName)), uintptr(accNameFormat), uintptr(desiredNameFormat), uintptr(unsafe.Pointer(translatedName)), uintptr(unsafe.Pointer(nSize)), 0)
|
||||||
|
if r1&0xff == 0 {
|
||||||
|
--
|
||||||
|
2.47.0
|
||||||
|
|
||||||
Reference in New Issue
Block a user