From 0aac2f777a688a146050bed47753e2dcf801d3c7 Mon Sep 17 00:00:00 2001 From: "Yao, Jiewen" Date: Fri, 22 Feb 2019 21:30:34 +0800 Subject: [PATCH] MdePkg/BaseLib: Add Shadow Stack Support for X86. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1521 This patch adds SSP - shadow stack pointer to JumpBuffer. It will be used for the platform that enabled CET/ShadowStack. We add gEfiMdePkgTokenSpaceGuid.PcdControlFlowEnforcementPropertyMask to control the global enable/disable. Cc: Michael D Kinney Cc: Liming Gao Cc: Eric Dong Cc: Ray Ni Cc: Laszlo Ersek Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Yao Jiewen Reviewed-by: Ray Ni Regression-tested-by: Laszlo Ersek --- MdePkg/Include/Library/BaseLib.h | 2 ++ MdePkg/Library/BaseLib/BaseLib.inf | 3 ++- MdePkg/Library/BaseLib/Ia32/LongJump.c | 28 ++++++++++++++++++++++- MdePkg/Library/BaseLib/Ia32/LongJump.nasm | 25 +++++++++++++++++++- MdePkg/Library/BaseLib/Ia32/SetJump.c | 28 ++++++++++++++++++++++- MdePkg/Library/BaseLib/Ia32/SetJump.nasm | 23 ++++++++++++++++++- MdePkg/Library/BaseLib/X64/LongJump.nasm | 27 +++++++++++++++++++++- MdePkg/Library/BaseLib/X64/SetJump.nasm | 23 ++++++++++++++++++- MdePkg/MdePkg.dec | 7 ++++++ 9 files changed, 159 insertions(+), 7 deletions(-) diff --git a/MdePkg/Include/Library/BaseLib.h b/MdePkg/Include/Library/BaseLib.h index 9c42f82a7d..616ba2e95b 100644 --- a/MdePkg/Include/Library/BaseLib.h +++ b/MdePkg/Include/Library/BaseLib.h @@ -31,6 +31,7 @@ typedef struct { UINT32 Ebp; UINT32 Esp; UINT32 Eip; + UINT32 Ssp; } BASE_LIBRARY_JUMP_BUFFER; #define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 4 @@ -54,6 +55,7 @@ typedef struct { UINT64 Rip; UINT64 MxCsr; UINT8 XmmBuffer[160]; ///< XMM6-XMM15. + UINT64 Ssp; } BASE_LIBRARY_JUMP_BUFFER; #define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 8 diff --git a/MdePkg/Library/BaseLib/BaseLib.inf b/MdePkg/Library/BaseLib/BaseLib.inf index f25a067a23..a0d6c372f9 100644 --- a/MdePkg/Library/BaseLib/BaseLib.inf +++ b/MdePkg/Library/BaseLib/BaseLib.inf @@ -1,7 +1,7 @@ ## @file # Base Library implementation. # -# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.
# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
# Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
# @@ -620,6 +620,7 @@ gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength ## SOMETIMES_CONSUMES gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength ## SOMETIMES_CONSUMES gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdControlFlowEnforcementPropertyMask ## SOMETIMES_CONSUMES [FeaturePcd] gEfiMdePkgTokenSpaceGuid.PcdVerifyNodeInList ## CONSUMES diff --git a/MdePkg/Library/BaseLib/Ia32/LongJump.c b/MdePkg/Library/BaseLib/Ia32/LongJump.c index 73973a9cce..2c1feb8373 100644 --- a/MdePkg/Library/BaseLib/Ia32/LongJump.c +++ b/MdePkg/Library/BaseLib/Ia32/LongJump.c @@ -1,7 +1,7 @@ /** @file Implementation of _LongJump() on IA-32. - Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -36,6 +36,32 @@ InternalLongJump ( ) { _asm { + mov eax, [PcdGet32 (PcdControlFlowEnforcementPropertyMask)] + test eax, eax + jz CetDone + _emit 0x0F + _emit 0x20 + _emit 0xE0 ; mov eax, cr4 + bt eax, 23 ; check if CET is enabled + jnc CetDone + + mov edx, [esp + 4] ; edx = JumpBuffer + mov edx, [edx + 24] ; edx = target SSP + _emit 0xF3 + _emit 0x0F + _emit 0x1E + _emit 0xC8 ; READSSP EAX + sub edx, eax ; edx = delta + mov eax, edx ; eax = delta + + shr eax, 2 ; eax = delta/sizeof(UINT32) + _emit 0xF3 + _emit 0x0F + _emit 0xAE + _emit 0xE8 ; INCSSP EAX + +CetDone: + pop eax ; skip return address pop edx ; edx <- JumpBuffer pop eax ; eax <- Value diff --git a/MdePkg/Library/BaseLib/Ia32/LongJump.nasm b/MdePkg/Library/BaseLib/Ia32/LongJump.nasm index 7ef03462ee..57305d4981 100644 --- a/MdePkg/Library/BaseLib/Ia32/LongJump.nasm +++ b/MdePkg/Library/BaseLib/Ia32/LongJump.nasm @@ -1,6 +1,6 @@ ;------------------------------------------------------------------------------ ; -; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
; This program and the accompanying materials ; are licensed and made available under the terms and conditions of the BSD License ; which accompanies this distribution. The full text of the license may be found at @@ -19,8 +19,12 @@ ; ;------------------------------------------------------------------------------ +%include "Nasm.inc" + SECTION .text +extern ASM_PFX(PcdGet32 (PcdControlFlowEnforcementPropertyMask)) + ;------------------------------------------------------------------------------ ; VOID ; EFIAPI @@ -31,6 +35,25 @@ ;------------------------------------------------------------------------------ global ASM_PFX(InternalLongJump) ASM_PFX(InternalLongJump): + + mov eax, [ASM_PFX(PcdGet32 (PcdControlFlowEnforcementPropertyMask))] + test eax, eax + jz CetDone + mov eax, cr4 + bt eax, 23 ; check if CET is enabled + jnc CetDone + + mov edx, [esp + 4] ; edx = JumpBuffer + mov edx, [edx + 24] ; edx = target SSP + READSSP_EAX + sub edx, eax ; edx = delta + mov eax, edx ; eax = delta + + shr eax, 2 ; eax = delta/sizeof(UINT32) + INCSSP_EAX + +CetDone: + pop eax ; skip return address pop edx ; edx <- JumpBuffer pop eax ; eax <- Value diff --git a/MdePkg/Library/BaseLib/Ia32/SetJump.c b/MdePkg/Library/BaseLib/Ia32/SetJump.c index 652d45d53b..d608fd9ccb 100644 --- a/MdePkg/Library/BaseLib/Ia32/SetJump.c +++ b/MdePkg/Library/BaseLib/Ia32/SetJump.c @@ -1,7 +1,7 @@ /** @file Implementation of SetJump() on IA-32. - Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -62,6 +62,32 @@ SetJump ( pop ecx pop ecx mov edx, [esp] + + xor eax, eax + mov [edx + 24], eax ; save 0 to SSP + + mov eax, [PcdGet32 (PcdControlFlowEnforcementPropertyMask)] + test eax, eax + jz CetDone + _emit 0x0F + _emit 0x20 + _emit 0xE0 ; mov eax, cr4 + bt eax, 23 ; check if CET is enabled + jnc CetDone + + mov eax, 1 + _emit 0xF3 + _emit 0x0F + _emit 0xAE + _emit 0xE8 ; INCSSP EAX to read original SSP + _emit 0xF3 + _emit 0x0F + _emit 0x1E + _emit 0xC8 ; READSSP EAX + mov [edx + 0x24], eax ; save SSP + +CetDone: + mov [edx], ebx mov [edx + 4], esi mov [edx + 8], edi diff --git a/MdePkg/Library/BaseLib/Ia32/SetJump.nasm b/MdePkg/Library/BaseLib/Ia32/SetJump.nasm index 6d3a5a25bb..840fed61c7 100644 --- a/MdePkg/Library/BaseLib/Ia32/SetJump.nasm +++ b/MdePkg/Library/BaseLib/Ia32/SetJump.nasm @@ -1,6 +1,6 @@ ;------------------------------------------------------------------------------ ; -; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
; This program and the accompanying materials ; are licensed and made available under the terms and conditions of the BSD License ; which accompanies this distribution. The full text of the license may be found at @@ -19,9 +19,12 @@ ; ;------------------------------------------------------------------------------ +%include "Nasm.inc" + SECTION .text extern ASM_PFX(InternalAssertJumpBuffer) +extern ASM_PFX(PcdGet32 (PcdControlFlowEnforcementPropertyMask)) ;------------------------------------------------------------------------------ ; UINTN @@ -37,6 +40,24 @@ ASM_PFX(SetJump): pop ecx pop ecx ; ecx <- return address mov edx, [esp] + + xor eax, eax + mov [edx + 24], eax ; save 0 to SSP + + mov eax, [ASM_PFX(PcdGet32 (PcdControlFlowEnforcementPropertyMask))] + test eax, eax + jz CetDone + mov eax, cr4 + bt eax, 23 ; check if CET is enabled + jnc CetDone + + mov eax, 1 + INCSSP_EAX ; to read original SSP + READSSP_EAX + mov [edx + 0x24], eax ; save SSP + +CetDone: + mov [edx], ebx mov [edx + 4], esi mov [edx + 8], edi diff --git a/MdePkg/Library/BaseLib/X64/LongJump.nasm b/MdePkg/Library/BaseLib/X64/LongJump.nasm index 3bac27469e..2b38ef0b25 100644 --- a/MdePkg/Library/BaseLib/X64/LongJump.nasm +++ b/MdePkg/Library/BaseLib/X64/LongJump.nasm @@ -1,6 +1,6 @@ ;------------------------------------------------------------------------------ ; -; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
; This program and the accompanying materials ; are licensed and made available under the terms and conditions of the BSD License ; which accompanies this distribution. The full text of the license may be found at @@ -19,9 +19,13 @@ ; ;------------------------------------------------------------------------------ +%include "Nasm.inc" + DEFAULT REL SECTION .text +extern ASM_PFX(PcdGet32 (PcdControlFlowEnforcementPropertyMask)) + ;------------------------------------------------------------------------------ ; VOID ; EFIAPI @@ -32,6 +36,27 @@ ;------------------------------------------------------------------------------ global ASM_PFX(InternalLongJump) ASM_PFX(InternalLongJump): + + mov eax, [ASM_PFX(PcdGet32 (PcdControlFlowEnforcementPropertyMask))] + test eax, eax + jz CetDone + mov rax, cr4 + bt eax, 23 ; check if CET is enabled + jnc CetDone + + push rdx ; save rdx + + mov rdx, [rcx + 0xF8] ; rdx = target SSP + READSSP_RAX + sub rdx, rax ; rdx = delta + mov rax, rdx ; rax = delta + + shr rax, 3 ; rax = delta/sizeof(UINT64) + INCSSP_RAX + + pop rdx ; restore rdx +CetDone: + mov rbx, [rcx] mov rsp, [rcx + 8] mov rbp, [rcx + 0x10] diff --git a/MdePkg/Library/BaseLib/X64/SetJump.nasm b/MdePkg/Library/BaseLib/X64/SetJump.nasm index b1d0ff7121..b491df896d 100644 --- a/MdePkg/Library/BaseLib/X64/SetJump.nasm +++ b/MdePkg/Library/BaseLib/X64/SetJump.nasm @@ -1,6 +1,6 @@ ;------------------------------------------------------------------------------ ; -; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
; This program and the accompanying materials ; are licensed and made available under the terms and conditions of the BSD License ; which accompanies this distribution. The full text of the license may be found at @@ -19,10 +19,13 @@ ; ;------------------------------------------------------------------------------ +%include "Nasm.inc" + DEFAULT REL SECTION .text extern ASM_PFX(InternalAssertJumpBuffer) +extern ASM_PFX(PcdGet32 (PcdControlFlowEnforcementPropertyMask)) ;------------------------------------------------------------------------------ ; UINTN @@ -39,6 +42,24 @@ ASM_PFX(SetJump): add rsp, 0x20 pop rcx pop rdx + + xor rax, rax + mov [rcx + 0xF8], rax ; save 0 to SSP + + mov eax, [ASM_PFX(PcdGet32 (PcdControlFlowEnforcementPropertyMask))] + test eax, eax + jz CetDone + mov rax, cr4 + bt eax, 23 ; check if CET is enabled + jnc CetDone + + mov rax, 1 + INCSSP_RAX ; to read original SSP + READSSP_RAX + mov [rcx + 0xF8], rax ; save SSP + +CetDone: + mov [rcx], rbx mov [rcx + 8], rsp mov [rcx + 0x10], rbp diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec index c859b4a511..69a9575a04 100644 --- a/MdePkg/MdePkg.dec +++ b/MdePkg/MdePkg.dec @@ -2087,6 +2087,13 @@ # @Prompt Fixed Debug Message Print Level. gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel|0xFFFFFFFF|UINT32|0x30001016 + ## Indicates the control flow enforcement enabling state. + # If enabled, it uses control flow enforcement technology to prevent ROP or JOP.

+ # BIT0 - SMM CET Shadow Stack is enabled.
+ # Other - reserved + # @Prompt Enable control flow enforcement. + gEfiMdePkgTokenSpaceGuid.PcdControlFlowEnforcementPropertyMask|0x0|UINT32|0x30001017 + [PcdsFixedAtBuild,PcdsPatchableInModule] ## Indicates the maximum length of unicode string used in the following # BaseLib functions: StrLen(), StrSize(), StrCmp(), StrnCmp(), StrCpy(), StrnCpy()

-- 2.39.2