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 + +.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.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include + +// +// 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.
+// +// 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.
+# +# 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.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +// +// The Library classes this module produced +// +#include +#include +#include + +/** + 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.
+// +// 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.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +// +// The Library classes this module produced +// +#include +#include +#include + +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.
+# +# 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.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include + +/** + 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.
+// +// 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.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include + +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.
+# +# 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.
+Copyright (c) Microsoft Corporation. +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include + +// +// 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.
+# +# 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.
+Copyright (c) 2016 - 2018, ARM Ltd. All rights reserved.
+Copyright (c) 2018, Linaro, Limited. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include + +/** + 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.
+// Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
+// Copyright (c) 2018, Linaro, Limited. All rights reserved.
+// +// 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.
+# Copyright (c) 2016-2018, ARM Ltd. All rights reserved.
+# Copyright (c) 2018, Linaro, Limited. All rights reserved.
+# +# 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.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include + +/** + 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.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +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.
+// +// 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.
+# +# 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.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include + +#include +#include +#include +#include + +/** + 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.
+// +// 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.
+# +# 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 +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. -`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. +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. -### StackCheckLibDynamicInit +### StackCheckLib -This section is future work. The below is the proposed instance. +`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. -`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. +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: - -```inf -[LibraryClasses.common.SEC, LibraryClasses.common.USER_DEFINED] - NULL|MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf -``` - -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. - -```inf -UefiCpuPkg/SecCore/SecCore.inf { - - NULL|MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf - } -``` - ### Custom Stack Check Library Configuration In order to use a different instance of StackCheckLib than `MdeLibs.dsc.inc` provides, a DSC -should add the following: +should add one of the following: + +#### Static Stack Check Cookie Configuration ```inf [Defines] - DEFINE CUSTOM_STACK_CHECK_LIB = TRUE + DEFINE CUSTOM_STACK_CHECK_LIB = STATIC ``` -This will cause `MdeLibs.dsc.inc` to not link `StackCheckLibNull` and rely on a DSC to -link whichever version(s) of `StackCheckLib` it desires. +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. -It is recommended that SEC and PEI_CORE modules use `StackCheckLibNull` and pre-memory modules -should use `StackCheckLibStaticInit`. All other modules should use `StackCheckLibDynamicInit`. - -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. If a platform wishes to use `StackCheckLib` +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 - -[LibraryClasses.common.PEIM] - NULL|MdePkg/Library/StackCheckLib/StackCheckLibStaticInit.inf - -[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 + StackCheckLib|MdePkg/Library/StackCheckLib/StackCheckLib.inf ``` +It is recommended that a platform only do this for debugging or if they have implemented +exception handlers for these phases. + +#### Dynamic Stack Cookie Configuration + +```inf +[Defines] + DEFINE CUSTOM_STACK_CHECK_LIB = DYNAMIC +``` + +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`. + +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] + 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. + +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.: + +```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 { + + 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]