Skip to content

Commit

Permalink
Add NX Support
Browse files Browse the repository at this point in the history
  • Loading branch information
TaylorBeebe authored and kenlautner committed May 4, 2023
1 parent 9b8e480 commit 66c6c8a
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 47 deletions.
84 changes: 42 additions & 42 deletions BaseTools/Conf/tools_def.template

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions MdeModulePkg/Core/Dxe/Image/Image.c
Expand Up @@ -8,6 +8,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent

#include "DxeMain.h"
#include "Image.h"
#include "MemoryProtectionSupport.h" // MU_CHANGE

//
// Module Globals
Expand Down Expand Up @@ -580,6 +581,10 @@ CoreIsImageTypeSupported (
relocate the PE/COFF file
@retval EFI_INVALID_PARAMETER Invalid parameter
@retval EFI_BUFFER_TOO_SMALL Buffer for image is too small
// MU_CHANGE START
@retval EFI_SECURITY_VIOLATION NXCOMPAT flag not set on image and it is
of subsystem type EFI_APPLICATION
// MU_CHANGE END
**/
EFI_STATUS
Expand Down Expand Up @@ -646,6 +651,20 @@ CoreLoadPeImage (
return EFI_UNSUPPORTED;
}

// MU_CHANGE START
// If the image doesn't have the NXCOMPAT flag and is an EFI_APPLICATION subsystem, it could be a boot
// loader or 3rd party binary which isn't NX aware. Because of this, we need to ensure future allocations
// of code memory types aren't set to NX in case this image does its own allocations.
// Or, if our memory protection policy specifies that we shouldn't allow such images, return a failure.
if (!(Image->ImageContext.SupportsNx) && (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)) {
if (gDxeMps.ImageProtectionPolicy.Fields.BlockImagesWithoutNxFlag) {
return EFI_SECURITY_VIOLATION;
}

TurnOffNxCompatibility ();
}

// MU_CHANGE END
//
// Allocate memory of the correct memory type aligned on the required image boundary
//
Expand Down
9 changes: 7 additions & 2 deletions MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
Expand Up @@ -708,11 +708,16 @@ GetPermissionAttributeForMemoryType (
// } else {
// return 0;
// }
if (GetDxeMemoryTypeSettingFromBitfield (MemoryType, gDxeMps.NxProtectionPolicy)) {

// Handle code allocations according to the NX_COMPAT DLL flag. If the flag is
// set, the image should update the attributes of code type allocates when it's ready to execute them.
if (IsCodeType (MemoryType) && !IsSystemNxCompatible ()) {
return 0;
} else if (GetDxeMemoryTypeSettingFromBitfield (MemoryType, gDxeMps.NxProtectionPolicy)) {
return EFI_MEMORY_XP;
}

return 0;
return 0;

// MU_CHANGE END
}
Expand Down
30 changes: 30 additions & 0 deletions MdeModulePkg/Core/Dxe/Misc/MemoryProtectionSupport.c
Expand Up @@ -25,6 +25,7 @@ MEMORY_PROTECTION_SPECIAL_REGION_PRIVATE_LIST_HEAD mSpecialMemoryRegionsPrivate
INITIALIZE_LIST_HEAD_VARIABLE (mSpecialMemoryRegionsPrivate.SpecialRegionList)
};

BOOLEAN mIsSystemNxCompatible = TRUE;
#define IS_BITMAP_INDEX_SET(Bitmap, Index) ((((UINT8*)Bitmap)[Index / 8] & (1 << (Index % 8))) != 0 ? TRUE : FALSE)
#define SET_BITMAP_INDEX(Bitmap, Index) (((UINT8*)Bitmap)[Index / 8] |= (1 << (Index % 8)))

Expand Down Expand Up @@ -3126,3 +3127,32 @@ GetDxeMemoryProtectionSettings (

return NULL;
}

/**
Sets the NX compatibility global to FALSE so future checks to
IsSystemNxCompatible() will return FALSE.
**/
VOID
EFIAPI
TurnOffNxCompatibility (
VOID
)
{
if (mIsSystemNxCompatible) {
DEBUG ((DEBUG_INFO, "%a - Setting Nx on Code types to FALSE\n", __FUNCTION__));
}

mIsSystemNxCompatible = FALSE;
}

/**
Returns TRUE if TurnOffNxCompatibility() has never been called.
**/
BOOLEAN
EFIAPI
IsSystemNxCompatible (
VOID
)
{
return mIsSystemNxCompatible;
}
19 changes: 19 additions & 0 deletions MdeModulePkg/Core/Dxe/Misc/MemoryProtectionSupport.h
Expand Up @@ -128,4 +128,23 @@ MemoryProtectionCpuArchProtocolNotifyMu (
IN VOID *Context
);

/**
Sets the NX compatibility global to FALSE so future checks to
IsSystemNxCompatible() will return FALSE.
**/
VOID
EFIAPI
TurnOffNxCompatibility (
VOID
);

/**
Returns TRUE if TurnOffNxCompatibility() has never been called.
**/
BOOLEAN
EFIAPI
IsSystemNxCompatible (
VOID
);

#endif
6 changes: 3 additions & 3 deletions MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf
Expand Up @@ -54,7 +54,7 @@
## MS_CHANGE_211478
## MSChange [BEGIN] - This is necessary to avoid the alignment change introduced with the Memory Attributes Table
[BuildOptions.X64]
MSFT:DEBUG_*_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
MSFT:RELEASE_*_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
MSFT:NOOPT_*_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
MSFT:DEBUG_*_X64_DLINK_FLAGS == /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
MSFT:RELEASE_*_X64_DLINK_FLAGS == /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.data=.text /MERGE:.rdata=.text
MSFT:NOOPT_*_X64_DLINK_FLAGS == /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG
## MSChange [END]
7 changes: 7 additions & 0 deletions MdePkg/Include/IndustryStandard/PeImage.h
Expand Up @@ -108,6 +108,13 @@ typedef struct {
#define EFI_IMAGE_FILE_DLL BIT13 ///< 0x2000 File is a DLL.
#define EFI_IMAGE_FILE_BYTES_REVERSED_HI BIT15 ///< 0x8000 Bytes of machine word are reversed.

// MU_CHANGE START
//
// DLL Characteristics
//
#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT BIT8 ///< 0x0100 Image is NX compatible
// MU_CHANGE END

///
/// Header Data Directories.
///
Expand Down
7 changes: 7 additions & 0 deletions MdePkg/Include/Library/PeCoffLib.h
Expand Up @@ -181,6 +181,13 @@ typedef struct {
/// Initialization Core Interface Specification.
///
BOOLEAN IsTeImage;
// MU_CHANGE START
///
/// Set by PeCoffLoaderGetImageInfo() to TRUE if the image has the IMAGE_DLLCHARACTERISTICS_NX_COMPAT
/// flag set.
///
BOOLEAN SupportsNx;
// MU_CHANGE END
///
/// Set by PeCoffLoaderLoadImage() to the HII resource offset
/// if the image contains a custom PE/COFF resource with the type 'HII'.
Expand Down
14 changes: 14 additions & 0 deletions MdePkg/Library/BasePeCoffLib/BasePeCoff.c
Expand Up @@ -633,6 +633,8 @@ PeCoffLoaderGetImageInfo (
//
ImageContext->ImageError = IMAGE_ERROR_SUCCESS;

ImageContext->SupportsNx = TRUE; // MU_CHANGE

Hdr.Union = &HdrData;
Status = PeCoffLoaderGetPeHeader (ImageContext, Hdr);
if (RETURN_ERROR (Status)) {
Expand Down Expand Up @@ -699,12 +701,24 @@ PeCoffLoaderGetImageInfo (
//
NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
// MU_CHANGE START
if (!(Hdr.Pe32->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NX_COMPAT)) {
ImageContext->SupportsNx = FALSE;
}

// MU_CHANGE END
} else {
//
// Use PE32+ offset
//
NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
// MU_CHANGE START
if (!(Hdr.Pe32Plus->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NX_COMPAT)) {
ImageContext->SupportsNx = FALSE;
}

// MU_CHANGE END
}

if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
Expand Down

0 comments on commit 66c6c8a

Please sign in to comment.