diff --git a/BaseTools/Source/C/GenFw/GenFw.c b/BaseTools/Source/C/GenFw/GenFw.c index 5893a8cfbd..808e1520da 100644 --- a/BaseTools/Source/C/GenFw/GenFw.c +++ b/BaseTools/Source/C/GenFw/GenFw.c @@ -443,6 +443,62 @@ Routine Description: return STATUS_SUCCESS; } +// MU_CHANGE begin +STATIC +BOOLEAN +IsNxCompatCompliant ( + EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr + ) +/*++ + +Routine Description: + + Checks if the Pe image is nxcompat. i.e. PE is 64bit, section alignment is + evenly divisible by 4k, and no section is writable and executable. + +Arguments: + + PeHdr The Pe header + +Returns: + + TRUE The PE is nx compat compliant + FALSE The PE is not nx compat compliant +--*/ +{ + EFI_IMAGE_SECTION_HEADER *SectionHeader; + UINT32 Index; + UINT32 Mask; + + // Must have an optional header to perform verification + if (PeHdr->Pe32.FileHeader.SizeOfOptionalHeader == 0) { + return FALSE; + } + + // Verify PE is 64 bit + if (!(PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC)) { + return FALSE; + } + + // Verify Section Alignment is divisible by 4K + if (!((PeHdr->Pe32Plus.OptionalHeader.SectionAlignment % EFI_PAGE_SIZE) == 0)) { + return FALSE; + } + + // Verify sections are not Write & Execute + Mask = EFI_IMAGE_SCN_MEM_EXECUTE | EFI_IMAGE_SCN_MEM_WRITE; + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32Plus.OptionalHeader) + PeHdr->Pe32Plus.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32Plus.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { + if ((SectionHeader->Characteristics & Mask) == Mask) { + return FALSE; + } + } + + // Passed all requirements, return TRUE + return TRUE; +} +// MU_CHANGE end + VOID SetHiiResourceHeader ( UINT8 *HiiBinData, @@ -2466,6 +2522,13 @@ Routine Description: TEImageHeader.BaseOfCode = Optional64->BaseOfCode; TEImageHeader.ImageBase = (UINT64) (Optional64->ImageBase); + // MU_CHANGE begin + // Set NxCompat flag + if (IsNxCompatCompliant (PeHdr)) { + Optional64->DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_NX_COMPAT; + } + // MU_CHANGE end + if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; diff --git a/BaseTools/Source/C/Include/IndustryStandard/PeImage.h b/BaseTools/Source/C/Include/IndustryStandard/PeImage.h index 0cccb623b4..1b2658fb8b 100644 --- a/BaseTools/Source/C/Include/IndustryStandard/PeImage.h +++ b/BaseTools/Source/C/Include/IndustryStandard/PeImage.h @@ -286,6 +286,23 @@ typedef struct { #define EFI_IMAGE_SUBSYSTEM_OS2_CUI 5 #define EFI_IMAGE_SUBSYSTEM_POSIX_CUI 7 +// MU_CHANGE begin +// +// DLL Characteristics +// +#define IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA 0x0020 +#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040 +#define IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY 0x0080 +#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100 +#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200 +#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400 +#define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800 +#define IMAGE_DLLCHARACTERISTICS_APPCONTAINER 0x1000 +#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000 +#define IMAGE_DLLCHARACTERISTICS_GUARD_CF 0x4000 +#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000 +// MU_CHANGE end + // // Directory Entries //