Skip to content

Commit

Permalink
Add Stack Cookie Support for IA32, ARM, and AARCH64
Browse files Browse the repository at this point in the history
Description

This update replaces StackCheckLib with StackCheckLibStaticInit and
StackCheckLibDynamicInit. The new libraries have GCC support for ARM,
AARCH64, IA32 and X64 builds. The libraries have MSVC support for IA32
and X64 builds.

StackCheckLibStaticInit does not have a library constructor and
should be used whenever the stack cookie value cannot be updated
during driver execution (i.e. when the stack cookie is not in a
writable or no RNG library is available).

StackCheckLibDynamicInit has a library constructor and should be used
whenever the stack cookie value can be updated at runtime (i.e. for
DXE modules and shadowed PEIMs).

This update also removes the stack cookie library definitions from
MdeLibs.dsc.inc due to GCC build issues when the instanced versions are
used during CI builds. The instanced versions will need to be explicitly
added to the platform DSC files, and this is acceptable because
platforms will likely want to mix and match the static and dynamic
versions of the library for each module type.

- [x] Impacts functionality?
  - **Functionality** - Does the change ultimately impact how firmware functions?
  - Examples: Add a new library, publish a new PPI, update an algorithm, ...
- [x] Impacts security?
  - **Security** - Does the change have a direct security impact on an application,
    flow, or firmware?
  - Examples: Crypto algorithm change, buffer overflow fix, parameter
    validation improvement, ...
- [x] Breaking change?
  - **Breaking change** - Will anyone consuming this change experience a break
    in build or boot behavior?
  - Examples: Add a new library class, move a module to a different repo, call
    a function in a new library class in a pre-existing module, ...
- [ ] Includes tests?
  - **Tests** - Does the change include any explicit test code?
  - Examples: Unit tests, integration tests, robot tests, ...
- [ ] Includes documentation?
  - **Documentation** - Does the change contain explicit documentation additions
    outside direct code modifications (and comments)?
  - Examples: Update readme file, add feature readme file, link to documentation
    on an a separate Web page, ...

How This Was Tested

Tested on a Q35 GCC and MSVC builds, and on an SBSA GCC build
by purposefully performing a stack overflow.

Integration Instructions

Platforms will need to explicitly declare the
StackCheckLib and StackCheckFailureLib instances for
their platforms.

EXAMPLE:

```
StackCheckFailureLib|MdePkg/Library/StackCheckFailureLibNull/StackCheckFailureLibNull.inf
[LibraryClasses.common.SEC, LibraryClasses.common.PEI_CORE]
  NULL|MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf

[LibraryClasses.common.PEIM, LibraryClasses.common.MM_CORE_STANDALONE, LibraryClasses.common.MM_STANDALONE]
  NULL|MdePkg/Library/StackCheckLib/StackCheckLibStaticInit.inf

[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
```
  • Loading branch information
TaylorBeebe committed Mar 2, 2024
1 parent 9222414 commit 2ffdb64
Show file tree
Hide file tree
Showing 23 changed files with 230 additions and 138 deletions.
7 changes: 5 additions & 2 deletions BaseTools/Source/Python/AutoGen/GenC.py
Original file line number Diff line number Diff line change
Expand Up @@ -700,10 +700,12 @@
}

## Library Constructor and Destructor Templates
# MU_CHANGE [BEGIN]: Add StackCookieSupport marker for stack cookie support.
gLibraryString = {
SUP_MODULE_BASE : TemplateString("""
${BEGIN}${FunctionPrototype}${END}
${StackCookieSupport}
VOID
EFIAPI
ProcessLibrary${Type}List (
Expand All @@ -714,10 +716,10 @@
${FunctionCall}${END}
}
"""),
# MU_CHANGE [BEGIN]: Add StackCookieSupport marker for stack cookie support.
'PEI' : TemplateString("""
${BEGIN}${FunctionPrototype}${END}
${StackCookieSupport}
VOID
EFIAPI
ProcessLibrary${Type}List (
Expand Down Expand Up @@ -745,10 +747,10 @@
${FunctionCall}${END}
}
"""),
# MU_CHANGE [END]: Add StackCookieSupport marker for stack cookie support.
'MM' : TemplateString("""
${BEGIN}${FunctionPrototype}${END}
${StackCookieSupport}
VOID
EFIAPI
ProcessLibrary${Type}List (
Expand All @@ -761,6 +763,7 @@
}
"""),
}
# MU_CHANGE [END]: Add StackCookieSupport marker for stack cookie support.

gBasicHeaderFile = "Base.h"

Expand Down
4 changes: 3 additions & 1 deletion CryptoPkg/CryptoPkg.dsc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
TlsLib|CryptoPkg/Library/TlsLibNull/TlsLibNull.inf
HashApiLib|CryptoPkg/Library/BaseHashApiLib/BaseHashApiLib.inf
RngLib|MdePkg/Library/BaseRngLibNull/BaseRngLibNull.inf
NULL|MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf # MU_CHANGE: /GS and -fstack-protector support


