aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmd/link/internal/ld/pe.go165
-rw-r--r--src/runtime/cgo/gcc_libinit_windows.c23
-rw-r--r--src/runtime/syscall_windows_test.go15
3 files changed, 201 insertions, 2 deletions
diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go
index 8184a32f83..3b97061aa0 100644
--- a/src/cmd/link/internal/ld/pe.go
+++ b/src/cmd/link/internal/ld/pe.go
@@ -151,9 +151,139 @@ const (
IMAGE_REL_BASED_DIR64 = 10
)
+// IMAGE_LOAD_CONFIG_DIRECTORY64.GuardFlags and IMAGE_LOAD_CONFIG_DIRECTORY32.GuardFlags
+// values. These can be combined together.
const (
- PeMinimumTargetMajorVersion = 6
- PeMinimumTargetMinorVersion = 1
+ IMAGE_GUARD_CF_INSTRUMENTED = 0x00000100 // Module performs control flow integrity checks using system-supplied support
+ IMAGE_GUARD_CFW_INSTRUMENTED = 0x00000200 // Module performs control flow and write integrity checks
+ IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT = 0x00000400 // Module contains valid control flow target metadata
+ IMAGE_GUARD_SECURITY_COOKIE_UNUSED = 0x00000800 // Module does not make use of the /GS security cookie
+ IMAGE_GUARD_PROTECT_DELAYLOAD_IAT = 0x00001000 // Module supports read only delay load IAT
+ IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION = 0x00002000 // Delayload import table in its own .didat section (with nothing else in it) that can be freely reprotected
+ IMAGE_GUARD_CF_EXPORT_SUPPRESSION_INFO_PRESENT = 0x00004000 // Module contains suppressed export information
+ IMAGE_GUARD_CF_ENABLE_EXPORT_SUPPRESSION = 0x00008000 // Module enables suppression of exports
+ IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT = 0x00010000 // Module contains longjmp target information
+ IMAGE_GUARD_RF_INSTRUMENTED = 0x00020000 // Module contains return flow instrumentation and metadata
+ IMAGE_GUARD_RF_ENABLE = 0x00040000 // Module requests that the OS enable return flow protection
+ IMAGE_GUARD_RF_STRICT = 0x00080000 // Module requests that the OS enable return flow protection in strict mode
+ IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK = 0xF0000000 // Stride of Guard CF function table encoded in these bits (additional count of bytes per element)
+ IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT = 28 // Shift to right-justify Guard CF function table stride
+)
+
+type IMAGE_LOAD_CONFIG_CODE_INTEGRITY struct {
+ Flags uint16
+ Catalog uint16
+ CatalogOffset uint32
+ Reserved uint32
+}
+
+type IMAGE_LOAD_CONFIG_DIRECTORY32 struct {
+ Size uint32
+ TimeDateStamp uint32
+ MajorVersion uint16
+ MinorVersion uint16
+ GlobalFlagsClear uint32
+ GlobalFlagsSet uint32
+ CriticalSectionDefaultTimeout uint32
+ DeCommitFreeBlockThreshold uint32
+ DeCommitTotalFreeThreshold uint32
+ LockPrefixTable uint32
+ MaximumAllocationSize uint32
+ VirtualMemoryThreshold uint32
+ ProcessHeapFlags uint32
+ ProcessAffinityMask uint32
+ CSDVersion uint16
+ DependentLoadFlags uint16
+ EditList uint32
+ SecurityCookie uint32
+ SEHandlerTable uint32
+ SEHandlerCount uint32
+ GuardCFCheckFunctionPointer uint32
+ GuardCFDispatchFunctionPointer uint32
+ GuardCFFunctionTable uint32
+ GuardCFFunctionCount uint32
+ GuardFlags uint32
+ CodeIntegrity IMAGE_LOAD_CONFIG_CODE_INTEGRITY
+ GuardAddressTakenIatEntryTable uint32
+ GuardAddressTakenIatEntryCount uint32
+ GuardLongJumpTargetTable uint32
+ GuardLongJumpTargetCount uint32
+ DynamicValueRelocTable uint32
+ CHPEMetadataPointer uint32
+ GuardRFFailureRoutine uint32
+ GuardRFFailureRoutineFunctionPointer uint32
+ DynamicValueRelocTableOffset uint32
+ DynamicValueRelocTableSection uint16
+ Reserved2 uint16
+ GuardRFVerifyStackPointerFunctionPointer uint32
+ HotPatchTableOffset uint32
+ Reserved3 uint32
+ EnclaveConfigurationPointer uint32
+ VolatileMetadataPointer uint32
+ GuardEHContinuationTable uint32
+ GuardEHContinuationCount uint32
+ GuardXFGCheckFunctionPointer uint32
+ GuardXFGDispatchFunctionPointer uint32
+ GuardXFGTableDispatchFunctionPointer uint32
+ CastGuardOsDeterminedFailureMode uint32
+ GuardMemcpyFunctionPointer uint32
+}
+
+type IMAGE_LOAD_CONFIG_DIRECTORY64 struct {
+ Size uint32
+ TimeDateStamp uint32
+ MajorVersion uint16
+ MinorVersion uint16
+ GlobalFlagsClear uint32
+ GlobalFlagsSet uint32
+ CriticalSectionDefaultTimeout uint32
+ DeCommitFreeBlockThreshold uint64
+ DeCommitTotalFreeThreshold uint64
+ LockPrefixTable uint64
+ MaximumAllocationSize uint64
+ VirtualMemoryThreshold uint64
+ ProcessAffinityMask uint64
+ ProcessHeapFlags uint32
+ CSDVersion uint16
+ DependentLoadFlags uint16
+ EditList uint64
+ SecurityCookie uint64
+ SEHandlerTable uint64
+ SEHandlerCount uint64
+ GuardCFCheckFunctionPointer uint64
+ GuardCFDispatchFunctionPointer uint64
+ GuardCFFunctionTable uint64
+ GuardCFFunctionCount uint64
+ GuardFlags uint32
+ CodeIntegrity IMAGE_LOAD_CONFIG_CODE_INTEGRITY
+ GuardAddressTakenIatEntryTable uint64
+ GuardAddressTakenIatEntryCount uint64
+ GuardLongJumpTargetTable uint64
+ GuardLongJumpTargetCount uint64
+ DynamicValueRelocTable uint64
+ CHPEMetadataPointer uint64
+ GuardRFFailureRoutine uint64
+ GuardRFFailureRoutineFunctionPointer uint64
+ DynamicValueRelocTableOffset uint32
+ DynamicValueRelocTableSection uint16
+ Reserved2 uint16
+ GuardRFVerifyStackPointerFunctionPointer uint64
+ HotPatchTableOffset uint32
+ Reserved3 uint32
+ EnclaveConfigurationPointer uint64
+ VolatileMetadataPointer uint64
+ GuardEHContinuationTable uint64
+ GuardEHContinuationCount uint64
+ GuardXFGCheckFunctionPointer uint64
+ GuardXFGDispatchFunctionPointer uint64
+ GuardXFGTableDispatchFunctionPointer uint64
+ CastGuardOsDeterminedFailureMode uint64
+ GuardMemcpyFunctionPointer uint64
+}
+
+const (
+ PeMinimumTargetMajorVersion = 10
+ PeMinimumTargetMinorVersion = 0
)
// DOS stub that prints out
@@ -1141,6 +1271,29 @@ func Peinit(ctxt *Link) {
ctxt.loader.SetAttrSpecial(sb.Sym(), true)
ctxt.loader.SetAttrLocal(sb.Sym(), true)
}
+
+ // The _load_config_used symbol is required to be present on modern
+ // Windows. We later wire this up to the PE data directory.
+ sb := ctxt.loader.CreateSymForUpdate("_load_config_used", 0)
+ sb.SetType(sym.SRODATA)
+ sb.SetAlign(int32(ctxt.Arch.PtrSize))
+ var buf bytes.Buffer
+ if pe64 {
+ lc := IMAGE_LOAD_CONFIG_DIRECTORY64{
+ Size: uint32(binary.Size(&IMAGE_LOAD_CONFIG_DIRECTORY64{})),
+ GuardFlags: IMAGE_GUARD_SECURITY_COOKIE_UNUSED,
+ }
+ binary.Write(&buf, binary.LittleEndian, &lc)
+ } else {
+ lc := IMAGE_LOAD_CONFIG_DIRECTORY32{
+ Size: uint32(binary.Size(&IMAGE_LOAD_CONFIG_DIRECTORY32{})),
+ GuardFlags: IMAGE_GUARD_SECURITY_COOKIE_UNUSED,
+ }
+ binary.Write(&buf, binary.LittleEndian, &lc)
+ }
+ sb.SetData(buf.Bytes())
+ sb.SetSize(int64(buf.Len()))
+ ctxt.loader.SetAttrReachable(sb.Sym(), true)
}
HEADR = PEFILEHEADR
@@ -1711,6 +1864,14 @@ func asmbPe(ctxt *Link) {
ro.checkSegment(&Segrodata)
pefile.rdataSect = ro
+ // This should have been added in Peinit and by now is part of the
+ // just-written .rdata section.
+ s := ctxt.loader.Lookup("_load_config_used", 0)
+ if s != 0 {
+ pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress = uint32(ctxt.loader.SymValue(s) - PEBASE)
+ pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size = uint32(ctxt.loader.SymSize(s))
+ }
+
var d *peSection
if ctxt.LinkMode != LinkExternal {
d = pefile.addSection(".data", int(Segdata.Length), int(Segdata.Filelen))
diff --git a/src/runtime/cgo/gcc_libinit_windows.c b/src/runtime/cgo/gcc_libinit_windows.c
index 78b32254cf..ed30878c3c 100644
--- a/src/runtime/cgo/gcc_libinit_windows.c
+++ b/src/runtime/cgo/gcc_libinit_windows.c
@@ -14,6 +14,29 @@
#include "libcgo.h"
+#define IMAGE_GUARD_SECURITY_COOKIE_UNUSED 0x00000800
+// With modern mingw, we can use the normal struct:
+//
+// const IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used = {
+// .Size = sizeof(_load_config_used),
+// .GuardFlags = IMAGE_GUARD_SECURITY_COOKIE_UNUSED
+// };
+//
+// But we support older toolchains, so instead, fix the offsets:
+#ifdef _WIN64
+const ULONGLONG _load_config_used[40] = {
+ sizeof(_load_config_used),
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ IMAGE_GUARD_SECURITY_COOKIE_UNUSED
+};
+#else
+const DWORD _load_config_used[48] = {
+ sizeof(_load_config_used),
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ IMAGE_GUARD_SECURITY_COOKIE_UNUSED
+};
+#endif
+
static volatile LONG runtime_init_once_gate = 0;
static volatile LONG runtime_init_once_done = 0;
diff --git a/src/runtime/syscall_windows_test.go b/src/runtime/syscall_windows_test.go
index 77092d8fbf..437c723d51 100644
--- a/src/runtime/syscall_windows_test.go
+++ b/src/runtime/syscall_windows_test.go
@@ -8,6 +8,7 @@ import (
"fmt"
"internal/abi"
"internal/race"
+ "internal/syscall/windows"
"internal/syscall/windows/sysdll"
"internal/testenv"
"io"
@@ -1226,6 +1227,20 @@ var (
procSetEvent = modkernel32.NewProc("SetEvent")
)
+func TestTrueVersion(t *testing.T) {
+ ver, err := syscall.GetVersion()
+ if err != nil {
+ t.Fatalf("GetVersion failed: %v", err)
+ }
+ wantMajor, wantMinor, wantBuild := windows.Version()
+ major := uint32(byte(ver))
+ minor := uint32(uint8(ver >> 8))
+ build := uint32(uint16(ver >> 16))
+ if major != wantMajor || minor != wantMinor || build != wantBuild {
+ t.Errorf("GetVersion = %d.%d (Build %d), want %d.%d (Build %d)", major, minor, build, wantMajor, wantMinor, wantBuild)
+ }
+}
+
func createEvent() (syscall.Handle, error) {
r0, _, e0 := syscall.Syscall6(procCreateEvent.Addr(), 4, 0, 0, 0, 0, 0, 0)
if r0 == 0 {