summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Smith-Denny <osde@microsoft.com>2025-01-29 11:05:03 -0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2025-02-07 02:23:11 +0000
commite6b6aa90d490c298da140bc118d73ceff510f563 (patch)
treee20b3795b7d5bab5c7280396aafbfb61e9b1b577
parentefbf5ed08c48478b51bb6b6da5670b1312755854 (diff)
downloadedk2-e6b6aa90d490c298da140bc118d73ceff510f563.tar.gz
MdePkg: Add Dynamic Stack Cookie Support
Adds dynamic stack cookies in the form of copies of the entry point libraries that use shared logic to update stack cookies at runtime. This relies on RDRAND on IA32/X64 and RNDR on AARCH64 to get a random number to apply to the stack cookie on module entry point. This simplifies the logic a platform must do to include stack check functionality. Signed-off-by: Oliver Smith-Denny <osde@microsoft.com>
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/AArch64/DynamicCookieGcc.S56
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCore/DxeCoreEntryPoint.c70
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCore/DxeCoreEntryPoint.uni16
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCoreEntryPoint.inf45
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/IA32/DynamicCookieGcc.nasm63
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/IA32/DynamicCookieMsvc.nasm63
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/PeiCore/PeiCoreEntryPoint.c93
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/PeiCore/PeiCoreEntryPoint.uni16
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/PeiCore/PeiCoreStackCheckEntryPointLibNull.c66
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/PeiCoreEntryPoint.inf44
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/Peim/PeimEntryPoint.c72
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/Peim/PeimEntryPoint.uni16
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/Peim/PeimStackCheckEntryPointLibNull.c46
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/PeimEntryPoint.inf43
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmCore/X64/StandaloneMmCoreEntryPoint.c65
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmCoreEntryPoint.inf38
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriver/StandaloneMmDriverEntryPoint.c135
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriver/StandaloneMmDriverEntryPoint.uni17
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriverEntryPoint.inf53
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplication/ApplicationEntryPoint.c112
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplication/ApplicationStackCheckEntryPointLibNull.c50
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplication/UefiApplicationEntryPoint.uni16
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplicationEntryPoint.inf45
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriver/DriverEntryPoint.c162
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriver/UefiDriverEntryPoint.uni16
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriverEntryPoint.inf68
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/X64/DynamicCookieGcc.nasm63
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/X64/DynamicCookieMsvc.nasm63
-rw-r--r--MdePkg/Library/StackCheckLib/Readme.md198
-rw-r--r--MdePkg/MdeLibs.dsc.inc36
-rw-r--r--MdePkg/MdePkg.dsc7
31 files changed, 1779 insertions, 74 deletions
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/AArch64/DynamicCookieGcc.S b/MdePkg/Library/DynamicStackCookieEntryPointLib/AArch64/DynamicCookieGcc.S
new file mode 100644
index 0000000000..d33c02a7c4
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/AArch64/DynamicCookieGcc.S
@@ -0,0 +1,56 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+# Module Name:
+#
+# DynamicCookie.S
+#
+# Abstract:
+#
+# Generates random number through the RNDR instruction on a 64-bit AARCH64 platform
+# to store a random value in the GCC __stack_check_guard stack cookie.
+# The first byte is 0'd to prevent string copy functions from clobbering
+# the stack cookie.
+#
+# Notes:
+#
+# If RNDR fails, the build time static stack cookie value will be used instead.
+#
+#------------------------------------------------------------------------------
+
+#include <AArch64/AArch64.h>
+
+.text
+.p2align 2
+
+GCC_ASM_IMPORT(__stack_chk_guard)
+GCC_ASM_IMPORT(_CModuleEntryPoint)
+GCC_ASM_EXPORT(_ModuleEntryPoint)
+
+#------------------------------------------------------------------------------
+# VOID
+# EFIAPI
+# _ModuleEntryPoint (
+# Parameters are passed through.
+# )
+#------------------------------------------------------------------------------
+ASM_PFX(_ModuleEntryPoint):
+ AARCH64_BTI(c)
+
+ mrs x9, ID_AA64ISAR0_EL1 // Read the AArch64 Instruction Set Attribute Register 0
+ ubfx x9, x9, #60, #4 // Extract the RNDR bit field (bits 60-63)
+ cbz x9, c_entry // If RNDR is not supported, jump to c_entry
+
+ mrs x9, RNDR // Generate a random number
+ b.eq c_entry // RNDR sets NZCV to 0b0100 on failure
+ // So if the zero flag is set, use the static stack guard
+
+ and x9, x9, #0xFFFFFFFFFFFFFF00 // Zero the first byte of the random value
+
+ adrp x8, ASM_PFX(__stack_chk_guard) // Load the page address of __stack_chk_guard
+ str x9, [x8, :lo12:ASM_PFX(__stack_chk_guard)] // Store the random value in __stack_chk_guard
+
+c_entry:
+ b ASM_PFX(_CModuleEntryPoint) // Jump to the C module entry point
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCore/DxeCoreEntryPoint.c b/MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCore/DxeCoreEntryPoint.c
new file mode 100644
index 0000000000..986ab25b31
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCore/DxeCoreEntryPoint.c
@@ -0,0 +1,70 @@
+/** @file
+ Entry point to the DXE Core.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/DxeCoreEntryPoint.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+
+//
+// Cache copy of HobList pointer.
+//
+VOID *gHobList = NULL;
+
+/**
+ The entry point of PE/COFF Image for the DXE Core.
+
+ This function is the entry point for the DXE Core. This function is required to call
+ ProcessModuleEntryPointList() and ProcessModuleEntryPointList() is never expected to return.
+ The DXE Core is responsible for calling ProcessLibraryConstructorList() as soon as the EFI
+ System Table and the image handle for the DXE Core itself have been established.
+ If ProcessModuleEntryPointList() returns, then ASSERT() and halt the system.
+
+ @param HobStart The pointer to the beginning of the HOB List passed in from the PEI Phase.
+
+**/
+VOID
+EFIAPI
+_CModuleEntryPoint (
+ IN VOID *HobStart
+ )
+{
+ //
+ // Cache a pointer to the HobList
+ //
+ gHobList = HobStart;
+
+ //
+ // Call the DXE Core entry point
+ //
+ ProcessModuleEntryPointList (HobStart);
+
+ //
+ // Should never return
+ //
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+}
+
+/**
+ Required by the EBC compiler and identical in functionality to _ModuleEntryPoint().
+
+ This function is required to call _ModuleEntryPoint() passing in HobStart.
+
+ @param HobStart The pointer to the beginning of the HOB List passed in from the PEI Phase.
+
+**/
+VOID
+EFIAPI
+EfiMain (
+ IN VOID *HobStart
+ )
+{
+ _ModuleEntryPoint (HobStart);
+}
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCore/DxeCoreEntryPoint.uni b/MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCore/DxeCoreEntryPoint.uni
new file mode 100644
index 0000000000..af26f0bec4
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCore/DxeCoreEntryPoint.uni
@@ -0,0 +1,16 @@
+// /** @file
+// Module entry point library for DXE core.
+//
+// Module entry point library for DXE core.
+//
+// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Module entry point library for DXE core"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Module entry point library for DXE core."
+
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCoreEntryPoint.inf b/MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCoreEntryPoint.inf
new file mode 100644
index 0000000000..ea84987678
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCoreEntryPoint.inf
@@ -0,0 +1,45 @@
+## @file
+# Module entry point library for DXE core that dynamically updates the stack cookie.
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DxeCoreEntryPointDynamicInit
+ MODULE_UNI_FILE = DxeCore/DxeCoreEntryPoint.uni
+ FILE_GUID = FD044D85-1407-4043-B527-471F16ABD8C6
+ MODULE_TYPE = DXE_CORE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = DxeCoreEntryPoint|DXE_CORE
+
+
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ DxeCore/DxeCoreEntryPoint.c
+
+[Sources.IA32]
+ IA32/DynamicCookieGcc.nasm | GCC
+ IA32/DynamicCookieMsvc.nasm | MSFT
+
+[Sources.X64]
+ X64/DynamicCookieGcc.nasm | GCC
+ X64/DynamicCookieMsvc.nasm | MSFT
+
+[Sources.AARCH64]
+ AArch64/DynamicCookieGcc.S | GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ StackCheckLib
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/IA32/DynamicCookieGcc.nasm b/MdePkg/Library/DynamicStackCookieEntryPointLib/IA32/DynamicCookieGcc.nasm
new file mode 100644
index 0000000000..ae8db569dc
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/IA32/DynamicCookieGcc.nasm
@@ -0,0 +1,63 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) Microsoft Corporation.
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; DynamicCookie.nasm
+;
+; Abstract:
+;
+; Generates random number through CPU RdRand instruction on a 32-bit platform
+; to store a random value in the GCC __stack_check_guard stack cookie.
+; The first byte is 0'd to prevent string copy functions from clobbering
+; the stack cookie.
+;
+; Notes:
+;
+; If RdRand fails, the build time static stack cookie value will be used instead.
+;
+;------------------------------------------------------------------------------
+
+SECTION .text
+
+extern ASM_PFX(__stack_chk_guard)
+extern ASM_PFX(_CModuleEntryPoint)
+global ASM_PFX(_ModuleEntryPoint)
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; _ModuleEntryPoint (
+; Parameters are passed through
+; );
+;------------------------------------------------------------------------------
+global _ModuleEntryPoint
+_ModuleEntryPoint:
+ push ebx
+ push ecx
+ push edx
+
+ mov eax, 1 ; CPUID function 1
+ cpuid
+ test ecx, 0x40000000 ; Check if the RdRand bit (bit 30) is set in ECX
+ jz c_entry ; If not set, jump to c_entry
+
+ rdrand eax ; Use rdrand, getting a 32 bit value as on
+ ; IA32, __stack_chk_guard is a 32 bit value.
+ ; CF=1 if RN generated ok, otherwise CF=0
+ jnc c_entry ; If the cmd fails, don't update __stack_chk_guard, we'll have to move forward
+ ; with the static value provided at build time.
+
+ lea ebx, [ASM_PFX(__stack_chk_guard)] ; load the address of __stack_chk_guard into ebx
+
+ xor ah, ah ; Zero a byte of the __stack_chk_guard value to protect against string functions
+ ; (such as strcpy like functions) clobbering past the canary
+ mov [ebx], eax ; Store our random value, with 0'd first byte to __stack_chk_guard
+
+c_entry:
+ pop edx
+ pop ecx
+ pop ebx
+ jmp ASM_PFX(_CModuleEntryPoint)
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/IA32/DynamicCookieMsvc.nasm b/MdePkg/Library/DynamicStackCookieEntryPointLib/IA32/DynamicCookieMsvc.nasm
new file mode 100644
index 0000000000..efd43c04a3
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/IA32/DynamicCookieMsvc.nasm
@@ -0,0 +1,63 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) Microsoft Corporation.
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; DynamicCookie.nasm
+;
+; Abstract:
+;
+; Generates random number through CPU RdRand instruction on a 32-bit platform
+; to store a random value in the GCC __stack_check_guard stack cookie.
+; The first byte is 0'd to prevent string copy functions from clobbering
+; the stack cookie.
+;
+; Notes:
+;
+; If RdRand fails, the build time static stack cookie value will be used instead.
+;
+;------------------------------------------------------------------------------
+
+SECTION .text
+
+extern ASM_PFX(__security_cookie)
+extern ASM_PFX(_CModuleEntryPoint)
+global ASM_PFX(_ModuleEntryPoint)
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; _ModuleEntryPoint (
+; Parameters are passed through
+; );
+;------------------------------------------------------------------------------
+global _ModuleEntryPoint
+_ModuleEntryPoint:
+ push ebx
+ push ecx
+ push edx
+
+ mov eax, 1 ; CPUID function 1
+ cpuid
+ test ecx, 0x40000000 ; Check if the RdRand bit (bit 30) is set in ECX
+ jz c_entry ; If not set, jump to c_entry
+
+ rdrand eax ; Use rdrand, getting a 32 bit value as on
+ ; IA32, __security_cookie is a 32 bit value.
+ ; CF=1 if RN generated ok, otherwise CF=0
+ jnc c_entry ; If the cmd fails, don't update __security_cookie, we'll have to move forward
+ ; with the static value provided at build time.
+
+ lea ebx, [ASM_PFX(__security_cookie)] ; load the address of __stack_chk_guard into ebx
+
+ xor ah, ah ; Zero a byte of the __security_cookie value to protect against string functions
+ ; (such as strcpy like functions) clobbering past the canary
+ mov [ebx], eax ; Store our random value, with 0'd first byte to __security_cookie
+
+c_entry:
+ pop edx
+ pop ecx
+ pop ebx
+ jmp ASM_PFX(_CModuleEntryPoint)
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/PeiCore/PeiCoreEntryPoint.c b/MdePkg/Library/DynamicStackCookieEntryPointLib/PeiCore/PeiCoreEntryPoint.c
new file mode 100644
index 0000000000..bcc9c2ce35
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/PeiCore/PeiCoreEntryPoint.c
@@ -0,0 +1,93 @@
+/** @file
+ Entry point to a the PEI Core.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+
+//
+// The Library classes this module produced
+//
+#include <Library/PeiCoreEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+/**
+ The entry point of PE/COFF Image for the PEI Core.
+
+ This function is the entry point for the PEI Foundation, which allows the SEC phase
+ to pass information about the stack, temporary RAM and the Boot Firmware Volume.
+ In addition, it also allows the SEC phase to pass services and data forward for use
+ during the PEI phase in the form of one or more PPIs.
+ There is no limit to the number of additional PPIs that can be passed from SEC into
+ the PEI Foundation. As part of its initialization phase, the PEI Foundation will add
+ these SEC-hosted PPIs to its PPI database such that both the PEI Foundation and any
+ modules can leverage the associated service calls and/or code in these early PPIs.
+ This function is required to call ProcessModuleEntryPointList() with the Context
+ parameter set to NULL. ProcessModuleEntryPoint() is never expected to return.
+ The PEI Core is responsible for calling ProcessLibraryConstructorList() as soon as
+ the PEI Services Table and the file handle for the PEI Core itself have been established.
+ If ProcessModuleEntryPointList() returns, then ASSERT() and halt the system.
+
+ @param SecCoreData Points to a data structure containing information about the
+ PEI core's operating environment, such as the size and
+ location of temporary RAM, the stack location and the BFV
+ location.
+
+ @param PpiList Points to a list of one or more PPI descriptors to be
+ installed initially by the PEI core. An empty PPI list
+ consists of a single descriptor with the end-tag
+ EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST.
+ As part of its initialization phase, the PEI Foundation will
+ add these SEC-hosted PPIs to its PPI database, such that both
+ the PEI Foundation and any modules can leverage the associated
+ service calls and/or code in these early PPIs.
+
+**/
+VOID
+EFIAPI
+_CModuleEntryPoint (
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
+ IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList
+ )
+{
+ ProcessModuleEntryPointList (SecCoreData, PpiList, NULL);
+
+ //
+ // Should never return
+ //
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+}
+
+/**
+ Required by the EBC compiler and identical in functionality to _ModuleEntryPoint().
+
+ This function is required to call _CModuleEntryPoint() passing in SecCoreData and PpiList.
+
+ @param SecCoreData Points to a data structure containing information about the PEI core's
+ operating environment, such as the size and location of temporary RAM,
+ the stack location and the BFV location.
+
+ @param PpiList Points to a list of one or more PPI descriptors to be installed
+ initially by the PEI core. An empty PPI list consists of
+ a single descriptor with the end-tag
+ EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST.
+ As part of its initialization phase, the PEI Foundation will
+ add these SEC-hosted PPIs to its PPI database, such that both
+ the PEI Foundationand any modules can leverage the associated
+ service calls and/or code in these early PPIs.
+
+**/
+VOID
+EFIAPI
+EfiMain (
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
+ IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList
+ )
+{
+ _CModuleEntryPoint (SecCoreData, PpiList);
+}
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/PeiCore/PeiCoreEntryPoint.uni b/MdePkg/Library/DynamicStackCookieEntryPointLib/PeiCore/PeiCoreEntryPoint.uni
new file mode 100644
index 0000000000..f4c12c0e60
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/PeiCore/PeiCoreEntryPoint.uni
@@ -0,0 +1,16 @@
+// /** @file
+// Module entry point library for PEI core.
+//
+// Module entry point library for PEI core.
+//
+// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Module entry point library for PEI core"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Module entry point library for PEI core."
+
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/PeiCore/PeiCoreStackCheckEntryPointLibNull.c b/MdePkg/Library/DynamicStackCookieEntryPointLib/PeiCore/PeiCoreStackCheckEntryPointLibNull.c
new file mode 100644
index 0000000000..c698cc640c
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/PeiCore/PeiCoreStackCheckEntryPointLibNull.c
@@ -0,0 +1,66 @@
+/** @file
+ Entry point to a the PEI Core that does not update the stack cookie dynamically.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+
+//
+// The Library classes this module produced
+//
+#include <Library/PeiCoreEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+extern
+VOID
+EFIAPI
+_CModuleEntryPoint (
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
+ IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList
+ );
+
+/**
+ The entry point of PE/COFF Image for the PEI Core.
+
+ This function is the entry point for the PEI Foundation, which allows the SEC phase
+ to pass information about the stack, temporary RAM and the Boot Firmware Volume.
+ In addition, it also allows the SEC phase to pass services and data forward for use
+ during the PEI phase in the form of one or more PPIs.
+ There is no limit to the number of additional PPIs that can be passed from SEC into
+ the PEI Foundation. As part of its initialization phase, the PEI Foundation will add
+ these SEC-hosted PPIs to its PPI database such that both the PEI Foundation and any
+ modules can leverage the associated service calls and/or code in these early PPIs.
+ This function is required to call ProcessModuleEntryPointList() with the Context
+ parameter set to NULL. ProcessModuleEntryPoint() is never expected to return.
+ The PEI Core is responsible for calling ProcessLibraryConstructorList() as soon as
+ the PEI Services Table and the file handle for the PEI Core itself have been established.
+ If ProcessModuleEntryPointList() returns, then ASSERT() and halt the system.
+
+ @param SecCoreData Points to a data structure containing information about the
+ PEI core's operating environment, such as the size and
+ location of temporary RAM, the stack location and the BFV
+ location.
+
+ @param PpiList Points to a list of one or more PPI descriptors to be
+ installed initially by the PEI core. An empty PPI list
+ consists of a single descriptor with the end-tag
+ EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST.
+ As part of its initialization phase, the PEI Foundation will
+ add these SEC-hosted PPIs to its PPI database, such that both
+ the PEI Foundation and any modules can leverage the associated
+ service calls and/or code in these early PPIs.
+
+**/
+VOID
+EFIAPI
+_ModuleEntryPoint (
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
+ IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList
+ )
+{
+ _CModuleEntryPoint (SecCoreData, PpiList);
+}
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/PeiCoreEntryPoint.inf b/MdePkg/Library/DynamicStackCookieEntryPointLib/PeiCoreEntryPoint.inf
new file mode 100644
index 0000000000..9ac20b8659
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/PeiCoreEntryPoint.inf
@@ -0,0 +1,44 @@
+## @file
+# Module entry point library for PEI core that dynamically updates the stack cookie.
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PeiCoreEntryPointDynamicInit
+ MODULE_UNI_FILE = PeiCore/PeiCoreEntryPoint.uni
+ FILE_GUID = 2627DFCD-054D-403E-B812-E67034865D29
+ MODULE_TYPE = PEI_CORE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PeiCoreEntryPoint|PEI_CORE
+
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ PeiCore/PeiCoreEntryPoint.c
+
+[Sources.IA32]
+ IA32/DynamicCookieGcc.nasm | GCC
+ IA32/DynamicCookieMsvc.nasm | MSFT
+
+[Sources.X64]
+ X64/DynamicCookieGcc.nasm | GCC
+ X64/DynamicCookieMsvc.nasm | MSFT
+
+[Sources.AARCH64]
+ AArch64/DynamicCookieGcc.S | GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ StackCheckLib
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/Peim/PeimEntryPoint.c b/MdePkg/Library/DynamicStackCookieEntryPointLib/Peim/PeimEntryPoint.c
new file mode 100644
index 0000000000..da03d61dac
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/Peim/PeimEntryPoint.c
@@ -0,0 +1,72 @@
+/** @file
+ Entry point to a PEIM.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+
+#include <Library/PeimEntryPoint.h>
+#include <Library/DebugLib.h>
+
+/**
+ The entry point of PE/COFF Image for a PEIM.
+
+ This function is the entry point for a PEIM. This function must call ProcessLibraryConstructorList()
+ and ProcessModuleEntryPointList(). The return value from ProcessModuleEntryPointList() is returned.
+ If _gPeimRevision is not zero and PeiServices->Hdr.Revision is less than _gPeimRevison, then ASSERT().
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+
+ @retval EFI_SUCCESS The PEIM executed normally.
+ @retval !EFI_SUCCESS The PEIM failed to execute normally.
+**/
+EFI_STATUS
+EFIAPI
+_CModuleEntryPoint (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ if (_gPeimRevision != 0) {
+ //
+ // Make sure that the PEI spec revision of the platform is >= PEI spec revision of the driver
+ //
+ ASSERT ((*PeiServices)->Hdr.Revision >= _gPeimRevision);
+ }
+
+ //
+ // Call constructor for all libraries
+ //
+ ProcessLibraryConstructorList (FileHandle, PeiServices);
+
+ //
+ // Call the driver entry point
+ //
+ return ProcessModuleEntryPointList (FileHandle, PeiServices);
+}
+
+/**
+ Required by the EBC compiler and identical in functionality to _ModuleEntryPoint().
+
+ This function is required to call _ModuleEntryPoint() passing in FileHandle and PeiServices.
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+
+ @retval EFI_SUCCESS The PEIM executed normally.
+ @retval !EFI_SUCCESS The PEIM failed to execute normally.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiMain (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ return _CModuleEntryPoint (FileHandle, PeiServices);
+}
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/Peim/PeimEntryPoint.uni b/MdePkg/Library/DynamicStackCookieEntryPointLib/Peim/PeimEntryPoint.uni
new file mode 100644
index 0000000000..bae3abaeb2
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/Peim/PeimEntryPoint.uni
@@ -0,0 +1,16 @@
+// /** @file
+// Module entry point library for PEIM.
+//
+// Module entry point library for PEIM.
+//
+// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Module entry point library for PEIM"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Module entry point library for PEIM."
+
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/Peim/PeimStackCheckEntryPointLibNull.c b/MdePkg/Library/DynamicStackCookieEntryPointLib/Peim/PeimStackCheckEntryPointLibNull.c
new file mode 100644
index 0000000000..aa4a55d8d6
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/Peim/PeimStackCheckEntryPointLibNull.c
@@ -0,0 +1,46 @@
+/** @file
+ Entry point to a PEIM that does not update the stack cookie dynamically.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+
+#include <Library/PeimEntryPoint.h>
+#include <Library/DebugLib.h>
+
+extern
+EFI_STATUS
+EFIAPI
+_CModuleEntryPoint (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ );
+
+/**
+ The entry point of PE/COFF Image for a PEIM.
+
+ This function is the entry point for a PEIM. This function must call ProcessLibraryConstructorList()
+ and ProcessModuleEntryPointList(). The return value from ProcessModuleEntryPointList() is returned.
+ If _gPeimRevision is not zero and PeiServices->Hdr.Revision is less than _gPeimRevison, then ASSERT().
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+
+ @retval EFI_SUCCESS The PEIM executed normally.
+ @retval !EFI_SUCCESS The PEIM failed to execute normally.
+**/
+EFI_STATUS
+EFIAPI
+_ModuleEntryPoint (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ //
+ // Call the driver entry point
+ //
+ return _CModuleEntryPoint (FileHandle, PeiServices);
+}
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/PeimEntryPoint.inf b/MdePkg/Library/DynamicStackCookieEntryPointLib/PeimEntryPoint.inf
new file mode 100644
index 0000000000..b6b8f0a94f
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/PeimEntryPoint.inf
@@ -0,0 +1,43 @@
+## @file
+# Module entry point library for PEIM that dynamically updates the stack cookie.
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PeimEntryPointDynamicInit
+ MODULE_UNI_FILE = Peim/PeimEntryPoint.uni
+ FILE_GUID = 0E53AFCB-7FDD-461E-B8CE-6DA9F3F9014C
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PeimEntryPoint|PEIM
+
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ Peim/PeimEntryPoint.c
+
+[Sources.IA32]
+ IA32/DynamicCookieGcc.nasm | GCC
+ IA32/DynamicCookieMsvc.nasm | MSFT
+
+[Sources.X64]
+ X64/DynamicCookieGcc.nasm | GCC
+ X64/DynamicCookieMsvc.nasm | MSFT
+
+[Sources.AARCH64]
+ AArch64/DynamicCookieGcc.S | GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ DebugLib
+ StackCheckLib
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmCore/X64/StandaloneMmCoreEntryPoint.c b/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmCore/X64/StandaloneMmCoreEntryPoint.c
new file mode 100644
index 0000000000..f68fa193e1
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmCore/X64/StandaloneMmCoreEntryPoint.c
@@ -0,0 +1,65 @@
+/** @file
+ Entry point to the Standalone Mm Core.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+
+#include <Library/StandaloneMmCoreEntryPoint.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+
+//
+// Cache copy of HobList pointer.
+//
+VOID *gHobList = NULL;
+
+/**
+ The entry point of PE/COFF Image for the STANDALONE MM Core.
+
+ This function is the entry point for the STANDALONE MM Core. This function is required to call
+ ProcessModuleEntryPointList() and ProcessModuleEntryPointList() is never expected to return.
+ The STANDALONE MM Core is responsible for calling ProcessLibraryConstructorList() as soon as the EFI
+ System Table and the image handle for the STANDALONE MM Core itself have been established.
+ If ProcessModuleEntryPointList() returns, then ASSERT() and halt the system.
+
+ @param HobStart Pointer to the beginning of the HOB List passed in from the PEI Phase.
+
+**/
+VOID
+EFIAPI
+_CModuleEntryPoint (
+ IN VOID *HobStart
+ )
+{
+ //
+ // Cache a pointer to the HobList
+ //
+ gHobList = HobStart;
+
+ //
+ // Call the Standalone MM Core entry point
+ //
+ ProcessModuleEntryPointList (HobStart);
+}
+
+/**
+ Required by the EBC compiler and identical in functionality to _ModuleEntryPoint().
+
+ This function is required to call _ModuleEntryPoint() passing in HobStart.
+
+ @param HobStart Pointer to the beginning of the HOB List passed in from the PEI Phase.
+
+**/
+VOID
+EFIAPI
+EfiMain (
+ IN VOID *HobStart
+ )
+{
+ _ModuleEntryPoint (HobStart);
+}
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmCoreEntryPoint.inf b/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmCoreEntryPoint.inf
new file mode 100644
index 0000000000..41361dde53
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmCoreEntryPoint.inf
@@ -0,0 +1,38 @@
+## @file
+# Module entry point library for StandaloneMm core that dynamically updates the stack cookie.
+# The AARCH64 version of this library lives in ArmPkg.
+#
+# Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = StandaloneMmCoreEntryPointDynamicInit
+ FILE_GUID = 490073A1-4DBC-4E9E-B30D-A4204139FC5F
+ MODULE_TYPE = MM_CORE_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ LIBRARY_CLASS = StandaloneMmCoreEntryPoint|MM_CORE_STANDALONE
+
+#
+# VALID_ARCHITECTURES = X64
+#
+
+[Sources.X64]
+ StandaloneMmCore/X64/StandaloneMmCoreEntryPoint.c
+
+[Sources.X64]
+ X64/DynamicCookieGcc.nasm | GCC
+ X64/DynamicCookieMsvc.nasm | MSFT
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ StackCheckLib
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriver/StandaloneMmDriverEntryPoint.c b/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriver/StandaloneMmDriverEntryPoint.c
new file mode 100644
index 0000000000..4241ef3058
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriver/StandaloneMmDriverEntryPoint.c
@@ -0,0 +1,135 @@
+/** @file
+ Entry point to a Standalone MM driver.
+
+Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2016 - 2018, ARM Ltd. All rights reserved.<BR>
+Copyright (c) 2018, Linaro, Limited. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+
+#include <Protocol/LoadedImage.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MmServicesTableLib.h>
+#include <Library/StandaloneMmDriverEntryPoint.h>
+
+/**
+ Unloads an image from memory.
+
+ This function is a callback that a driver registers to do cleanup
+ when the UnloadImage boot service function is called.
+
+ @param ImageHandle The handle to the image to unload.
+
+ @return Status returned by all unload().
+
+**/
+EFI_STATUS
+EFIAPI
+_DriverUnloadHandler (
+ EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // If an UnloadImage() handler is specified, then call it
+ //
+ Status = ProcessModuleUnloadList (ImageHandle);
+
+ //
+ // If the driver specific unload handler does not return an error, then call all of the
+ // library destructors. If the unload handler returned an error, then the driver can not be
+ // unloaded, and the library destructors should not be called
+ //
+ if (!EFI_ERROR (Status)) {
+ ProcessLibraryDestructorList (ImageHandle, gMmst);
+ }
+
+ //
+ // Return the status from the driver specific unload handler
+ //
+ return Status;
+}
+
+/**
+ The entry point of PE/COFF Image for a Standalone MM Driver.
+
+ This function is the entry point for a Standalone MM Driver.
+ This function must call ProcessLibraryConstructorList() and
+ ProcessModuleEntryPointList().
+ If the return status from ProcessModuleEntryPointList()
+ is an error status, then ProcessLibraryDestructorList() must be called.
+ The return value from ProcessModuleEntryPointList() is returned.
+ If _gMmRevision is not zero and SystemTable->Hdr.Revision is
+ less than _gMmRevision, then return EFI_INCOMPATIBLE_VERSION.
+
+ @param ImageHandle The image handle of the Standalone MM Driver.
+ @param MmSystemTable A pointer to the MM System Table.
+
+ @retval EFI_SUCCESS The Standalone MM Driver exited normally.
+ @retval EFI_INCOMPATIBLE_VERSION _gMmRevision is greater than
+ MmSystemTable->Hdr.Revision.
+ @retval Other Return value from
+ ProcessModuleEntryPointList().
+
+**/
+EFI_STATUS
+EFIAPI
+_CModuleEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN IN EFI_MM_SYSTEM_TABLE *MmSystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+
+ if (_gMmRevision != 0) {
+ //
+ // Make sure that the MM spec revision of the platform
+ // is >= MM spec revision of the driver
+ //
+ if (MmSystemTable->Hdr.Revision < _gMmRevision) {
+ return EFI_INCOMPATIBLE_VERSION;
+ }
+ }
+
+ //
+ // Call constructor for all libraries
+ //
+ ProcessLibraryConstructorList (ImageHandle, MmSystemTable);
+
+ //
+ // Install unload handler...
+ //
+ if (_gDriverUnloadImageCount != 0) {
+ Status = gMmst->MmHandleProtocol (
+ ImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **)&LoadedImage
+ );
+ ASSERT_EFI_ERROR (Status);
+ LoadedImage->Unload = _DriverUnloadHandler;
+ }
+
+ //
+ // Call the driver entry point
+ //
+ Status = ProcessModuleEntryPointList (ImageHandle, MmSystemTable);
+
+ //
+ // If all of the drivers returned errors, then invoke all of the library destructors
+ //
+ if (EFI_ERROR (Status)) {
+ ProcessLibraryDestructorList (ImageHandle, MmSystemTable);
+ }
+
+ //
+ // Return the cumulative return status code from all of the driver entry points
+ //
+ return Status;
+}
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriver/StandaloneMmDriverEntryPoint.uni b/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriver/StandaloneMmDriverEntryPoint.uni
new file mode 100644
index 0000000000..917ae95144
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriver/StandaloneMmDriverEntryPoint.uni
@@ -0,0 +1,17 @@
+// /** @file
+//
+// Module entry point library for standalone MM driver
+//
+// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
+// Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
+// Copyright (c) 2018, Linaro, Limited. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Module entry point library for standalone MM driver"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Module entry point library for standalone MM driver."
+
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriverEntryPoint.inf b/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriverEntryPoint.inf
new file mode 100644
index 0000000000..1d43ce9345
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriverEntryPoint.inf
@@ -0,0 +1,53 @@
+## @file
+# Module entry point library for Standalone MM drivers that dynamically updates the stack cookie.
+#
+# Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2016-2018, ARM Ltd. All rights reserved.<BR>
+# Copyright (c) 2018, Linaro, Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = StandaloneMmDriverEntryPointDynamicInit
+ MODULE_UNI_FILE = StandaloneMmDriver/StandaloneMmDriverEntryPoint.uni
+ FILE_GUID = 28CBCD87-2FEE-4D46-BB5C-B37732BBEEB1
+ MODULE_TYPE = MM_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ LIBRARY_CLASS = StandaloneMmDriverEntryPoint|MM_STANDALONE
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = X64 AARCH64
+#
+
+[Sources]
+ StandaloneMmDriver/StandaloneMmDriverEntryPoint.c
+
+[Sources.IA32]
+ IA32/DynamicCookieGcc.nasm | GCC
+ IA32/DynamicCookieMsvc.nasm | MSFT
+
+[Sources.X64]
+ X64/DynamicCookieGcc.nasm | GCC
+ X64/DynamicCookieMsvc.nasm | MSFT
+
+[Sources.AARCH64]
+ AArch64/DynamicCookieGcc.S | GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ MmServicesTableLib
+ StackCheckLib
+
+[Protocols]
+ gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMES
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplication/ApplicationEntryPoint.c b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplication/ApplicationEntryPoint.c
new file mode 100644
index 0000000000..0c57b20417
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplication/ApplicationEntryPoint.c
@@ -0,0 +1,112 @@
+/** @file
+ Entry point library instance to a UEFI application.
+
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/UefiApplicationEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+/**
+ Entry point to UEFI Application.
+
+ This function is the entry point for a UEFI Application. This function must call
+ ProcessLibraryConstructorList(), ProcessModuleEntryPointList(), and ProcessLibraryDestructorList().
+ The return value from ProcessModuleEntryPointList() is returned.
+ If _gUefiDriverRevision is not zero and SystemTable->Hdr.Revision is less than _gUefiDriverRevison,
+ then return EFI_INCOMPATIBLE_VERSION.
+
+ @param ImageHandle The image handle of the UEFI Application.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The UEFI Application exited normally.
+ @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than SystemTable->Hdr.Revision.
+ @retval Other Return value from ProcessModuleEntryPointList().
+
+**/
+EFI_STATUS
+EFIAPI
+_CModuleEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ if (_gUefiDriverRevision != 0) {
+ //
+ // Make sure that the EFI/UEFI spec revision of the platform is >= EFI/UEFI spec revision of the application.
+ //
+ if (SystemTable->Hdr.Revision < _gUefiDriverRevision) {
+ return EFI_INCOMPATIBLE_VERSION;
+ }
+ }
+
+ //
+ // Call constructor for all libraries.
+ //
+ ProcessLibraryConstructorList (ImageHandle, SystemTable);
+
+ //
+ // Call the module's entry point
+ //
+ Status = ProcessModuleEntryPointList (ImageHandle, SystemTable);
+
+ //
+ // Process destructor for all libraries.
+ //
+ ProcessLibraryDestructorList (ImageHandle, SystemTable);
+
+ //
+ // Return the return status code from the driver entry point
+ //
+ return Status;
+}
+
+/**
+ Invokes the library destructors for all dependent libraries and terminates
+ the UEFI Application.
+
+ This function calls ProcessLibraryDestructorList() and the EFI Boot Service Exit()
+ with a status specified by Status.
+
+ @param Status Status returned by the application that is exiting.
+
+**/
+VOID
+EFIAPI
+Exit (
+ IN EFI_STATUS Status
+ )
+
+{
+ ProcessLibraryDestructorList (gImageHandle, gST);
+
+ gBS->Exit (gImageHandle, Status, 0, NULL);
+}
+
+/**
+ Required by the EBC compiler and identical in functionality to _ModuleEntryPoint().
+
+ @param ImageHandle The image handle of the UEFI Application.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The UEFI Application exited normally.
+ @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than SystemTable->Hdr.Revision.
+ @retval Other Return value from ProcessModuleEntryPointList().
+
+**/
+EFI_STATUS
+EFIAPI
+EfiMain (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return _ModuleEntryPoint (ImageHandle, SystemTable);
+}
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplication/ApplicationStackCheckEntryPointLibNull.c b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplication/ApplicationStackCheckEntryPointLibNull.c
new file mode 100644
index 0000000000..7c18e22ae7
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplication/ApplicationStackCheckEntryPointLibNull.c
@@ -0,0 +1,50 @@
+/** @file
+ Entry point library instance to a UEFI application that does not update the stack cookie dynamically.
+
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/UefiApplicationEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+extern
+EFI_STATUS
+EFIAPI
+_CModuleEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Entry point to UEFI Application.
+
+ This function is the entry point for a UEFI Application. This function must call
+ ProcessLibraryConstructorList(), ProcessModuleEntryPointList(), and ProcessLibraryDestructorList().
+ The return value from ProcessModuleEntryPointList() is returned.
+ If _gUefiDriverRevision is not zero and SystemTable->Hdr.Revision is less than _gUefiDriverRevison,
+ then return EFI_INCOMPATIBLE_VERSION.
+
+ @param ImageHandle The image handle of the UEFI Application.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The UEFI Application exited normally.
+ @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than SystemTable->Hdr.Revision.
+ @retval Other Return value from ProcessModuleEntryPointList().
+
+**/
+EFI_STATUS
+EFIAPI
+_ModuleEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // Call the module's entry point
+ //
+ return _CModuleEntryPoint (ImageHandle, SystemTable);
+}
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplication/UefiApplicationEntryPoint.uni b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplication/UefiApplicationEntryPoint.uni
new file mode 100644
index 0000000000..8a68a8a70c
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplication/UefiApplicationEntryPoint.uni
@@ -0,0 +1,16 @@
+// /** @file
+// Module entry point library for UEFI Application.
+//
+// Module entry point library for UEFI Application.
+//
+// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Module entry point library for UEFI Application"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Module entry point library for UEFI Application."
+
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplicationEntryPoint.inf b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplicationEntryPoint.inf
new file mode 100644
index 0000000000..596303e001
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplicationEntryPoint.inf
@@ -0,0 +1,45 @@
+## @file
+# Module entry point library for UEFI Application that dynamically updates the stack cookie.
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = UefiApplicationEntryPointDynamicInit
+ MODULE_UNI_FILE = UefiApplication/UefiApplicationEntryPoint.uni
+ FILE_GUID = 755B9094-E5AF-4E5B-BE33-D430CDE2C5D2
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = UefiApplicationEntryPoint|UEFI_APPLICATION
+
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ UefiApplication/ApplicationEntryPoint.c
+
+[Sources.IA32]
+ IA32/DynamicCookieGcc.nasm | GCC
+ IA32/DynamicCookieMsvc.nasm | MSFT
+
+[Sources.X64]
+ X64/DynamicCookieGcc.nasm | GCC
+ X64/DynamicCookieMsvc.nasm | MSFT
+
+[Sources.AARCH64]
+ AArch64/DynamicCookieGcc.S | GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ DebugLib
+ BaseLib
+ StackCheckLib
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriver/DriverEntryPoint.c b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriver/DriverEntryPoint.c
new file mode 100644
index 0000000000..09e7bcaea5
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriver/DriverEntryPoint.c
@@ -0,0 +1,162 @@
+/** @file
+ Entry point to a EFI/DXE driver.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Protocol/LoadedImage.h>
+
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+/**
+ Unloads an image from memory.
+
+ This function is a callback that a driver registers to do cleanup
+ when the UnloadImage boot service function is called.
+
+ @param ImageHandle The handle to the image to unload.
+
+ @return Status returned by all unload().
+
+**/
+EFI_STATUS
+EFIAPI
+_DriverUnloadHandler (
+ EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // If an UnloadImage() handler is specified, then call it
+ //
+ Status = ProcessModuleUnloadList (ImageHandle);
+
+ //
+ // If the driver specific unload handler does not return an error, then call all of the
+ // library destructors. If the unload handler returned an error, then the driver can not be
+ // unloaded, and the library destructors should not be called
+ //
+ if (!EFI_ERROR (Status)) {
+ ProcessLibraryDestructorList (ImageHandle, gST);
+ }
+
+ //
+ // Return the status from the driver specific unload handler
+ //
+ return Status;
+}
+
+/**
+ The entry point of PE/COFF Image for a DXE Driver, DXE Runtime Driver, DXE SMM
+ Driver, or UEFI Driver.
+
+ This function is the entry point for a DXE Driver, DXE Runtime Driver, DXE SMM Driver,
+ or UEFI Driver. This function must call ProcessLibraryConstructorList() and
+ ProcessModuleEntryPointList(). If the return status from ProcessModuleEntryPointList()
+ is an error status, then ProcessLibraryDestructorList() must be called. The return
+ value from ProcessModuleEntryPointList() is returned. If _gDriverUnloadImageCount
+ is greater than zero, then an unload handler must be registered for this image
+ and the unload handler must invoke ProcessModuleUnloadList().
+ If _gUefiDriverRevision is not zero and SystemTable->Hdr.Revision is less than
+ _gUefiDriverRevison, then return EFI_INCOMPATIBLE_VERSION.
+
+
+ @param ImageHandle The image handle of the DXE Driver, DXE Runtime Driver,
+ DXE SMM Driver, or UEFI Driver.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The DXE Driver, DXE Runtime Driver, DXE SMM
+ Driver, or UEFI Driver exited normally.
+ @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than
+ SystemTable->Hdr.Revision.
+ @retval Other Return value from ProcessModuleEntryPointList().
+
+**/
+EFI_STATUS
+EFIAPI
+_CModuleEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+
+ if (_gUefiDriverRevision != 0) {
+ //
+ // Make sure that the EFI/UEFI spec revision of the platform is >= EFI/UEFI spec revision of the driver
+ //
+ if (SystemTable->Hdr.Revision < _gUefiDriverRevision) {
+ return EFI_INCOMPATIBLE_VERSION;
+ }
+ }
+
+ //
+ // Call constructor for all libraries
+ //
+ ProcessLibraryConstructorList (ImageHandle, SystemTable);
+
+ //
+ // Install unload handler...
+ //
+ if (_gDriverUnloadImageCount != 0) {
+ Status = gBS->HandleProtocol (
+ ImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **)&LoadedImage
+ );
+ ASSERT_EFI_ERROR (Status);
+ LoadedImage->Unload = _DriverUnloadHandler;
+ }
+
+ //
+ // Call the driver entry point
+ //
+ Status = ProcessModuleEntryPointList (ImageHandle, SystemTable);
+
+ //
+ // If all of the drivers returned errors, then invoke all of the library destructors
+ //
+ if (EFI_ERROR (Status)) {
+ ProcessLibraryDestructorList (ImageHandle, SystemTable);
+ }
+
+ //
+ // Return the cummalative return status code from all of the driver entry points
+ //
+ return Status;
+}
+
+/**
+ Required by the EBC compiler and identical in functionality to _ModuleEntryPoint().
+
+ This function is required to call _ModuleEntryPoint() passing in ImageHandle,
+ and SystemTable.
+
+ @param ImageHandle The image handle of the DXE Driver, DXE Runtime Driver, DXE
+ SMM Driver, or UEFI Driver.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The DXE Driver, DXE Runtime Driver, DXE SMM
+ Driver, or UEFI Driver exited normally.
+ @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than
+ SystemTable->Hdr.Revision.
+ @retval Other Return value from ProcessModuleEntryPointList().
+**/
+EFI_STATUS
+EFIAPI
+EfiMain (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return _ModuleEntryPoint (ImageHandle, SystemTable);
+}
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriver/UefiDriverEntryPoint.uni b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriver/UefiDriverEntryPoint.uni
new file mode 100644
index 0000000000..6667c378fa
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriver/UefiDriverEntryPoint.uni
@@ -0,0 +1,16 @@
+// /** @file
+// Module entry point library for UEFI driver, DXE driver and SMM driver.
+//
+// Module entry point library for UEFI driver, DXE driver and SMM driver.
+//
+// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Module entry point library for UEFI driver, DXE driver and SMM driver"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Module entry point library for UEFI driver, DXE driver and SMM driver."
+
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriverEntryPoint.inf b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriverEntryPoint.inf
new file mode 100644
index 0000000000..d624c3e1a3
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriverEntryPoint.inf
@@ -0,0 +1,68 @@
+## @file
+# Module entry point library for UEFI driver, DXE driver and SMM driver that dynamically sets the stack cookie.
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = UefiDriverEntryPointDynamicInit
+ MODULE_UNI_FILE = UefiDriver/UefiDriverEntryPoint.uni
+ FILE_GUID = 900238F9-1421-4596-9548-A1BF58C97693
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = UefiDriverEntryPoint|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_DRIVER SMM_CORE DXE_SMM_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ UefiDriver/DriverEntryPoint.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[Sources.IA32]
+ IA32/DynamicCookieGcc.nasm | GCC
+ IA32/DynamicCookieMsvc.nasm | MSFT
+
+[Sources.X64]
+ X64/DynamicCookieGcc.nasm | GCC
+ X64/DynamicCookieMsvc.nasm | MSFT
+
+[Sources.AARCH64]
+ AArch64/DynamicCookieGcc.S | GCC
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ DebugLib
+ BaseLib
+ StackCheckLib
+
+[Protocols]
+ gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMES
+
+#
+# For UEFI drivers, these architectural protocols defined in PI 1.0 spec need
+# to be appended and merged to the final dependency section.
+#
+[Depex.common.UEFI_DRIVER]
+ gEfiBdsArchProtocolGuid AND
+ gEfiCpuArchProtocolGuid AND
+ gEfiMetronomeArchProtocolGuid AND
+ gEfiMonotonicCounterArchProtocolGuid AND
+ gEfiRealTimeClockArchProtocolGuid AND
+ gEfiResetArchProtocolGuid AND
+ gEfiRuntimeArchProtocolGuid AND
+ gEfiSecurityArchProtocolGuid AND
+ gEfiTimerArchProtocolGuid AND
+ gEfiVariableWriteArchProtocolGuid AND
+ gEfiVariableArchProtocolGuid AND
+ gEfiWatchdogTimerArchProtocolGuid
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/X64/DynamicCookieGcc.nasm b/MdePkg/Library/DynamicStackCookieEntryPointLib/X64/DynamicCookieGcc.nasm
new file mode 100644
index 0000000000..872e0f703c
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/X64/DynamicCookieGcc.nasm
@@ -0,0 +1,63 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) Microsoft Corporation.
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; DynamicCookie.nasm
+;
+; Abstract:
+;
+; Generates random number through CPU RdRand instruction on 64-bit platform
+; to store a random value in the GCC __stack_check_guard stack cookie.
+; The first byte is 0'd to prevent string copy functions from clobbering
+; the stack cookie.
+;
+; Notes:
+;
+; If RdRand fails, the build time static stack cookie value will be used instead.
+;
+;------------------------------------------------------------------------------
+
+DEFAULT REL
+SECTION .text
+
+extern ASM_PFX(__stack_chk_guard)
+extern ASM_PFX(_CModuleEntryPoint)
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; _ModuleEntryPoint (
+; Parameters are passed through. TODO: Make sure there are only two args on X64
+; );
+;------------------------------------------------------------------------------
+global ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+ push rbx
+ push rcx
+ push rdx
+
+ mov eax, 1 ; Set eax to 1 to get feature information
+ cpuid ; Call cpuid
+ test ecx, 0x40000000 ; Test the rdrand bit (bit 30) in ecx
+ jz c_entry ; If rdrand is not supported, jump to c_entry
+
+ rdrand rax ; Call rdrand functionality here, getting a 64 bit value as on
+ ; X64, __stack_chk_guard is a 64 bit value.
+ ; CF=1 if RN generated ok, otherwise CF=0
+ jnc c_entry ; If the cmd fails, don't, update __stack_chk_guard, we'll have to move forward
+ ; with the static value provided at build time.
+
+ lea rbx, [rel ASM_PFX(__stack_chk_guard)] ; load the address of __stack_check_guard into rbx
+
+ xor ah, ah ; Zero a byte of the __stack_chk_guard value to protect against string functions
+ ; (such as strcpy like functions) clobbering past the canary
+ mov [rbx], rax ; Store our random value, with 0'd first byte to __stack_chk_guard
+
+c_entry:
+ pop rdx
+ pop rcx
+ pop rbx
+ jmp ASM_PFX(_CModuleEntryPoint)
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/X64/DynamicCookieMsvc.nasm b/MdePkg/Library/DynamicStackCookieEntryPointLib/X64/DynamicCookieMsvc.nasm
new file mode 100644
index 0000000000..23c34e7289
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/X64/DynamicCookieMsvc.nasm
@@ -0,0 +1,63 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) Microsoft Corporation.
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; DynamicCookie.nasm
+;
+; Abstract:
+;
+; Generates random number through CPU RdRand instruction on 64-bit platform
+; to store a random value in the GCC __stack_check_guard stack cookie.
+; The first byte is 0'd to prevent string copy functions from clobbering
+; the stack cookie.
+;
+; Notes:
+;
+; If RdRand fails, the build time static stack cookie value will be used instead.
+;
+;------------------------------------------------------------------------------
+
+DEFAULT REL
+SECTION .text
+
+extern ASM_PFX(__security_cookie)
+extern ASM_PFX(_CModuleEntryPoint)
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; _ModuleEntryPoint (
+; Parameters are passed through. TODO: Make sure there are only two args on X64
+; );
+;------------------------------------------------------------------------------
+global ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+ push rbx
+ push rcx
+ push rdx
+
+ mov eax, 1 ; Set eax to 1 to get feature information
+ cpuid ; Call cpuid
+ test ecx, 0x40000000 ; Test the rdrand bit (bit 30) in ecx
+ jz c_entry ; If rdrand is not supported, jump to c_entry
+
+ rdrand rax ; Call rdrand functionality here, getting a 64 bit value as on
+ ; X64, __stack_chk_guard is a 64 bit value.
+ ; CF=1 if RN generated ok, otherwise CF=0
+ jnc c_entry ; If the cmd fails, don't, update __stack_chk_guard, we'll have to move forward
+ ; with the static value provided at build time.
+
+ lea rbx, [rel ASM_PFX(__security_cookie)] ; load the address of __stack_check_guard into rbx
+
+ xor ah, ah ; Zero a byte of the __stack_chk_guard value to protect against string functions
+ ; (such as strcpy like functions) clobbering past the canary
+ mov [rbx], rax ; Store our random value, with 0'd first byte to __stack_chk_guard
+
+c_entry:
+ pop rdx
+ pop rcx
+ pop rbx
+ jmp ASM_PFX(_CModuleEntryPoint)
diff --git a/MdePkg/Library/StackCheckLib/Readme.md b/MdePkg/Library/StackCheckLib/Readme.md
index 8d15ad4ca4..2d9bb6fbda 100644
--- a/MdePkg/Library/StackCheckLib/Readme.md
+++ b/MdePkg/Library/StackCheckLib/Readme.md
@@ -1,12 +1,12 @@
-# StackCheckLib
+# StackCheckLib Overview
## Table of Contents
- [StackCheckLib](#stackchecklib)
- [Table of Contents](#table-of-contents)
- [Introduction and Library Instances](#introduction-and-library-instances)
- - [StackCheckLibStaticInit](#stackchecklibstaticinit)
- - [StackCheckLibDynamicInit](#stackchecklibdynamicinit)
+ - [StackCheckLib](#stackchecklib)
+ - [DynamicStackCookieEntryPointLib](#dynamicstackcookieentrypointlib)
- [StackCheckLibNull](#stackchecklibnull)
- [How Failures are Handled](#how-failures-are-handled)
- [Debugging Stack Cookie Check Failures](#debugging-stack-cookie-check-failures)
@@ -15,44 +15,79 @@
## Introduction and Library Instances
`StackCheckLib` contains the required functionality for initializing the stack cookie
-value, checking the value, and triggering an interrupt when a mismatch occurs.
-The stack cookie is a random value placed on the stack between the stack variables
-and the return address so that continuously writing past the stack variables will
-cause the stack cookie to be overwritten. Before the function returns, the stack
-cookie value will be checked and if there is a mismatch then `StackCheckLib` handles
-the failure.
+value (based on a randomly generated value during build time), checking the value,
+and triggering an interrupt when a mismatch occurs. The stack cookie is a random value
+placed on the stack between the stack variables and the return address so that
+continuously writing past the stack variables will cause the stack cookie to be
+overwritten. Before the function returns, the stack cookie value will be checked and
+if there is a mismatch then `StackCheckLib` handles the failure.
Because UEFI doesn't use the C runtime libraries provided by MSVC, the stack
check code is written in assembly within this library. GCC and Clang compilers
have built-in support for stack cookie checking, so this library only handles failures.
-### StackCheckLibStaticInit
-
-`StackCheckLibStaticInit` is an instance of `StackCheckLib` which does not update the
-stack cookie value for the module at runtime. It's always preferable to use
-`StackCheckLibDynamicInit` for improved security but there are cases where the stack
-cookie global cannot be written to such as in execute-in-place (XIP) modules and during
-the Cache-as-RAM (CAR) phase of the boot process. The stack cookie value is initialized
-at compile time via updates to the AutoGen process. Each module will define
-`STACK_COOKIE_VALUE` which is used for the module stack cookie value.
-
-### StackCheckLibDynamicInit
-
-This section is future work. The below is the proposed instance.
-
-`StackCheckLibDynamicInit` is an instance of `StackCheckLib` which updates the stack
-cookie value for the module at runtime. This is the preferred method for stack cookie
-initialization as it provides improved security. The stack cookie value is initialized
-at runtime by calling `GetRandomNumber32()` or `GetRandomNumber64()` to generate a random
-value via the platform's random number generator protocol. If the random number generator
-returns an error, then the value will still have the build-time randomized value to fall
-back on.
+The stack cookie value is initialized at compile time via updates to the AutoGen process.
+Each module will define `STACK_COOKIE_VALUE` which is used for the module stack cookie
+value.
+
+The entry point libraries under `MdePkg/DynamicStackCookieEntryPointLib/` update the stack
+cookie value at runtime for improved security, but there are cases where the stack cookie
+global cannot be written to such as in execute-in-place (XIP) modules and during the
+temporary RAM phase of the boot process. It is always preferable to use
+one of the dynamic stack cookie entry points when possible.
+
+### StackCheckLib
+
+`StackCheckLib` provides the stack cookie checking functionality per architecture and
+toolchain. The currently supported pairs are IA32{GCC,MSVC}, X64{GCC, MSVC},
+ARM{GCC, MSVC}, and AARCH64{GCC, MSVC}. `StackCheckLib` is agnostic as to
+whether the stack cookie was updated during build time or run time; it simply
+checks the cookie in the MSVC case and in both GCC and MSVC responds to stack
+cookie checking failures.
+
+To add support for other architectures/toolchains, additional assembly files
+should be added to `StackCheckLib.inf` and scoped to that architecture/toolchain.
+
+Note: Stack cookie failures generate exceptions and SEC and PEI_CORE may not have
+exception handlers registered. In order to safely use stack cookie checking in
+these phases, a platform should implement exception handlers because unhandled
+exceptions may lead to a hung system state. If a platform does not implement
+exception handlers in SEC and PEI_CORE, it is recommended to use `StackCheckLibNull`
+for these phases, except for development purposes.
+
+### DynamicStackCookieEntryPointLib
+
+Each EntryPoint lib under `MdePkg/DynamicStackCookieEntryPointLib/` is an instance of
+that module type entry point lib which updates the stack cookie value for the module at
+runtime. This is the preferred method for stack cookie initialization as it provides
+improved security. The stack cookie value is initialized at runtime in `_ModuleEntryPoint`
+by calling `rdrand` on x86 and `RNDR` on AARCH64. If the random number generator is not
+supported on that platform or otherwise returns an error, then the value will still have
+the build-time randomized value to fall back on.
+
+Typically, dynamic cookies cannot be used for SEC, PEI_CORE, and PEIM modules, due to
+the lack of the ability to write to globals for many architectures. If a given platform
+can write to globals during these phases, it is recommended to use the provided dynamic
+stack cookie entry point lib for those types. Note that SEC does not have a universal
+entry point, so there is no dynamic stack cookie entry point lib there.
+
+The dynamic stack cookie entry point lib is used in place of the standard entry point lib,
+e.g. for UefiDriverEntryPoint to have dynamic stack cookies, a platform would remove
+MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf from its DSC and instead
+include MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriverEntryPoint.inf.
+
+See the Usage section for other ways of including these libraries.
+
+Note: Standalone MM Core support for dynamic cookies for AARCH64 is currently not
+supported, due to the unique entry point mechanism there. This support will be
+added at a future date.
### StackCheckLibNull
`StackCheckLibNull` is an instance of `StackCheckLib` which does not perform any stack
cookie checks. This is useful for modules which will fail if stack cookie checks are
-inserted. Of course, this is not recommended for production code.
+inserted. Of course, this is not recommended for production code outside of
+SEC and PEI_CORE.
## How Failures are Handled
@@ -104,8 +139,9 @@ edk2 updated the tools_def to add `/GS` to VS2022 and VS2019 IA32/X64 builds and
`-fstack-protector` to GCC builds. This will cause stack cookie references to be inserted
throughout the code. Every module should have a `StackCheckLib` instance linked to satisfy
these references. So every module doesn't need to add `StackCheckLib` to the LibraryClasses
-section of the INF file, `StackCheckLib` instances should be linked as NULL in the platform
-DSC files. The only exception to this is MSVC built host-based unit tests as they will be
+section of the INF file, `StackCheckLib` is added as a dependency for each entry point lib.
+This means that custom entry point libs need to have StackCheckLib added as a dependency.
+The only exception to this is MSVC built host-based unit tests as they will be
compiled with the runtime libraries which already contain the stack cookie definitions
and will collide with `StackCheckLib`. A `StackCheckLibHostApplication.inf` is linked
by `UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc` that provides the stack
@@ -113,70 +149,80 @@ cookie functions for GCC HOST_APPLICATIONS but not for MSVC HOST_APPLICATIONS.
### Default Stack Check Library Configuration
-`MdePkg/MdeLibs.dsc.inc` links `StackCheckLibNull` for all types except SEC, HOST_APPLICATION,
-and USER_DEFINED in order to not break existing DSCs. SEC cannot be generically linked to
-because there are some SEC modules which do not link against the standard entry point
-libraries and thus do not get stack cookies inserted by the compiler. USER_DEFINED modules
-are by nature different from other modules, so we do not make any assumptions about their
-state.
+`MdePkg/MdeLibs.dsc.inc` links `StackCheckLibNull` and `StackCheckFailureLibNull` for all
+types.
As stated above, all HOST_APPLICATIONS will link against a HOST_APPLICATION specific
implementation provided in `UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc`.
-To link the rest of a platform's modules to `StackCheckLibNull`, a platform would needs
-to link it for all SEC and USER_DEFINED modules. If all of the DSC's SEC and USER_DEFINED
-modules link against the entry point libs, it would look like the following:
+### Custom Stack Check Library Configuration
+
+In order to use a different instance of StackCheckLib than `MdeLibs.dsc.inc` provides, a DSC
+should add one of the following:
+
+#### Static Stack Check Cookie Configuration
```inf
-[LibraryClasses.common.SEC, LibraryClasses.common.USER_DEFINED]
- NULL|MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf
+[Defines]
+ DEFINE CUSTOM_STACK_CHECK_LIB = STATIC
```
-If some do not, then the individual SEC/USER_DEFINED modules that do link against
-the entry point libs will need to be linked to `StackCheckLibNull`, such as below.
-This case is identifiable if a DSC is built and the linker complains the stack
-check functions are not found for a module.
+This will cause `MdeLibs.dsc.inc` to not link `StackCheckLibNull` and instead link
+`StackCheckLib` to perform stack cookie checking on the static stack cookies, but not update
+any of the stack cookies at runtime.
+
+Because edk2 does not implement exception handling for `SEC` and `PEI_CORE`, `MdeLibs.dsc.inc`
+uses `StackCheckLibNull` for these phases always. If a platform wishes to use `StackCheckLib`
+for these phases, it should override this in its DSC, e.g.:
```inf
-UefiCpuPkg/SecCore/SecCore.inf {
- <LibraryClasses>
- NULL|MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf
- }
+[LibraryClasses.common.SEC, LibraryClasses.common.PEI_CORE]
+ StackCheckLib|MdePkg/Library/StackCheckLib/StackCheckLib.inf
```
-### Custom Stack Check Library Configuration
+It is recommended that a platform only do this for debugging or if they have implemented
+exception handlers for these phases.
-In order to use a different instance of StackCheckLib than `MdeLibs.dsc.inc` provides, a DSC
-should add the following:
+#### Dynamic Stack Cookie Configuration
```inf
[Defines]
- DEFINE CUSTOM_STACK_CHECK_LIB = TRUE
+ DEFINE CUSTOM_STACK_CHECK_LIB = DYNAMIC
```
-This will cause `MdeLibs.dsc.inc` to not link `StackCheckLibNull` and rely on a DSC to
-link whichever version(s) of `StackCheckLib` it desires.
-
-It is recommended that SEC and PEI_CORE modules use `StackCheckLibNull` and pre-memory modules
-should use `StackCheckLibStaticInit`. All other modules should use `StackCheckLibDynamicInit`.
+This will cause `MdeLibs.dsc.inc` to not link `StackCheckLibNull` and instead link
+`StackCheckLib` to perform stack cookie checking. It will also link the dynamic
+stack cookie updating versions of `DxeCoreEntryPoint`, `StandaloneMmDriverEntryPoint`,
+`UefiApplicationEntryPoint`, and `UefiDriverEntryPoint`.
-Below is an **example** of how to link the `StackCheckLib` instances in the platform DSC file
-but it may need customization based on the platform's requirements:
+Because edk2 does not implement exception handling for `SEC` and `PEI_CORE`, `MdeLibs.dsc.inc`
+uses `StackCheckLibNull` for these phases always. As a result, dynamic stack cookies are also
+not set for `PEI_CORE`. There is no standard `SEC` entrypoint, so it is not supported generically
+to apply dynamic stack cookies there. If a platform wishes to use `StackCheckLib` and dynamic stack
+cookies for these phases, it should override this in its DSC, e.g.:
```inf
[LibraryClasses.common.SEC, LibraryClasses.common.PEI_CORE]
- NULL|MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf
+ StackCheckLib|MdePkg/Library/StackCheckLib/StackCheckLib.inf
+ PeiCoreEntryPoint|MdePkg/Library/DynamicStackCookieEntryPointLib/PeiCoreEntryPoint.inf
+```
+
+It is recommended that a platform only do this for debugging or if they have implemented
+exception handlers for these phases.
-[LibraryClasses.common.PEIM]
- NULL|MdePkg/Library/StackCheckLib/StackCheckLibStaticInit.inf
+Note: `StandaloneMmCoreEntryPoint` is recommended to use the dynamic stack cookie if
+possible, but as it is not supported on AARCH64 today, it is not included in MdeLibs.dsc.inc.
+Platforms should include this separately, e.g.:
-[LibraryClasses.common.MM_CORE_STANDALONE, LibraryClasses.common.MM_STANDALONE, LibraryClasses.common.DXE_CORE,
-LibraryClasses.common.SMM_CORE, LibraryClasses.common.DXE_SMM_DRIVER, LibraryClasses.common.DXE_DRIVER,
-LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.DXE_SAL_DRIVER, LibraryClasses.common.UEFI_DRIVER,
-LibraryClasses.common.UEFI_APPLICATION]
- NULL|MdePkg/Library/StackCheckLib/StackCheckLibDynamicInit.inf
+```inf
+[LibraryClasses.X64]
+ StandaloneMmCoreEntryPoint|MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmCoreEntryPoint.inf
```
+Platforms then must remove any references to these entry point libs in their DSC, so that
+the `MdeLibs.dsc.inc` versions are chosen. Alternatively, for better DSC readability,
+a platform can directly reference the dynamic stack cookie entry points.
+
### Disable Stack Check Library
If a platform would like to disable stack cookies (say for debugging purposes),
@@ -191,4 +237,14 @@ they can add the following to their DSC:
The same build options can be put in a module's INF to only disable stack cookies
for that module.
+Alternatively, a module can have the stack cookies inserted but checking disabled
+by including the following in a DSC:
+
+```inf
+SomePkg/SomeDirectory/SomeModule.inf {
+ <LibraryClasses>
+ StackCheckLib|MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf
+}
+```
+
It is not recommended to disable stack cookie checking in production scenarios.
diff --git a/MdePkg/MdeLibs.dsc.inc b/MdePkg/MdeLibs.dsc.inc
index 19a883d50d..57818e2499 100644
--- a/MdePkg/MdeLibs.dsc.inc
+++ b/MdePkg/MdeLibs.dsc.inc
@@ -11,6 +11,14 @@
#
##
+[Defines]
+!ifndef CUSTOM_STACK_CHECK_LIB
+ # The DSC parser will set any unset macros to 0. Then, below when we check for STATIC or DYNAMIC, even if we couch
+ # that in a !ifdef CUSTOM_STACK_CHECK_LIB, the parser will issue a warning that we are comparing a boolean (0) against
+ # a string, which will always fail. So we set it to a dummy value here.
+ DEFINE CUSTOM_STACK_CHECK_LIB = NONE
+!endif
+
[LibraryClasses]
OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf
ArmTrngLib|MdePkg/Library/BaseArmTrngLibNull/BaseArmTrngLibNull.inf
@@ -22,13 +30,35 @@
MmUnblockMemoryLib|MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf
StackCheckFailureHookLib|MdePkg/Library/StackCheckFailureHookLibNull/StackCheckFailureHookLibNull.inf
-!ifndef CUSTOM_STACK_CHECK_LIB
+!if $(CUSTOM_STACK_CHECK_LIB) == STATIC
+ # To only use the static stack cookie, we just include the checking functionality.
+ StackCheckLib|MdePkg/Library/StackCheckLib/StackCheckLib.inf
+!elseif $(CUSTOM_STACK_CHECK_LIB) == DYNAMIC
+ StackCheckLib|MdePkg/Library/StackCheckLib/StackCheckLib.inf
+
+ # To use the dynamic stack cookie, we need to include the entry point libraries that will set up the stack cookie.
+ # Typically, PeiCore and PEIMs will not use dynamic stack cookies, so they are not included generally.
+ # If dynamic stack cookies are not enabled, we do not setup the entry points, as the existing behavior was
+ # for a platform to define them.
+ # StandaloneMmCoreEntryPoint is not included here because support dynamic stack cookies is not available for
+ # AARCH64 here. X64 platforms should include the DynamicStackCookieEntryPointLib in their DSC file.
+ DxeCoreEntryPoint|MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCoreEntryPoint.inf
+ StandaloneMmDriverEntryPoint|MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriverEntryPoint.inf
+ UefiApplicationEntryPoint|MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplicationEntryPoint.inf
+ UefiDriverEntryPoint|MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriverEntryPoint.inf
+
+!else
# If CUSTOM_STACK_CHECK_LIB is set, MdeLibs.dsc.inc will not link StackCheckLibNull and it is expected that the
# DSC being built is providing it's own implementation of StackCheckLib.
- NULL|MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf
-
+ StackCheckLib|MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf
!endif
+[LibraryClasses.common.SEC, LibraryClasses.common.PEI_CORE]
+ # edk2 does not implement exception handling for SEC and PEI_CORE, so StackCheckLibNull is used, as failing
+ # stack cookies will generate an exception, which if unhandled can lead to a hung system state. If a platform
+ # implements exception handling for SEC and PEI_CORE, it can use StackCheckLib for these phases in its DSC.
+ StackCheckLib|MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf
+
[LibraryClasses.ARM, LibraryClasses.AARCH64]
#
# It is not possible to prevent the ARM/AARCH64 compilers from inserting generic intrinsic functions.
diff --git a/MdePkg/MdePkg.dsc b/MdePkg/MdePkg.dsc
index ccefe558f3..12a1b8f13c 100644
--- a/MdePkg/MdePkg.dsc
+++ b/MdePkg/MdePkg.dsc
@@ -143,6 +143,12 @@
MdePkg/Library/StackCheckFailureHookLibNull/StackCheckFailureHookLibNull.inf
MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf
MdePkg/Library/StackCheckLib/StackCheckLib.inf
+ MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCoreEntryPoint.inf
+ MdePkg/Library/DynamicStackCookieEntryPointLib/PeiCoreEntryPoint.inf
+ MdePkg/Library/DynamicStackCookieEntryPointLib/PeimEntryPoint.inf
+ MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriverEntryPoint.inf
+ MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplicationEntryPoint.inf
+ MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriverEntryPoint.inf
[Components.IA32, Components.X64, Components.ARM, Components.AARCH64]
#
@@ -193,6 +199,7 @@
MdePkg/Library/TraceHubDebugSysTLibNull/TraceHubDebugSysTLibNull.inf
[Components.X64]
+ MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmCoreEntryPoint.inf
MdePkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf
[Components.EBC]