[LibraryClasses.common.UEFI_APPLICATION]
RngLib|MdePkg/Library/DxeRngLib/DxeRngLib.inf
Expand All @@ -62,7 +64,7 @@
NULL|MdePkg/Library/CompilerIntrinsicsLib/ArmCompilerIntrinsicsLib.inf

# Add support for stack protector
NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
# NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf # MU_CHANGE: Use Project Mu StackCheckLib

################################################################################
#
Expand Down
4 changes: 3 additions & 1 deletion MdeModulePkg/MdeModulePkg.dsc
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@

PanicLib|MdePkg/Library/BasePanicLibNull/BasePanicLibNull.inf # MU_CHANGE

NULL|MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf # MU_CHANGE: /GS and -fstack-protector support

# MU_CHANGE START Include MemoryProtectionHobLib
[LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.DXE_CORE, LibraryClasses.common.UEFI_APPLICATION]
DxeMemoryProtectionHobLib|MdeModulePkg/Library/MemoryProtectionHobLib/DxeMemoryProtectionHobLib.inf
Expand Down Expand Up @@ -235,7 +237,7 @@
# Since software stack checking may be heuristically enabled by the compiler
# include BaseStackCheckLib unconditionally.
#
NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
# NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf # MU_CHANGE: Use Project Mu StackCheckLib

[LibraryClasses.EBC, LibraryClasses.RISCV64, LibraryClasses.LOONGARCH64]
LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
Expand Down
21 changes: 21 additions & 0 deletions MdePkg/Library/StackCheckLib/AArch64/StackCookieInterrupt.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//------------------------------------------------------------------------------
// AArch64/StackCookieInterrupt.S
//
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: BSD-2-Clause-Patent
//------------------------------------------------------------------------------

.text

//------------------------------------------------------------------------------
// Calls an interrupt using the vector specified by PcdStackCookieExceptionVector
//
// VOID
// TriggerStackCookieInterrupt (
// VOID
// );
//------------------------------------------------------------------------------
.global ASM_PFX(TriggerStackCookieInterrupt)
ASM_PFX(TriggerStackCookieInterrupt):
smc FixedPcdGet8 (PcdStackCookieExceptionVector)
ret
21 changes: 21 additions & 0 deletions MdePkg/Library/StackCheckLib/Arm/StackCookieInterrupt.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//------------------------------------------------------------------------------
// Arm/StackCookieInterrupt.S
//
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: BSD-2-Clause-Patent
//------------------------------------------------------------------------------

.text

//------------------------------------------------------------------------------
// Calls an interrupt using the vector specified by PcdStackCookieExceptionVector
//
// VOID
// TriggerStackCookieInterrupt (
// VOID
// );
//------------------------------------------------------------------------------
.global ASM_PFX(TriggerStackCookieInterrupt)
ASM_PFX(TriggerStackCookieInterrupt):
swi FixedPcdGet8 (PcdStackCookieExceptionVector)
bx lr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
;------------------------------------------------------------------------------
; IA32/StackCheckFunctionsMsvc.nasm
; IA32/CheckCookieMsvc.nasm
;
; Copyright (c) Microsoft Corporation. All rights reserved.
; SPDX-License-Identifier: BSD-2-Clause-Patent
Expand All @@ -8,23 +8,8 @@
DEFAULT REL
SECTION .text

extern ASM_PFX(__security_cookie)
extern ASM_PFX(StackCheckFailure)
extern ASM_PFX(CpuDeadLoop)

; Called when a buffer check fails. This functionality is dependent on MSVC
; C runtime libraries and so is unsupported in UEFI.
global ASM_PFX(__report_rangecheckfailure)
ASM_PFX(__report_rangecheckfailure):
jmp ASM_PFX(CpuDeadLoop)
ret

; The GS handler is for checking the stack cookie during SEH or
; EH exceptions and is unsupported in UEFI.
global ASM_PFX(__GSHandlerCheck)
ASM_PFX(__GSHandlerCheck):
jmp ASM_PFX(CpuDeadLoop)
ret
extern ASM_PFX(__security_cookie)

;------------------------------------------------------------------------------
; Checks the stack cookie value against __security_cookie and calls the
Expand All @@ -33,15 +18,11 @@ ASM_PFX(__GSHandlerCheck):
; VOID
; EFIAPI
; __security_check_cookie (
; IN UINTN CheckValue);
; IN UINTN CheckValue
; );
;------------------------------------------------------------------------------
global @__security_check_cookie@4
@__security_check_cookie@4:
cmp ecx, [ASM_PFX(__security_cookie)]
jne security_check_cookie_failure
ret

