From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-oi1-f180.google.com (mail-oi1-f180.google.com [209.85.167.180]) by mx.groups.io with SMTP id smtpd.web10.1849.1689119584786239016 for ; Tue, 11 Jul 2023 16:53:05 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="signature has expired" header.i=@taylorbeebe.com header.s=google header.b=MtegC1DZ; spf=pass (domain: taylorbeebe.com, ip: 209.85.167.180, mailfrom: t@taylorbeebe.com) Received: by mail-oi1-f180.google.com with SMTP id 5614622812f47-3a1d9b64837so5154204b6e.0 for ; Tue, 11 Jul 2023 16:53:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=taylorbeebe.com; s=google; t=1689119584; x=1691711584; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Hc6PIB1Noel61R+dmzdtqUqZHb+lhvT/hPrj1N9tMuc=; b=MtegC1DZ6xHxnvGZiQ/RrQrb+0AJAxGWpjk4l0h6SpPOR9aJxskSRbzp9gdF7lSzkA kdB4BxwIIPzo73pJI3FmhGqgSOUp+gzXgJkq2sbA8aTjtK93xPYy2Yp0Z9B1o54pkju6 +bMubgNpi7PloMW/e2YTRrAYCYR6e6/tmpngfae3xILvMvS1F/kitNiEm+J0E0siGv+s ssIuI/PrR9zf8ESPwyqfonemaFT1HFcc7gkpotDLVpKLdNegEHyJ86v2dpIlc2IBG2AW xkQ9mQCyxGBYbWDsezpgNSUpHfrID524U1cjO1iee1/94xMMmJlBFVHGLRnNxbzyvCjl UgLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1689119584; x=1691711584; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Hc6PIB1Noel61R+dmzdtqUqZHb+lhvT/hPrj1N9tMuc=; b=ivLK0QklWOUCe0cyhSDh6FGNzJ5tphZBaztPz2gMtsLA9kKvzVAUWC3Il2ns/0824M 5LcZKk3cmxAyzH6rqagAEtdudeSD6djI7abTzcXBWbzJv6iPC/zJDlqfDRI8f6ejg+0S +y6StObHgGQZVGZM8TerZpEEvrwXuYv+419do5sP7TLaCXmBDpoexHsVhqXupXdqmtep xpisDRPF4cYNmP7LGArxT44rRMT28ztjT87fbRzyKPklKsOXIBqo2ynDitKVa2VHF4sB /HAfWEbAm148YVVfB1lMUGoaRb0qMiNbuSuXHBH7YOWhzdpcrpnbNv+S4UQpmiyHTrrd B0pw== X-Gm-Message-State: ABy/qLZEGiHm3e1/PlwAo21ZAe0cPWXMIZoWoAsPx2kYbt4uAxr0GKAX UgzgGoHYFMxBiOH6Jk5Va7Uozj+7JWoYa9hpN/2jkA== X-Google-Smtp-Source: APBJJlFAd9MK43ufCVwXqZ66N8XHV7yVHQ7CcScfgeoeCNujots5ILjs5ZWnsDtsixFgOE81CsPbvQ== X-Received: by 2002:a05:6808:3008:b0:3a3:f289:8205 with SMTP id ay8-20020a056808300800b003a3f2898205mr13185060oib.35.1689119583755; Tue, 11 Jul 2023 16:53:03 -0700 (PDT) Return-Path: Received: from localhost.localdomain ([50.46.230.135]) by smtp.gmail.com with ESMTPSA id a13-20020a62e20d000000b00660d80087a8sm2232677pfi.187.2023.07.11.16.53.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Jul 2023 16:53:03 -0700 (PDT) From: "Taylor Beebe" To: devel@edk2.groups.io Cc: Jian J Wang , Liming Gao , Dandan Bi Subject: [PATCH 01/14] MdeModulePkg: Add DXE and MM Memory Protection Settings Definitions Date: Tue, 11 Jul 2023 16:52:38 -0700 Message-ID: <90e3068695d8dc23c940e7f8ad00a7efc6d91bd6.1689101263.git.t@taylorbeebe.com> X-Mailer: git-send-email 2.41.0.windows.2 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Taylor Beebe These headers provide settings definitions for memory protections, settings profiles for easily enabling memory protections, and the GUIDs used for producing the memory protection HOB. The settings options are functionally 1:1 with the existing PCD bitfield definitions. Instead of setting a fixed at build PCD, memory protection settings will be created via a HOB at runtime. Signed-off-by: Taylor Beebe Cc: Jian J Wang Cc: Liming Gao Cc: Dandan Bi --- .../Guid/DxeMemoryProtectionSettings.h | 413 ++++++++++++++++++ .../Include/Guid/MmMemoryProtectionSettings.h | 211 +++++++++ MdeModulePkg/MdeModulePkg.dec | 10 + 3 files changed, 634 insertions(+) create mode 100644 MdeModulePkg/Include/Guid/DxeMemoryProtectionSettings.h create mode 100644 MdeModulePkg/Include/Guid/MmMemoryProtectionSettings.h diff --git a/MdeModulePkg/Include/Guid/DxeMemoryProtectionSettings.h b/MdeModulePkg/Include/Guid/DxeMemoryProtectionSettings.h new file mode 100644 index 0000000000..93144494d5 --- /dev/null +++ b/MdeModulePkg/Include/Guid/DxeMemoryProtectionSettings.h @@ -0,0 +1,413 @@ +/** @file + +Defines memory protection settings guid and struct for DXE. + +Copyright (C) Microsoft Corporation. All rights reserved. +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef DXE_MEMORY_PROTECTION_SETTINGS_H_ +#define DXE_MEMORY_PROTECTION_SETTINGS_H_ + +#include + +// Current iteration of DXE_MEMORY_PROTECTION_SETTINGS +#define DXE_MEMORY_PROTECTION_SETTINGS_CURRENT_VERSION 1 + +#define OEM_RESERVED_MPS_MEMORY_TYPE EfiMaxMemoryType +#define OS_RESERVED_MPS_MEMORY_TYPE (EfiMaxMemoryType + 1) +#define MAX_DXE_MPS_MEMORY_TYPE (EfiMaxMemoryType + 2) +#define DXE_MPS_MEMORY_TYPE_BUFFER_SIZE (MAX_DXE_MPS_MEMORY_TYPE * sizeof (BOOLEAN)) + +typedef struct { + BOOLEAN Enabled : 1; + BOOLEAN DisableEndOfDxe : 1; + BOOLEAN NonstopModeEnabled : 1; +} DXE_NULL_DETECTION_POLICY; + +typedef struct { + BOOLEAN ProtectImageFromUnknown : 1; + BOOLEAN ProtectImageFromFv : 1; +} DXE_IMAGE_PROTECTION_POLICY; + +typedef struct { + BOOLEAN PageGuardEnabled : 1; + BOOLEAN PoolGuardEnabled : 1; + BOOLEAN FreedMemoryGuardEnabled : 1; + BOOLEAN NonstopModeEnabled : 1; + BOOLEAN GuardAlignedToTail : 1; +} DXE_HEAP_GUARD_POLICY; + +typedef struct { + BOOLEAN EnabledForType[MAX_DXE_MPS_MEMORY_TYPE]; +} DXE_MPS_MEMORY_TYPES; + +typedef UINT8 DXE_MEMORY_PROTECTION_SETTINGS_VERSION; + +// +// Memory Protection Settings struct +// +typedef struct { + // The current version of the structure definition. This is used to ensure there isn't a + // definition mismatch if modules have differing iterations of this header. When creating + // this struct, use the DXE_MEMORY_PROTECTION_SETTINGS_CURRENT_VERSION macro. + DXE_MEMORY_PROTECTION_SETTINGS_VERSION StructVersion; + + // If enabled, the page at the top of the stack will be invalidated to catch stack overflow. + BOOLEAN CpuStackGuardEnabled; + + // If enabled, the stack will be marked non-executable. + BOOLEAN StackExecutionProtectionEnabled; + + // If enabled, accessing the NULL address in UEFI will be caught by marking + // the NULL page as not present. + // .NullDetectionEnabled : Enable NULL pointer detection. + // .DisableEndOfDxe : Disable NULL pointer detection just after EndOfDxe. + // This is a workaround for those unsolvable NULL access issues in + // OptionROM, boot loader, etc. It can also help to avoid unnecessary + // exception caused by legacy memory (0-4095) access after EndOfDxe, + // such as Windows 7 boot on Qemu. + // .NonstopModeEnabled : If enabled the debug flag will be raised when a fault occurs + // to break into debugger. + DXE_NULL_DETECTION_POLICY NullPointerDetection; + + // Set image protection policy. + // + // .ProtectImageFromUnknown : If set, images from unknown devices will be protected by + // DxeCore if they are aligned. The code section becomes + // read-only, and the data section becomes non-executable. + // .ProtectImageFromFv : If set, images from firmware volumes will be protected by + // DxeCore if they are aligned. The code section becomes + // read-only, and the data section becomes non-executable. + DXE_IMAGE_PROTECTION_POLICY ImageProtection; + + // If a bit is set, memory regions of the associated type will be mapped non-executable. + // + // The execution protection setting for EfiBootServicesData and EfiConventionalMemory must + // be the same. + DXE_MPS_MEMORY_TYPES ExecutionProtection; + + // Configures general heap guard behavior. + // + // .PageGuardEnabled : Enable page guard. + // .PoolGuardEnabled : Enable pool guard. + // .FreedMemoryGuardEnabled : Enable freed-memory guard (Use-After-Free memory detection). + // .NonstopModeEnabled : If enabled the debug flag will be raised when a fault occurs + // to break into debugger. + // .GuardAlignedToTail : TRUE if the pool is aligned to tail guard page. If FALSE, the + // pool is aligned to head guard page. + // + // Note: + // a) Due to the limit of pool memory implementation and the alignment + // requirement of UEFI spec, HeapGuard.GuardAlignedToTail is a try-best + // setting which cannot guarantee that the returned pool is exactly + // adjacent to head or tail guard page. + // b) Freed-memory guard and pool/page guard cannot be enabled + // at the same time. + DXE_HEAP_GUARD_POLICY HeapGuard; + + // Indicates which type allocation need guard page. + // + // If bit is set, a head guard page and a tail guard page will be added just + // before and after corresponding type of pages which the allocated pool occupies, + // if there's enough free memory for all of them. + // + // These settings are only valid if HeapGuard.PoolGuardEnabled is TRUE. + DXE_MPS_MEMORY_TYPES PoolGuard; + + // Indicates which type allocation need guard page. + // + // If a bit is set, a head guard page and a tail guard page will be added just + // before and after corresponding type of pages allocated if there's enough + // free pages for all of them. + // + // These settings are only valid if HeapGuard.PageGuardEnabled is TRUE. + DXE_MPS_MEMORY_TYPES PageGuard; +} DXE_MEMORY_PROTECTION_SETTINGS; + +#define DXE_MPS_IS_STRUCT_VALID(DxeMpsPtr) \ + (((DXE_MEMORY_PROTECTION_SETTINGS *)DxeMpsPtr)->StructVersion == DXE_MEMORY_PROTECTION_SETTINGS_CURRENT_VERSION) + +#define DXE_MPS_IS_ANY_MEMORY_TYPE_ACTIVE(MpsMemoryTypesPtr) \ + (!IsZeroBuffer (&((DXE_MPS_MEMORY_TYPES *)MpsMemoryTypesPtr)->EnabledForType, DXE_MPS_MEMORY_TYPE_BUFFER_SIZE)) + +#define DXE_MPS_IS_IMAGE_PROTECTION_ENABLED(DxeMpsPtr) \ + (((DXE_MEMORY_PROTECTION_SETTINGS*)DxeMpsPtr)->ImageProtection.ProtectImageFromFv || \ + ((DXE_MEMORY_PROTECTION_SETTINGS*)DxeMpsPtr)->ImageProtection.ProtectImageFromUnknown) + +#define DXE_MPS_IS_EXECUTION_PROTECTION_ENABLED(DxeMpsPtr) \ + DXE_MPS_IS_ANY_MEMORY_TYPE_ACTIVE(&((DXE_MEMORY_PROTECTION_SETTINGS*)DxeMpsPtr)->ExecutionProtection) + +#define DXE_MPS_ARE_PAGE_GUARDS_ENABLED(DxeMpsPtr) \ + (((DXE_MEMORY_PROTECTION_SETTINGS*)DxeMpsPtr)->HeapGuard.PageGuardEnabled && \ + DXE_MPS_IS_ANY_MEMORY_TYPE_ACTIVE(&((DXE_MEMORY_PROTECTION_SETTINGS*)DxeMpsPtr)->PageGuard)) + +#define DXE_MPS_ARE_POOL_GUARDS_ENABLED(DxeMpsPtr) \ + (((DXE_MEMORY_PROTECTION_SETTINGS*)DxeMpsPtr)->HeapGuard.PoolGuardEnabled && \ + DXE_MPS_IS_ANY_MEMORY_TYPE_ACTIVE(&((DXE_MEMORY_PROTECTION_SETTINGS*)DxeMpsPtr)->PoolGuard)) + +#define DXE_MPS_IS_MEMORY_PROTECTION_ACTIVE(DxeMpsPtr) \ + (DXE_MPS_IS_STRUCT_VALID(DxeMpsPtr) && \ + (((DXE_MEMORY_PROTECTION_SETTINGS*)DxeMpsPtr)->CpuStackGuardEnabled || \ + ((DXE_MEMORY_PROTECTION_SETTINGS*)DxeMpsPtr)->StackExecutionProtectionEnabled || \ + ((DXE_MEMORY_PROTECTION_SETTINGS*)DxeMpsPtr)->NullPointerDetection.Enabled || \ + DXE_MPS_IS_IMAGE_PROTECTION_ENABLED(DxeMpsPtr) || \ + DXE_MPS_IS_EXECUTION_PROTECTION_ENABLED(DxeMpsPtr) || \ + DXE_MPS_ARE_PAGE_GUARDS_ENABLED(DxeMpsPtr) || \ + DXE_MPS_ARE_POOL_GUARDS_ENABLED(DxeMpsPtr)) \ + ) + +#define HOB_DXE_MEMORY_PROTECTION_SETTINGS_GUID \ + { \ + { 0x9ABFD639, 0xD1D0, 0x4EFF, { 0xBD, 0xB6, 0x7E, 0xC4, 0x19, 0x0D, 0x17, 0xD5 } } \ + } + +extern GUID gDxeMemoryProtectionSettingsGuid; + +// +// A memory profile with strict settings ideal for development scenarios. +// +#define DXE_MEMORY_PROTECTION_SETTINGS_DEBUG { \ + DXE_MEMORY_PROTECTION_SETTINGS_CURRENT_VERSION, \ + TRUE, /* Stack Guard */ \ + TRUE, /* Stack Execution Protection */ \ + { /* NULL Pointer Detection */ \ + .Enabled = TRUE, \ + .DisableEndOfDxe = FALSE, \ + .NonstopModeEnabled = TRUE \ + }, \ + { /* Image Protection */ \ + .ProtectImageFromUnknown = TRUE, \ + .ProtectImageFromFv = TRUE \ + }, \ + { /* Execution Protection */ \ + .EnabledForType = { \ + [EfiReservedMemoryType] = TRUE, \ + [EfiLoaderCode] = FALSE, \ + [EfiLoaderData] = TRUE, \ + [EfiBootServicesCode] = FALSE, \ + [EfiBootServicesData] = TRUE, \ + [EfiRuntimeServicesCode] = FALSE, \ + [EfiRuntimeServicesData] = TRUE, \ + [EfiConventionalMemory] = TRUE, \ + [EfiUnusableMemory] = TRUE, \ + [EfiACPIReclaimMemory] = TRUE, \ + [EfiACPIMemoryNVS] = TRUE, \ + [EfiMemoryMappedIO] = TRUE, \ + [EfiMemoryMappedIOPortSpace] = TRUE, \ + [EfiPalCode] = TRUE, \ + [EfiPersistentMemory] = FALSE, \ + [EfiUnacceptedMemoryType] = TRUE, \ + [OEM_RESERVED_MPS_MEMORY_TYPE] = TRUE, \ + [OS_RESERVED_MPS_MEMORY_TYPE] = TRUE \ + } \ + }, \ + { /* Heap Guard */ \ + .PageGuardEnabled = TRUE, \ + .PoolGuardEnabled = TRUE, \ + .FreedMemoryGuardEnabled = FALSE, \ + .NonstopModeEnabled = TRUE, \ + .GuardAlignedToTail = FALSE \ + }, \ + { /* Pool Guard */ \ + .EnabledForType = { \ + [EfiReservedMemoryType] = TRUE, \ + [EfiLoaderCode] = TRUE, \ + [EfiLoaderData] = TRUE, \ + [EfiBootServicesCode] = TRUE, \ + [EfiBootServicesData] = TRUE, \ + [EfiRuntimeServicesCode] = TRUE, \ + [EfiRuntimeServicesData] = TRUE, \ + [EfiConventionalMemory] = FALSE, \ + [EfiUnusableMemory] = TRUE, \ + [EfiACPIReclaimMemory] = TRUE, \ + [EfiACPIMemoryNVS] = TRUE, \ + [EfiMemoryMappedIO] = TRUE, \ + [EfiMemoryMappedIOPortSpace] = TRUE, \ + [EfiPalCode] = TRUE, \ + [EfiPersistentMemory] = FALSE, \ + [EfiUnacceptedMemoryType] = TRUE, \ + [OEM_RESERVED_MPS_MEMORY_TYPE] = TRUE, \ + [OS_RESERVED_MPS_MEMORY_TYPE] = TRUE \ + } \ + }, \ + { /* Page Guard */ \ + .EnabledForType = { \ + [EfiReservedMemoryType] = TRUE, \ + [EfiLoaderCode] = TRUE, \ + [EfiLoaderData] = TRUE, \ + [EfiBootServicesCode] = TRUE, \ + [EfiBootServicesData] = TRUE, \ + [EfiRuntimeServicesCode] = TRUE, \ + [EfiRuntimeServicesData] = TRUE, \ + [EfiConventionalMemory] = FALSE, \ + [EfiUnusableMemory] = TRUE, \ + [EfiACPIReclaimMemory] = TRUE, \ + [EfiACPIMemoryNVS] = TRUE, \ + [EfiMemoryMappedIO] = TRUE, \ + [EfiMemoryMappedIOPortSpace] = TRUE, \ + [EfiPalCode] = TRUE, \ + [EfiPersistentMemory] = FALSE, \ + [EfiUnacceptedMemoryType] = TRUE, \ + [OEM_RESERVED_MPS_MEMORY_TYPE] = TRUE, \ + [OS_RESERVED_MPS_MEMORY_TYPE] = TRUE \ + } \ + } \ + }; + +// +// A memory profile recommended for production. Compared to the debug +// settings, this profile removes the pool guards and uses page guards +// for fewer memory types. +// +#define DXE_MEMORY_PROTECTION_SETTINGS_PROD_MODE \ + { \ + DXE_MEMORY_PROTECTION_SETTINGS_CURRENT_VERSION, \ + TRUE, /* Stack Guard */ \ + TRUE, /* Stack Execution Protection */ \ + { /* NULL Pointer Detection */ \ + .Enabled = TRUE, \ + .DisableEndOfDxe = FALSE, \ + .NonstopModeEnabled = FALSE \ + }, \ + { /* Image Protection */ \ + .ProtectImageFromUnknown = FALSE, \ + .ProtectImageFromFv = TRUE \ + }, \ + { /* Execution Protection */ \ + .EnabledForType = { \ + [EfiReservedMemoryType] = TRUE, \ + [EfiLoaderCode] = FALSE, \ + [EfiLoaderData] = TRUE, \ + [EfiBootServicesCode] = FALSE, \ + [EfiBootServicesData] = TRUE, \ + [EfiRuntimeServicesCode] = FALSE, \ + [EfiRuntimeServicesData] = TRUE, \ + [EfiConventionalMemory] = TRUE, \ + [EfiUnusableMemory] = TRUE, \ + [EfiACPIReclaimMemory] = TRUE, \ + [EfiACPIMemoryNVS] = TRUE, \ + [EfiMemoryMappedIO] = TRUE, \ + [EfiMemoryMappedIOPortSpace] = TRUE, \ + [EfiPalCode] = TRUE, \ + [EfiPersistentMemory] = FALSE, \ + [EfiUnacceptedMemoryType] = TRUE, \ + [OEM_RESERVED_MPS_MEMORY_TYPE] = TRUE, \ + [OS_RESERVED_MPS_MEMORY_TYPE] = TRUE \ + } \ + }, \ + { /* Heap Guard */ \ + .PageGuardEnabled = TRUE, \ + .PoolGuardEnabled = FALSE, \ + .FreedMemoryGuardEnabled = FALSE, \ + .NonstopModeEnabled = FALSE, \ + .GuardAlignedToTail = FALSE \ + }, \ + { /* Pool Guard */ \ + 0 \ + }, \ + { /* Page Guard */ \ + .EnabledForType = { \ + [EfiReservedMemoryType] = FALSE, \ + [EfiLoaderCode] = FALSE, \ + [EfiLoaderData] = FALSE, \ + [EfiBootServicesCode] = FALSE, \ + [EfiBootServicesData] = TRUE, \ + [EfiRuntimeServicesCode] = FALSE, \ + [EfiRuntimeServicesData] = TRUE, \ + [EfiConventionalMemory] = FALSE, \ + [EfiUnusableMemory] = FALSE, \ + [EfiACPIReclaimMemory] = FALSE, \ + [EfiACPIMemoryNVS] = FALSE, \ + [EfiMemoryMappedIO] = FALSE, \ + [EfiMemoryMappedIOPortSpace] = FALSE, \ + [EfiPalCode] = FALSE, \ + [EfiPersistentMemory] = FALSE, \ + [EfiUnacceptedMemoryType] = FALSE, \ + [OEM_RESERVED_MPS_MEMORY_TYPE] = FALSE, \ + [OS_RESERVED_MPS_MEMORY_TYPE] = FALSE \ + } \ + } \ + }; + +// +// A memory profile which mirrors DXE_MEMORY_PROTECTION_SETTINGS_PROD_MODE +// but doesn't include page guards. +// +#define DXE_MEMORY_PROTECTION_SETTINGS_PROD_MODE_NO_PAGE_GUARDS \ + { \ + DXE_MEMORY_PROTECTION_SETTINGS_CURRENT_VERSION, \ + TRUE, /* Stack Guard */ \ + TRUE, /* Stack Execution Protection */ \ + { /* NULL Pointer Detection */ \ + .Enabled = TRUE, \ + .DisableEndOfDxe = FALSE, \ + .NonstopModeEnabled = FALSE \ + }, \ + { /* Image Protection */ \ + .ProtectImageFromUnknown = FALSE, \ + .ProtectImageFromFv = TRUE \ + }, \ + { /* Execution Protection */ \ + .EnabledForType = { \ + [EfiReservedMemoryType] = TRUE, \ + [EfiLoaderCode] = FALSE, \ + [EfiLoaderData] = TRUE, \ + [EfiBootServicesCode] = FALSE, \ + [EfiBootServicesData] = TRUE, \ + [EfiRuntimeServicesCode] = FALSE, \ + [EfiRuntimeServicesData] = TRUE, \ + [EfiConventionalMemory] = TRUE, \ + [EfiUnusableMemory] = TRUE, \ + [EfiACPIReclaimMemory] = TRUE, \ + [EfiACPIMemoryNVS] = TRUE, \ + [EfiMemoryMappedIO] = TRUE, \ + [EfiMemoryMappedIOPortSpace] = TRUE, \ + [EfiPalCode] = TRUE, \ + [EfiPersistentMemory] = FALSE, \ + [EfiUnacceptedMemoryType] = TRUE, \ + [OEM_RESERVED_MPS_MEMORY_TYPE] = TRUE, \ + [OS_RESERVED_MPS_MEMORY_TYPE] = TRUE \ + } \ + }, \ + { /* Heap Guard */ \ + 0 \ + }, \ + { /* Pool Guard */ \ + 0 \ + }, \ + { /* Page Guard */ \ + 0 \ + } \ + }; + +// +// A memory profile which disables all DXE memory protection settings. +// +#define DXE_MEMORY_PROTECTION_SETTINGS_OFF \ + { \ + DXE_MEMORY_PROTECTION_SETTINGS_CURRENT_VERSION, \ + FALSE, /* Stack Guard */ \ + FALSE, /* Stack Execution Protection */ \ + { /* NULL Pointer Detection */ \ + 0 \ + }, \ + { /* Image Protection */ \ + 0 \ + }, \ + { /* Execution Protection */ \ + 0 \ + }, \ + { /* Heap Guard */ \ + 0 \ + }, \ + { /* Pool Guard */ \ + 0 \ + }, \ + { /* Page Guard */ \ + 0 \ + } \ + }; + +#endif diff --git a/MdeModulePkg/Include/Guid/MmMemoryProtectionSettings.h b/MdeModulePkg/Include/Guid/MmMemoryProtectionSettings.h new file mode 100644 index 0000000000..383788b8f3 --- /dev/null +++ b/MdeModulePkg/Include/Guid/MmMemoryProtectionSettings.h @@ -0,0 +1,211 @@ +/** @file + +Defines memory protection settings guid and struct for MM. + +Copyright (C) Microsoft Corporation. All rights reserved. +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef MM_MEMORY_PROTECTION_SETTINGS_H_ +#define MM_MEMORY_PROTECTION_SETTINGS_H_ + +#include + +// Current iteration of MM_MEMORY_PROTECTION_SETTINGS +#define MM_MEMORY_PROTECTION_SETTINGS_CURRENT_VERSION 1 + +#define OEM_RESERVED_MPS_MEMORY_TYPE EfiMaxMemoryType +#define OS_RESERVED_MPS_MEMORY_TYPE (EfiMaxMemoryType + 1) +#define MAX_MM_MPS_MEMORY_TYPE (EfiMaxMemoryType + 2) +#define MM_MPS_MEMORY_TYPE_BUFFER_SIZE (MAX_MM_MPS_MEMORY_TYPE * sizeof (BOOLEAN)) + +typedef struct { + BOOLEAN Enabled : 1; + BOOLEAN NonstopModeEnabled : 1; +} MM_NULL_DETECTION_POLICY; + +typedef struct { + BOOLEAN PageGuardEnabled : 1; + BOOLEAN PoolGuardEnabled : 1; + BOOLEAN NonstopModeEnabled : 1; + BOOLEAN GuardAlignedToTail : 1; +} MM_HEAP_GUARD_POLICY; + +typedef struct { + BOOLEAN EnabledForType[MAX_MM_MPS_MEMORY_TYPE]; +} MM_MPS_MEMORY_TYPES; + +typedef UINT8 MM_MEMORY_PROTECTION_SETTINGS_VERSION; + +// +// Memory Protection Settings struct +// +typedef struct { + // The current version of the structure definition. This is used to ensure there isn't a + // definition mismatch if modules have differing iterations of this header. When creating + // this struct, use the MM_MEMORY_PROTECTION_SETTINGS_CURRENT_VERSION macro. + MM_MEMORY_PROTECTION_SETTINGS_VERSION StructVersion; + + // If enabled, accessing the NULL address in MM will be caught by marking + // the NULL page as not present. + // .NullDetectionEnabled : Enable NULL pointer detection. + // .NonstopModeEnabled : If enabled the debug flag will be raised when a fault occurs + // to break into debugger. + MM_NULL_DETECTION_POLICY NullPointerDetection; + + // Configures general heap guard behavior. + // + // Note: + // a) Due to the limit of pool memory implementation and the alignment + // requirement of UEFI spec, HeapGuard.GuardAlignedToTail is a try-best + // setting which cannot guarantee that the returned pool is exactly + // adjacent to head or tail guard page. + // + // .PageGuardEnabled : Enable page guard. + // .PoolGuardEnabled : Enable pool guard. + // .NonstopModeEnabled : If enabled the debug flag will be raised when a fault occurs + // to break into debugger. + // .GuardAlignedToTail : TRUE if the pool is aligned to tail guard page. If FALSE, the + // pool is aligned to head guard page. + MM_HEAP_GUARD_POLICY HeapGuard; + + // Indicates which type allocation need guard page. + // + // If bit is set, a head guard page and a tail guard page will be added just + // before and after corresponding type of pages which the allocated pool occupies, + // if there's enough free memory for all of them. + // + // These settings are only valid if PoolGuardEnabled is TRUE in HeapGuard. + MM_MPS_MEMORY_TYPES PoolGuard; + + // Indicates which type allocation need guard page. + // + // If a bit is set, a head guard page and a tail guard page will be added just + // before and after corresponding type of pages allocated if there's enough + // free pages for all of them. + // + // This bitfield is only valid if PageGuardEnabled is TRUE in HeapGuard. + MM_MPS_MEMORY_TYPES PageGuard; +} MM_MEMORY_PROTECTION_SETTINGS; + +#define MM_MPS_IS_STRUCT_VALID(MmMpsPtr) \ + (((MM_MEMORY_PROTECTION_SETTINGS *)MmMpsPtr)->StructVersion == MM_MEMORY_PROTECTION_SETTINGS_CURRENT_VERSION) + +#define MM_MPS_IS_ANY_MEMORY_TYPE_ACTIVE(MpsMemoryTypesPtr) \ + (!IsZeroBuffer (&((MM_MPS_MEMORY_TYPES *)MpsMemoryTypesPtr)->EnabledForType, MM_MPS_MEMORY_TYPE_BUFFER_SIZE)) + +#define MM_MPS_IS_IMAGE_PROTECTION_ENABLED(MmMpsPtr) \ + (((MM_MEMORY_PROTECTION_SETTINGS*)MmMpsPtr)->ImageProtection.ProtectImageFromFv || \ + ((MM_MEMORY_PROTECTION_SETTINGS*)MmMpsPtr)->ImageProtection.ProtectImageFromUnknown) + +#define MM_MPS_IS_EXECUTION_PROTECTION_ENABLED(MmMpsPtr) \ + MM_MPS_IS_ANY_MEMORY_TYPE_ACTIVE(&((MM_MEMORY_PROTECTION_SETTINGS*)MmMpsPtr)->ExecutionProtection) + +#define MM_MPS_ARE_PAGE_GUARDS_ENABLED(MmMpsPtr) \ + (((MM_MEMORY_PROTECTION_SETTINGS*)MmMpsPtr)->HeapGuard.PageGuardEnabled && \ + MM_MPS_IS_ANY_MEMORY_TYPE_ACTIVE(&((MM_MEMORY_PROTECTION_SETTINGS*)MmMpsPtr)->PageGuard)) + +#define MM_MPS_ARE_POOL_GUARDS_ENABLED(MmMpsPtr) \ + (((MM_MEMORY_PROTECTION_SETTINGS*)MmMpsPtr)->HeapGuard.PoolGuardEnabled && \ + MM_MPS_IS_ANY_MEMORY_TYPE_ACTIVE(&((MM_MEMORY_PROTECTION_SETTINGS*)MmMpsPtr)->PoolGuard)) + +#define MM_MPS_IS_MEMORY_PROTECTION_ACTIVE(MmMpsPtr) \ + (MM_MPS_IS_STRUCT_VALID(MmMpsPtr) && \ + (((MM_MEMORY_PROTECTION_SETTINGS*)MmMpsPtr)->CpuStackGuardEnabled || \ + ((MM_MEMORY_PROTECTION_SETTINGS*)MmMpsPtr)->StackExecutionProtectionEnabled || \ + ((MM_MEMORY_PROTECTION_SETTINGS*)MmMpsPtr)->NullPointerDetection.Enabled || \ + MM_MPS_IS_IMAGE_PROTECTION_ENABLED(MmMpsPtr) || \ + MM_MPS_IS_EXECUTION_PROTECTION_ENABLED(MmMpsPtr) || \ + MM_MPS_ARE_PAGE_GUARDS_ENABLED(MmMpsPtr) || \ + MM_MPS_ARE_POOL_GUARDS_ENABLED(MmMpsPtr)) \ + ) + +#define HOB_MM_MEMORY_PROTECTION_SETTINGS_GUID \ + { \ + { 0x0CF445DD, 0xA67C, 0x4F8C, { 0x81, 0x9B, 0xB7, 0xB6, 0x86, 0xED, 0x7C, 0x75 } } \ + } + +extern GUID gMmMemoryProtectionSettingsGuid; + +// +// A memory profile ideal for development scenarios. +// +#define MM_MEMORY_PROTECTION_SETTINGS_DEBUG { \ + MM_MEMORY_PROTECTION_SETTINGS_CURRENT_VERSION, \ + { /* NULL Pointer Detection */ \ + .Enabled = TRUE, \ + .NonstopModeEnabled = TRUE \ + }, \ + { /* Heap Guard */ \ + .PageGuardEnabled = TRUE, \ + .PoolGuardEnabled = TRUE, \ + .NonstopModeEnabled = TRUE, \ + .GuardAlignedToTail = FALSE \ + }, \ + { /* Pool Guard */ \ + .EnabledForType = { \ + [EfiReservedMemoryType] = FALSE, \ + [EfiLoaderCode] = FALSE, \ + [EfiLoaderData] = FALSE, \ + [EfiBootServicesCode] = FALSE, \ + [EfiBootServicesData] = TRUE, \ + [EfiRuntimeServicesCode] = FALSE, \ + [EfiRuntimeServicesData] = TRUE, \ + [EfiConventionalMemory] = FALSE, \ + [EfiUnusableMemory] = FALSE, \ + [EfiACPIReclaimMemory] = FALSE, \ + [EfiACPIMemoryNVS] = FALSE, \ + [EfiMemoryMappedIO] = FALSE, \ + [EfiMemoryMappedIOPortSpace] = FALSE, \ + [EfiPalCode] = FALSE, \ + [EfiPersistentMemory] = FALSE, \ + [EfiUnacceptedMemoryType] = FALSE, \ + [OEM_RESERVED_MPS_MEMORY_TYPE] = FALSE, \ + [OS_RESERVED_MPS_MEMORY_TYPE] = FALSE \ + } \ + }, \ + { /* Page Guard */ \ + .EnabledForType = { \ + [EfiReservedMemoryType] = FALSE, \ + [EfiLoaderCode] = FALSE, \ + [EfiLoaderData] = FALSE, \ + [EfiBootServicesCode] = FALSE, \ + [EfiBootServicesData] = TRUE, \ + [EfiRuntimeServicesCode] = FALSE, \ + [EfiRuntimeServicesData] = TRUE, \ + [EfiConventionalMemory] = FALSE, \ + [EfiUnusableMemory] = FALSE, \ + [EfiACPIReclaimMemory] = FALSE, \ + [EfiACPIMemoryNVS] = FALSE, \ + [EfiMemoryMappedIO] = FALSE, \ + [EfiMemoryMappedIOPortSpace] = FALSE, \ + [EfiPalCode] = FALSE, \ + [EfiPersistentMemory] = FALSE, \ + [EfiUnacceptedMemoryType] = FALSE, \ + [OEM_RESERVED_MPS_MEMORY_TYPE] = FALSE, \ + [OS_RESERVED_MPS_MEMORY_TYPE] = FALSE \ + } \ + } \ + } + +// +// A memory profile which disables all MM memory protection settings. +// +#define MM_MEMORY_PROTECTION_SETTINGS_OFF { \ + MM_MEMORY_PROTECTION_SETTINGS_CURRENT_VERSION, \ + { /* NULL Pointer Detection */ \ + 0 \ + }, \ + { /* Heap Guard */ \ + 0 \ + }, \ + { /* Pool Guard */ \ + 0 \ + }, \ + { /* Page Guard */ \ + 0 \ + } \ + } + +#endif diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index d65dae18aa..f8c0fb4e93 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -399,6 +399,16 @@ ## Include/Guid/EndofS3Resume.h gEdkiiEndOfS3ResumeGuid = { 0x96f5296d, 0x05f7, 0x4f3c, {0x84, 0x67, 0xe4, 0x56, 0x89, 0x0e, 0x0c, 0xb5 } } + ## DXE Memory Protection Settings Guid. Used to create and fetch the DXE memory protection settings HOB entry. + # + # Include/Guid/DxeMemoryProtectionSettings + gDxeMemoryProtectionSettingsGuid = { 0x9ABFD639, 0xD1D0, 0x4EFF, { 0xBD, 0xB6, 0x7E, 0xC4, 0x19, 0x0D, 0x17, 0xD5 }} + + ## SMM Memory Protection Settings Guid. Used to create and fetch the SMM memory protection settings HOB entry. + # + # Include/Guid/MmMemoryProtectionSettings + gMmMemoryProtectionSettingsGuid = { 0x0CF445DD, 0xA67C, 0x4F8C, { 0x81, 0x9B, 0xB7, 0xB6, 0x86, 0xED, 0x7C, 0x75 }} + ## Used (similar to Variable Services) to communicate policies to the enforcement engine. # {DA1B0D11-D1A7-46C4-9DC9-F3714875C6EB} gVarCheckPolicyLibMmiHandlerGuid = { 0xda1b0d11, 0xd1a7, 0x46c4, { 0x9d, 0xc9, 0xf3, 0x71, 0x48, 0x75, 0xc6, 0xeb }} -- 2.41.0.windows.2