1
0
mirror of https://github.com/golang/go synced 2024-11-17 05:14:56 -07:00

cmd/link: do not generate NT 4 compatibility binaries

Incredibly, the subsystem version numbers in the PE header influence how
win32k handles various syscalls. The first time a win32k syscall is
invoked and the kernel upgrades the thread object to a tagTHREADINFO
with all of the lovely undocumented UI members and such, it sets the
dwExpWinVer member (offset 624 in Windows 10 build 1809) to the result
of RtlGetExpWinVer(PsGetProcessSectionBaseAddress(proc)).
RtlGetExpWinVer, also undocumented, then calls into the undocumented
RtlImageNtHeader function, which returns a fortunately documented
IMAGE_NT_HEADERS structure. It uses the subsystem members in there to
set the dwExpWinVer member of our newly minted tagTHREADINFO object.
Later, functions like SendInput consult this to vary their behaviors and
return values. In fact, littered through out win32k are checks like `if
(gsti->dwExpWinVer >= 0x501) { ... }`.

I don't think Go ever supported NT 4.0. These days the minimum version
is Windows 7, which is 6.1. So, let's set the version numbers in the PE
header at that, which should give us the behavior that MSDN advertises
for various functions, as opposed to bizarre archeological remnants.

Interestingly, I suspect that most people never noticed the brokenness,
because most people trying to do serious Win32 UI stuff wind up linking
in cgo, if not for actually using C, then just to have a larger system
stack so that the stack doesn't get corrupted by various UI functions.
When MingW is used, the PE header gets a later version. But recently
there's been a bug report of some people trying to do more modest UI
manipulation using SendInput in a setting where this cgo hack probably
isn't required, so they ran into the weird historical compatibility
stuff.

Fixes #31685

Change-Id: I54461ce820f6e9df349e37be5ecc5a44c04a3e26
Reviewed-on: https://go-review.googlesource.com/c/go/+/178977
Run-TryBot: Jason Donenfeld <Jason@zx2c4.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Jason A. Donenfeld 2019-05-26 15:28:05 +02:00 committed by Brad Fitzpatrick
parent e12efecfa7
commit e883d000f4

View File

@ -833,18 +833,18 @@ func (f *peFile) writeOptionalHeader(ctxt *Link) {
oh.SectionAlignment = uint32(PESECTALIGN) oh.SectionAlignment = uint32(PESECTALIGN)
oh64.FileAlignment = uint32(PEFILEALIGN) oh64.FileAlignment = uint32(PEFILEALIGN)
oh.FileAlignment = uint32(PEFILEALIGN) oh.FileAlignment = uint32(PEFILEALIGN)
oh64.MajorOperatingSystemVersion = 4 oh64.MajorOperatingSystemVersion = 6
oh.MajorOperatingSystemVersion = 4 oh.MajorOperatingSystemVersion = 6
oh64.MinorOperatingSystemVersion = 0 oh64.MinorOperatingSystemVersion = 1
oh.MinorOperatingSystemVersion = 0 oh.MinorOperatingSystemVersion = 1
oh64.MajorImageVersion = 1 oh64.MajorImageVersion = 1
oh.MajorImageVersion = 1 oh.MajorImageVersion = 1
oh64.MinorImageVersion = 0 oh64.MinorImageVersion = 0
oh.MinorImageVersion = 0 oh.MinorImageVersion = 0
oh64.MajorSubsystemVersion = 4 oh64.MajorSubsystemVersion = 6
oh.MajorSubsystemVersion = 4 oh.MajorSubsystemVersion = 6
oh64.MinorSubsystemVersion = 0 oh64.MinorSubsystemVersion = 1
oh.MinorSubsystemVersion = 0 oh.MinorSubsystemVersion = 1
oh64.SizeOfImage = f.nextSectOffset oh64.SizeOfImage = f.nextSectOffset
oh.SizeOfImage = f.nextSectOffset oh.SizeOfImage = f.nextSectOffset
oh64.SizeOfHeaders = uint32(PEFILEHEADR) oh64.SizeOfHeaders = uint32(PEFILEHEADR)