security_check_cookie_failure:
call ASM_PFX(StackCheckFailure)
int FixedPcdGet8 (PcdStackCookieExceptionVector)
jne ASM_PFX(StackCheckFailure)
ret
23 changes: 23 additions & 0 deletions MdePkg/Library/StackCheckLib/IA32/StackCookieInterrupt.nasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
;------------------------------------------------------------------------------
; IA32/StackCookieInterrupt.nasm
;
; Copyright (c) Microsoft Corporation. All rights reserved.
; SPDX-License-Identifier: BSD-2-Clause-Patent
;------------------------------------------------------------------------------

DEFAULT REL
SECTION .text

;------------------------------------------------------------------------------
; Checks the stack cookie value against __security_cookie and calls the
; stack cookie failure handler if there is a mismatch.
;
; VOID
; TriggerStackCookieInterrupt (
; VOID
; );
;------------------------------------------------------------------------------
global ASM_PFX(TriggerStackCookieInterrupt)
ASM_PFX(TriggerStackCookieInterrupt):
int FixedPcdGet8 (PcdStackCookieExceptionVector)
ret
17 changes: 0 additions & 17 deletions MdePkg/Library/StackCheckLib/StackCheckFunctionsGcc.nasm

This file was deleted.

61 changes: 61 additions & 0 deletions MdePkg/Library/StackCheckLib/StackCheckLibCommon.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/** @file
Provides the required functionality for handling stack
cookie check failures.
Copyright (c) Microsoft Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#include <Base.h>

#include <Library/BaseLib.h>
#include <Library/DebugLib.h>

/**
Calls an interrupt using the vector specified by PcdStackCookieExceptionVector
**/
VOID
TriggerStackCookieInterrupt (
VOID
);

#if defined (__GNUC__) || defined (__clang__)

VOID *__stack_chk_guard = (VOID *)(UINTN)STACK_COOKIE_VALUE;

VOID
__stack_chk_fail (
VOID
)
{
TriggerStackCookieInterrupt ();
}

#elif defined (_MSC_VER)
VOID *__security_cookie = (VOID *)(UINTN)STACK_COOKIE_VALUE;

NORETURN VOID __cdecl
__report_rangecheckfailure (
VOID
)
{
CpuDeadLoop ();
}

NORETURN VOID __cdecl
__GSHandlerCheck (
VOID
)
{
CpuDeadLoop ();
}

VOID
StackCheckFailure (
VOID *ActualCookieValue
)
{
TriggerStackCookieInterrupt ();
}

#endif
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
/** @file
Provides the required functionality for initializing and
checking the stack cookie.
Provides the required functionality for initializing
the stack cookie value.
Copyright (c) Microsoft Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#include <Base.h>
#include <Uefi.h>
#include <Uefi/UefiBaseType.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/PeCoffLib.h>

#include <Library/RngLib.h>
#include <Library/StackCheckFailureLib.h>

#if defined (__GNUC__) || defined (__clang__)
VOID *__stack_chk_guard = (VOID *)0xBEEBE;
extern VOID *__stack_chk_guard;
#elif defined (_MSC_VER)
UINTN __security_cookie = 0xBEEBE;
extern VOID *__security_cookie;
#endif

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,42 @@

[Defines]
INF_VERSION = 0x00010005
BASE_NAME = StackCheckLib
BASE_NAME = StackCheckLibDynamicInit
FILE_GUID = 495b10c8-7148-4b62-92b0-7cf4551df83d
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = NULL
CONSTRUCTOR = InitializeSecurityCookie

[Sources]
StackCheckLib.c
StackCheckFunctionsGcc.nasm |GCC
StackCheckLibCommon.c
StackCheckLibDynamicInit.c

[Sources.IA32]
IA32/StackCheckFunctionsMsvc.nasm | MSFT
IA32/CheckCookieMsvc.nasm | MSFT

[Sources.X64]
X64/StackCheckFunctionsMsvc.nasm | MSFT
X64/CheckCookieMsvc.nasm | MSFT

[Sources.IA32, Sources.X64]
IA32/StackCookieInterrupt.nasm

[Sources.ARM]
Arm/StackCookieInterrupt.S |GCC

[Sources.AARCH64]
AArch64/StackCookieInterrupt.S |GCC

[Packages]
MdePkg/MdePkg.dec

[LibraryClasses]
BaseLib
BaseMemoryLib
DebugLib
RngLib
StackCheckFailureLib

[FixedPcd]
gEfiMdePkgTokenSpaceGuid.PcdStackCookieExceptionVector

# Disable LTO to ensure the linker doesn't optimize out the stack cookie
[BuildOptions]
GCC:*_*_*_CC_FLAGS = -fno-lto
MSFT:*_*_*_CC_FLAGS = /GL-
Loading

0 comments on commit 2ffdb64

Please sign in to comment.