public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH V3 0/4] Add SMM CET support
@ 2019-02-22 13:30 Jiewen Yao
  2019-02-22 13:30 ` [PATCH V3 1/4] MdePkg/Include: Add Nasm.inc Jiewen Yao
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Jiewen Yao @ 2019-02-22 13:30 UTC (permalink / raw)
  To: edk2-devel
  Cc: Michael D Kinney, Liming Gao, Eric Dong, Ray Ni, Laszlo Ersek,
	Yao Jiewen

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1521

V3:
Add Nasm.inc to include CET related instruction as MACRO.
This is the only place to use DB.
Any other NASM just use the MACRO - 
SETSSBSY, READSSP_[E|R]AX, INCSSP_[E|R]AX
=====================

V2:
Fix emulation platform issue.
The NT32 platform cannot access CR4 register.
So we add a global PCD to choose disable CR4 access in SetJump/LongJump.
gEfiMdePkgTokenSpaceGuid.PcdControlFlowEnforcementPropertyMask
=====================

This patch series implement add CET ShadowStack support for SMM.

The CET document can be found at:
https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-enforcement-technology-preview.pdf

Patch 1 adds SSP (ShadowStackPointer) to JUMP_BUFFER.
Patch 2 adds Control Protection exception (CP#) dump info.
Patch 3 adds CET ShadowStack support in SMM.

For more detail please refer to each patch. 

I also post all update to https://github.com/jyao1/edk2/tree/CET_V2

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yao Jiewen <jiewen.yao@intel.com>

Jiewen Yao (4):
  MdePkg/Include: Add Nasm.inc
  MdePkg/BaseLib: Add Shadow Stack Support for X86.
  UefiCpuPkg/ExceptionLib: Add CET support.
  UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.

 MdePkg/Include/Ia32/Nasm.inc                  |  28 ++++
 MdePkg/Include/Library/BaseLib.h              |   2 +
 MdePkg/Include/X64/Nasm.inc                   |  28 ++++
 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 +
 .../Include/Library/SmmCpuFeaturesLib.h       |  23 +++-
 .../CpuExceptionCommon.c                      |   7 +-
 .../CpuExceptionCommon.h                      |   3 +-
 .../Ia32/ArchExceptionHandler.c               |   5 +-
 .../X64/ArchExceptionHandler.c                |   5 +-
 UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/Cet.nasm       |  39 ++++++
 UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c      |  38 +++++-
 UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.nasm  |  99 ++++++++++++++-
 .../PiSmmCpuDxeSmm/Ia32/SmiException.nasm     |   6 +-
 UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c |  57 ++++++++-
 UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c         |  12 +-
 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c    |  97 ++++++++++++--
 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h    | 103 ++++++++++++++-
 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf  |   6 +-
 .../PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c   |  85 ++++++++++++-
 UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c        |  18 ++-
 UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.h        |   4 +-
 UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c    |   4 +-
 UefiCpuPkg/PiSmmCpuDxeSmm/X64/Cet.nasm        |  40 ++++++
 UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c       |  39 +++++-
 UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm   | 120 +++++++++++++++++-
 UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c  |  58 ++++++++-
 UefiCpuPkg/UefiCpuPkg.dec                     |   6 +-
 34 files changed, 1034 insertions(+), 62 deletions(-)
 create mode 100644 MdePkg/Include/Ia32/Nasm.inc
 create mode 100644 MdePkg/Include/X64/Nasm.inc
 create mode 100644 UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/Cet.nasm
 create mode 100644 UefiCpuPkg/PiSmmCpuDxeSmm/X64/Cet.nasm

-- 
2.19.2.windows.1



^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH V3 1/4] MdePkg/Include: Add Nasm.inc
  2019-02-22 13:30 [PATCH V3 0/4] Add SMM CET support Jiewen Yao
@ 2019-02-22 13:30 ` Jiewen Yao
  2019-02-22 13:30 ` [PATCH V3 2/4] MdePkg/BaseLib: Add Shadow Stack Support for X86 Jiewen Yao
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Jiewen Yao @ 2019-02-22 13:30 UTC (permalink / raw)
  To: edk2-devel
  Cc: Michael D Kinney, Liming Gao, Eric Dong, Ray Ni, Laszlo Ersek,
	Yao Jiewen

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1521

This is to add CET related instruction in Nasm
because CET instruction is not supported yet.

See https://www.nasm.us/xdoc/2.14.02/html/nasmdocb.html

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yao Jiewen <jiewen.yao@intel.com>
---
 MdePkg/Include/Ia32/Nasm.inc | 28 ++++++++++++++++++++
 MdePkg/Include/X64/Nasm.inc  | 28 ++++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/MdePkg/Include/Ia32/Nasm.inc b/MdePkg/Include/Ia32/Nasm.inc
new file mode 100644
index 0000000000..c018bb3cae
--- /dev/null
+++ b/MdePkg/Include/Ia32/Nasm.inc
@@ -0,0 +1,28 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+; 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
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+; Abstract:
+;
+;   This file provides macro definitions for NASM files.
+;
+;------------------------------------------------------------------------------
+
+%macro SETSSBSY        0
+    DB 0xF3, 0x0F, 0x01, 0xE8
+%endmacro
+
+%macro READSSP_EAX     0
+    DB 0xF3, 0x0F, 0x1E, 0xC8
+%endmacro
+
+%macro INCSSP_EAX      0
+    DB 0xF3, 0x0F, 0xAE, 0xE8
+%endmacro
diff --git a/MdePkg/Include/X64/Nasm.inc b/MdePkg/Include/X64/Nasm.inc
new file mode 100644
index 0000000000..129a330212
--- /dev/null
+++ b/MdePkg/Include/X64/Nasm.inc
@@ -0,0 +1,28 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+; 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
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+; Abstract:
+;
+;   This file provides macro definitions for NASM files.
+;
+;------------------------------------------------------------------------------
+
+%macro SETSSBSY        0
+    DB 0xF3, 0x0F, 0x01, 0xE8
+%endmacro
+
+%macro READSSP_RAX     0
+    DB 0xF3, 0x48, 0x0F, 0x1E, 0xC8
+%endmacro
+
+%macro INCSSP_RAX      0
+    DB 0xF3, 0x48, 0x0F, 0xAE, 0xE8
+%endmacro
-- 
2.19.2.windows.1



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH V3 2/4] MdePkg/BaseLib: Add Shadow Stack Support for X86.
  2019-02-22 13:30 [PATCH V3 0/4] Add SMM CET support Jiewen Yao
  2019-02-22 13:30 ` [PATCH V3 1/4] MdePkg/Include: Add Nasm.inc Jiewen Yao
@ 2019-02-22 13:30 ` Jiewen Yao
  2019-02-22 13:30 ` [PATCH V3 3/4] UefiCpuPkg/ExceptionLib: Add CET support Jiewen Yao
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Jiewen Yao @ 2019-02-22 13:30 UTC (permalink / raw)
  To: edk2-devel
  Cc: Michael D Kinney, Liming Gao, Eric Dong, Ray Ni, Laszlo Ersek,
	Yao Jiewen

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 <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yao Jiewen <jiewen.yao@intel.com>
---
 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.<BR>
+#  Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
 #  Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
 #  Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
 #
@@ -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.<BR>
+  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
   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.<BR>
+; Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
 ; 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.<BR>
+  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
   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.<BR>
+; Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
 ; 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.<BR>
+; Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
 ; 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.<BR>
+; Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
 ; 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.<BR><BR>
+  #   BIT0 - SMM CET Shadow Stack is enabled.<BR>
+  #   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()<BR><BR>
-- 
2.19.2.windows.1



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH V3 3/4] UefiCpuPkg/ExceptionLib: Add CET support.
  2019-02-22 13:30 [PATCH V3 0/4] Add SMM CET support Jiewen Yao
  2019-02-22 13:30 ` [PATCH V3 1/4] MdePkg/Include: Add Nasm.inc Jiewen Yao
  2019-02-22 13:30 ` [PATCH V3 2/4] MdePkg/BaseLib: Add Shadow Stack Support for X86 Jiewen Yao
@ 2019-02-22 13:30 ` Jiewen Yao
  2019-02-22 13:30 ` [PATCH V3 4/4] UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM Jiewen Yao
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Jiewen Yao @ 2019-02-22 13:30 UTC (permalink / raw)
  To: edk2-devel; +Cc: Eric Dong, Ray Ni, Laszlo Ersek, Yao Jiewen

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1521

Add information dump for Control Protection exception.

Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yao Jiewen <jiewen.yao@intel.com>
---
 UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c        | 7 ++++---
 UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h        | 3 ++-
 UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c | 5 +++--
 UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c  | 5 +++--
 4 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c
index 0576144a97..ca210d1de2 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c
@@ -1,7 +1,7 @@
 /** @file
   CPU Exception Handler Library common functions.
 
-  Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2012 - 2019, Intel Corporation. All rights reserved.<BR>
   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
@@ -20,7 +20,7 @@
 //
 // 1 means an error code will be pushed, otherwise 0
 //
-CONST UINT32 mErrorCodeFlag = 0x00027d00;
+CONST UINT32 mErrorCodeFlag = 0x00227d00;
 
 //
 // Define the maximum message length
@@ -49,7 +49,8 @@ CONST CHAR8 *mExceptionNameStr[] = {
   "#AC - Alignment Check",
   "#MC - Machine-Check",
   "#XM - SIMD floating-point",
-  "#VE - Virtualization"
+  "#VE - Virtualization",
+  "#CP - Control Protection"
 };
 
 #define EXCEPTION_KNOWN_NAME_NUM  (sizeof (mExceptionNameStr) / sizeof (CHAR8 *))
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
index 83e55ab828..edf46cb60d 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
@@ -1,7 +1,7 @@
 /** @file
   Common header file for CPU Exception Handler Library.
 
-  Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2012 - 2019, Intel Corporation. All rights reserved.<BR>
   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
@@ -39,6 +39,7 @@
 #define IA32_PF_EC_RSVD             BIT3
 #define IA32_PF_EC_ID               BIT4
 #define IA32_PF_EC_PK               BIT5
+#define IA32_PF_EC_SS               BIT6
 #define IA32_PF_EC_SGX              BIT15
 
 #include "ArchInterruptDefs.h"
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c
index 531258610a..f3d993af75 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c
@@ -1,7 +1,7 @@
 /** @file
   IA32 CPU Exception Handler functons.
 
-  Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2012 - 2019, Intel Corporation. All rights reserved.<BR>
   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
@@ -326,13 +326,14 @@ DumpCpuContext (
       );
     if (ExceptionType == EXCEPT_IA32_PAGE_FAULT) {
       InternalPrintMessage (
-        "  I:%x R:%x U:%x W:%x P:%x PK:%x S:%x",
+        "  I:%x R:%x U:%x W:%x P:%x PK:%x SS:%x SGX:%x",
         (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_ID)   != 0,
         (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_RSVD) != 0,
         (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_US)   != 0,
         (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_WR)   != 0,
         (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_P)    != 0,
         (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_PK)   != 0,
+        (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_SS)   != 0,
         (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_SGX)  != 0
         );
     }
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
index d7e883d19a..0183239e59 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
@@ -1,7 +1,7 @@
 /** @file
   x64 CPU Exception Handler.
 
-  Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2012 - 2019, Intel Corporation. All rights reserved.<BR>
   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
@@ -299,13 +299,14 @@ DumpCpuContext (
       );
     if (ExceptionType == EXCEPT_IA32_PAGE_FAULT) {
       InternalPrintMessage (
-        "  I:%x R:%x U:%x W:%x P:%x PK:%x S:%x",
+        "  I:%x R:%x U:%x W:%x P:%x PK:%x SS:%x SGX:%x",
         (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_ID)   != 0,
         (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_RSVD) != 0,
         (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_US)   != 0,
         (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_WR)   != 0,
         (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_P)    != 0,
         (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_PK)   != 0,
+        (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_SS)   != 0,
         (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_SGX)  != 0
         );
     }
-- 
2.19.2.windows.1



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH V3 4/4] UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.
  2019-02-22 13:30 [PATCH V3 0/4] Add SMM CET support Jiewen Yao
                   ` (2 preceding siblings ...)
  2019-02-22 13:30 ` [PATCH V3 3/4] UefiCpuPkg/ExceptionLib: Add CET support Jiewen Yao
@ 2019-02-22 13:30 ` Jiewen Yao
  2019-02-22 14:29 ` [PATCH V3 0/4] Add SMM CET support Ni, Ray
  2019-02-22 21:41 ` Laszlo Ersek
  5 siblings, 0 replies; 8+ messages in thread
From: Jiewen Yao @ 2019-02-22 13:30 UTC (permalink / raw)
  To: edk2-devel; +Cc: Eric Dong, Ray Ni, Laszlo Ersek, Yao Jiewen

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1521

We scan the SMM code with ROPgadget.
http://shell-storm.org/project/ROPgadget/
https://github.com/JonathanSalwan/ROPgadget/tree/master
This tool reports the gadget in SMM driver.

This patch enabled CET ShadowStack for X86 SMM.
If CET is supported, SMM will enable CET ShadowStack.
SMM CET will save the OS CET context at SmmEntry and
restore OS CET context at SmmExit.

Test:
1) test Intel internal platform (x64 only, CET enabled/disabled)
Boot test:
CET supported or not supported CPU
on CET supported platform
  CET enabled/disabled
  PcdCpuSmmCetEnable enabled/disabled
  Single core/Multiple core
  PcdCpuSmmStackGuard enabled/disabled
  PcdCpuSmmProfileEnable enabled/disabled
  PcdCpuSmmStaticPageTable enabled/disabled
CET exception test:
  #CF generated with PcdCpuSmmStackGuard enabled/disabled.
Other exception test:
  #PF for normal stack overflow
  #PF for NX protection
  #PF for RO protection
CET env test:
  Launch SMM in CET enabled/disabled environment (DXE) - no impact to DXE

The test case can be found at
https://github.com/jyao1/SecurityEx/tree/master/ControlFlowPkg

2) test ovmf (both IA32 and X64 SMM, CET disabled only)
test OvmfIa32/Ovmf3264, with -D SMM_REQUIRE.
  qemu-system-x86_64.exe -machine q35,smm=on -smp 4
    -serial file:serial.log
    -drive if=pflash,format=raw,unit=0,file=OVMF_CODE.fd,readonly=on
    -drive if=pflash,format=raw,unit=1,file=OVMF_VARS.fd
QEMU emulator version 3.1.0 (v3.1.0-11736-g7a30e7adb0-dirty)

3) not tested
IA32 CET enabled platform

Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yao Jiewen <jiewen.yao@intel.com>
---
 UefiCpuPkg/Include/Library/SmmCpuFeaturesLib.h     |  23 +++-
 UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/Cet.nasm            |  39 +++++++
 UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c           |  38 ++++++-
 UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.nasm       |  99 +++++++++++++++-
 UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiException.nasm   |   6 +-
 UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c      |  57 +++++++++-
 UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c              |  12 +-
 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c         |  97 ++++++++++++++--
 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h         | 103 ++++++++++++++++-
 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf       |   6 +-
 UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c |  85 +++++++++++++-
 UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c             |  18 ++-
 UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.h             |   4 +-
 UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c         |   4 +-
 UefiCpuPkg/PiSmmCpuDxeSmm/X64/Cet.nasm             |  40 +++++++
 UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c            |  39 ++++++-
 UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm        | 120 +++++++++++++++++++-
 UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c       |  58 +++++++++-
 UefiCpuPkg/UefiCpuPkg.dec                          |   6 +-
 19 files changed, 807 insertions(+), 47 deletions(-)

diff --git a/UefiCpuPkg/Include/Library/SmmCpuFeaturesLib.h b/UefiCpuPkg/Include/Library/SmmCpuFeaturesLib.h
index 4478003467..aec24b5dda 100644
--- a/UefiCpuPkg/Include/Library/SmmCpuFeaturesLib.h
+++ b/UefiCpuPkg/Include/Library/SmmCpuFeaturesLib.h
@@ -1,7 +1,7 @@
 /** @file
 Library that provides CPU specific functions to support the PiSmmCpuDxeSmm module.
 
-Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
 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
@@ -160,14 +160,33 @@ SmmCpuFeaturesGetSmiHandlerSize (
   than zero and is called by the CPU that was elected as monarch during System
   Management Mode initialization.
 
+    //
+    // Append Shadow Stack after normal stack
+    //
+    // |= SmiStack
+    // +--------------------------------------------------+---------------------------------------------------------------+
+    // | Known Good Stack | Guard Page |    SMM Stack     | Known Good Shadow Stack | Guard Page |    SMM Shadow Stack    |
+    // +--------------------------------------------------+---------------------------------------------------------------+
+    // |                               |PcdCpuSmmStackSize|                                      |PcdCpuSmmShadowStackSize|
+    // |<-------------------- StackSize ----------------->|<------------------------- ShadowStackSize ------------------->|
+    // |                                                                                                                  |
+    // |<-------------------------------------------- Processor N ------------------------------------------------------->|
+    // | low address (bottom)                                                                          high address (top) |
+    //
+
   @param[in] CpuIndex   The index of the CPU to install the custom SMI handler.
                         The value must be between 0 and the NumberOfCpus field
                         in the System Management System Table (SMST).
   @param[in] SmBase     The SMBASE address for the CPU specified by CpuIndex.
-  @param[in] SmiStack   The stack to use when an SMI is processed by the
+  @param[in] SmiStack   The bottom of stack to use when an SMI is processed by the
                         the CPU specified by CpuIndex.
   @param[in] StackSize  The size, in bytes, if the stack used when an SMI is
                         processed by the CPU specified by CpuIndex.
+                        StackSize should be PcdCpuSmmStackSize, with 2 more pages
+                        if PcdCpuSmmStackGuard is true.
+                        If ShadowStack is enabled, the shadow stack is allocated
+                        after the normal Stack. The size is PcdCpuSmmShadowStackSize.
+                        with 2 more pages if PcdCpuSmmStackGuard is true.
   @param[in] GdtBase    The base address of the GDT to use when an SMI is
                         processed by the CPU specified by CpuIndex.
   @param[in] GdtSize    The size, in bytes, of the GDT used when an SMI is
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/Cet.nasm b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/Cet.nasm
new file mode 100644
index 0000000000..aa6b5e33ca
--- /dev/null
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/Cet.nasm
@@ -0,0 +1,39 @@
+;------------------------------------------------------------------------------ ;
+; Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+; 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
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+;-------------------------------------------------------------------------------
+
+%include "Nasm.inc"
+
+SECTION .text
+
+global ASM_PFX(DisableCet)
+ASM_PFX(DisableCet):
+
+    ; Skip the pushed data for call
+    mov     eax, 1
+    INCSSP_EAX
+
+    mov     eax, cr4
+    btr     eax, 23                      ; clear CET
+    mov     cr4, eax
+    ret
+
+global ASM_PFX(EnableCet)
+ASM_PFX(EnableCet):
+
+    mov     eax, cr4
+    bts     eax, 23                      ; set CET
+    mov     cr4, eax
+
+    ; use jmp to skip the check for ret
+    pop     eax
+    jmp     eax
+
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
index a32b736089..b734a1ea8c 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
@@ -1,7 +1,7 @@
 /** @file
 Page table manipulation functions for IA-32 processors
 
-Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
 Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
 
 This program and the accompanying materials
@@ -16,6 +16,24 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 
 #include "PiSmmCpuDxeSmm.h"
 
+/**
+  Disable CET.
+**/
+VOID
+EFIAPI
+DisableCet (
+  VOID
+  );
+
+/**
+  Enable CET.
+**/
+VOID
+EFIAPI
+EnableCet (
+  VOID
+  );
+
 /**
   Create PageTable for SMM use.
 
@@ -138,6 +156,7 @@ SmiPFHandler (
       }
     }
     CpuDeadLoop ();
+    goto Exit;
   }
 
   //
@@ -152,6 +171,7 @@ SmiPFHandler (
         DumpModuleInfoByIp (*(UINTN *)(UINTN)SystemContext.SystemContextIa32->Esp);
       );
       CpuDeadLoop ();
+      goto Exit;
     }
 
     //
@@ -171,6 +191,7 @@ SmiPFHandler (
       }
 
       CpuDeadLoop ();
+      goto Exit;
     }
 
     if (IsSmmCommBufferForbiddenAddress (PFAddress)) {
@@ -180,6 +201,7 @@ SmiPFHandler (
         DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextIa32->Eip);
       );
       CpuDeadLoop ();
+      goto Exit;
     }
   }
 
@@ -212,6 +234,7 @@ SetPageTableAttributes (
   UINT64                *L3PageTable;
   BOOLEAN               IsSplitted;
   BOOLEAN               PageTableSplitted;
+  BOOLEAN               CetEnabled;
 
   //
   // Don't mark page table to read-only if heap guard is enabled.
@@ -238,6 +261,13 @@ SetPageTableAttributes (
   // Disable write protection, because we need mark page table to be write protected.
   // We need *write* page table memory, to mark itself to be *read only*.
   //
+  CetEnabled = ((AsmReadCr4() & CR4_CET_ENABLE) != 0) ? TRUE : FALSE;
+  if (CetEnabled) {
+    //
+    // CET must be disabled if WP is disabled.
+    //
+    DisableCet();
+  }
   AsmWriteCr0 (AsmReadCr0() & ~CR0_WP);
 
   do {
@@ -277,6 +307,12 @@ SetPageTableAttributes (
   // Enable write protection, after page table updated.
   //
   AsmWriteCr0 (AsmReadCr0() | CR0_WP);
+  if (CetEnabled) {
+    //
+    // re-enable CET.
+    //
+    EnableCet();
+  }
 
   return ;
 }
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.nasm b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.nasm
index 3791cfa144..101215b389 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.nasm
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.nasm
@@ -1,5 +1,5 @@
 ;------------------------------------------------------------------------------ ;
-; Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
 ; 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,6 +19,20 @@
 ;-------------------------------------------------------------------------------
 
 %include "StuffRsbNasm.inc"
+%include "Nasm.inc"
+
+%define MSR_IA32_S_CET                     0x6A2
+%define   MSR_IA32_CET_SH_STK_EN             0x1
+%define   MSR_IA32_CET_WR_SHSTK_EN           0x2
+%define   MSR_IA32_CET_ENDBR_EN              0x4
+%define   MSR_IA32_CET_LEG_IW_EN             0x8
+%define   MSR_IA32_CET_NO_TRACK_EN           0x10
+%define   MSR_IA32_CET_SUPPRESS_DIS          0x20
+%define   MSR_IA32_CET_SUPPRESS              0x400
+%define   MSR_IA32_CET_TRACKER               0x800
+%define MSR_IA32_PL0_SSP                   0x6A4
+
+%define CR4_CET                            0x800000
 
 %define MSR_IA32_MISC_ENABLE 0x1A0
 %define MSR_EFER      0xc0000080
@@ -53,6 +67,11 @@ extern ASM_PFX(mXdSupported)
 global ASM_PFX(gPatchXdSupported)
 extern ASM_PFX(gSmiHandlerIdtr)
 
+extern ASM_PFX(mCetSupported)
+global ASM_PFX(mPatchCetSupported)
+global ASM_PFX(mPatchCetPl0Ssp)
+global ASM_PFX(mPatchCetInterruptSsp)
+
     SECTION .text
 
 BITS 16
@@ -173,11 +192,61 @@ ASM_PFX(gPatchXdSupported):
     mov     ax, [ebx + DSC_SS]
     mov     ss, eax
 
-;   jmp     _SmiHandler                 ; instruction is not needed
+    mov     ebx, [esp + 4]                  ; ebx <- CpuIndex
+
+; enable CET if supported
+    mov     al, strict byte 1           ; source operand may be patched
+ASM_PFX(mPatchCetSupported):
+    cmp     al, 0
+    jz      CetDone
+
+    mov     ecx, MSR_IA32_S_CET
+    rdmsr
+    push    edx
+    push    eax
+
+    mov     ecx, MSR_IA32_PL0_SSP
+    rdmsr
+    push    edx
+    push    eax
+
+    mov     ecx, MSR_IA32_S_CET
+    mov     eax, MSR_IA32_CET_SH_STK_EN
+    xor     edx, edx
+    wrmsr
+
+    mov     ecx, MSR_IA32_PL0_SSP
+    mov     eax, strict dword 0         ; source operand will be patched
+ASM_PFX(mPatchCetPl0Ssp):
+    xor     edx, edx
+    wrmsr
+    mov     ecx, cr0
+    btr     ecx, 16                     ; clear WP
+    mov     cr0, ecx
+    mov     [eax], eax                  ; reload SSP, and clear busyflag.
+    xor     ecx, ecx
+    mov     [eax + 4], ecx
+
+    mov     eax, strict dword 0         ; source operand will be patched
+ASM_PFX(mPatchCetInterruptSsp):
+    cmp     eax, 0
+    jz      CetInterruptDone
+    mov     [eax], eax                  ; reload SSP, and clear busyflag.
+    xor     ecx, ecx
+    mov     [eax + 4], ecx
+CetInterruptDone:
+
+    mov     ecx, cr0
+    bts     ecx, 16                     ; set WP
+    mov     cr0, ecx
+
+    mov     eax, 0x668 | CR4_CET
+    mov     cr4, eax
+
+    SETSSBSY
+
+CetDone:
 
-global ASM_PFX(SmiHandler)
-ASM_PFX(SmiHandler):
-    mov     ebx, [esp + 4]                  ; CPU Index
     push    ebx
     mov     eax, ASM_PFX(CpuSmmDebugEntry)
     call    eax
@@ -193,6 +262,25 @@ ASM_PFX(SmiHandler):
     call    eax
     add     esp, 4
 
+    mov     eax, ASM_PFX(mCetSupported)
+    mov     al, [eax]
+    cmp     al, 0
+    jz      CetDone2
+
+    mov     eax, 0x668
+    mov     cr4, eax       ; disable CET
+
+    mov     ecx, MSR_IA32_PL0_SSP
+    pop     eax
+    pop     edx
+    wrmsr
+
+    mov     ecx, MSR_IA32_S_CET
+    pop     eax
+    pop     edx
+    wrmsr
+CetDone2:
+
     mov     eax, ASM_PFX(mXdSupported)
     mov     al, [eax]
     cmp     al, 0
@@ -206,6 +294,7 @@ ASM_PFX(SmiHandler):
     wrmsr
 
 .7:
+
     StuffRsb32
     rsm
 
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiException.nasm b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiException.nasm
index 879fa0ba63..97a5fcad32 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiException.nasm
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiException.nasm
@@ -1,5 +1,5 @@
 ;------------------------------------------------------------------------------ ;
-; Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
 ; 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
@@ -89,7 +89,7 @@ TssSeg:
             DB      0x80                ; LimitHigh
             DB      0                   ; BaseHigh
 ExceptionTssSeg:
-            DW      TSS_DESC_SIZE       ; LimitLow
+            DW      EXCEPTION_TSS_DESC_SIZE       ; LimitLow
             DW      0                   ; BaseLow
             DB      0                   ; BaseMid
             DB      0x89
@@ -223,6 +223,8 @@ ExceptionTssDescriptor:
             DW      0                   ; Reserved
             DW      0                   ; T
             DW      0                   ; I/O Map Base
+            DD      0                   ; SSP
+EXCEPTION_TSS_DESC_SIZE equ $ - ExceptionTssDescriptor
 
 ASM_PFX(gcPsd):
             DB      'PSDSIG  '
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c
index 4f1f67fe4a..e44eb5c6d9 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c
@@ -1,7 +1,7 @@
 /** @file
   SMM CPU misc functions for Ia32 arch specific.
 
-Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
 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,6 +19,14 @@ extern UINT64 gTaskGateDescriptor;
 EFI_PHYSICAL_ADDRESS                mGdtBuffer;
 UINTN                               mGdtBufferSize;
 
+extern BOOLEAN mCetSupported;
+extern UINTN mSmmShadowStackSize;
+
+X86_ASSEMBLY_PATCH_LABEL mPatchCetPl0Ssp;
+X86_ASSEMBLY_PATCH_LABEL mPatchCetInterruptSsp;
+UINT32 mCetPl0Ssp;
+UINT32 mCetInterruptSsp;
+
 /**
   Initialize IDT for SMM Stack Guard.
 
@@ -62,6 +70,7 @@ InitGdt (
   UINTN                     GdtTssTableSize;
   UINT8                     *GdtTssTables;
   UINTN                     GdtTableStepSize;
+  UINTN                     InterruptShadowStack;
 
   if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
     //
@@ -75,7 +84,7 @@ InitGdt (
     //
     gcSmiGdtr.Limit += (UINT16)(2 * sizeof (IA32_SEGMENT_DESCRIPTOR));
 
-    GdtTssTableSize = (gcSmiGdtr.Limit + 1 + TSS_SIZE * 2 + 7) & ~7; // 8 bytes aligned
+    GdtTssTableSize = (gcSmiGdtr.Limit + 1 + TSS_SIZE + EXCEPTION_TSS_SIZE + 7) & ~7; // 8 bytes aligned
     mGdtBufferSize = GdtTssTableSize * gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus;
     //
     // IA32 Stack Guard need use task switch to switch stack that need
@@ -88,7 +97,7 @@ InitGdt (
     GdtTableStepSize = GdtTssTableSize;
 
     for (Index = 0; Index < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; Index++) {
-      CopyMem (GdtTssTables + GdtTableStepSize * Index, (VOID*)(UINTN)gcSmiGdtr.Base, gcSmiGdtr.Limit + 1 + TSS_SIZE * 2);
+      CopyMem (GdtTssTables + GdtTableStepSize * Index, (VOID*)(UINTN)gcSmiGdtr.Base, gcSmiGdtr.Limit + 1 + TSS_SIZE + EXCEPTION_TSS_SIZE);
       //
       // Fixup TSS descriptors
       //
@@ -110,6 +119,14 @@ InitGdt (
       //
       *(UINTN *)(TssBase + TSS_IA32_ESP_OFFSET) =  mSmmStackArrayBase + EFI_PAGE_SIZE + Index * mSmmStackSize;
       *(UINT32 *)(TssBase + TSS_IA32_CR3_OFFSET) = Cr3;
+
+      //
+      // Setup ShadowStack for stack switch
+      //
+      if ((PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) && mCetSupported) {
+        InterruptShadowStack = (UINTN)(mSmmStackArrayBase + mSmmStackSize + EFI_PAGES_TO_SIZE (1) - sizeof(UINT64) + (mSmmStackSize + mSmmShadowStackSize) * Index);
+        *(UINT32 *)(TssBase + TSS_IA32_SSP_OFFSET) = (UINT32)InterruptShadowStack;
+      }
     }
   } else {
     //
@@ -157,3 +174,37 @@ TransferApToSafeState (
   //
   ASSERT (FALSE);
 }
+
+/**
+  Initialize the shadow stack related data structure.
+
+  @param CpuIndex     The index of CPU.
+  @param ShadowStack  The bottom of the shadow stack for this CPU.
+**/
+VOID
+InitShadowStack (
+  IN UINTN  CpuIndex,
+  IN VOID   *ShadowStack
+  )
+{
+  UINTN       SmmShadowStackSize;
+
+  if ((PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) && mCetSupported) {
+    SmmShadowStackSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmShadowStackSize)));
+    if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
+      SmmShadowStackSize += EFI_PAGES_TO_SIZE (2);
+    }
+    mCetPl0Ssp = (UINT32)((UINTN)ShadowStack + SmmShadowStackSize - sizeof(UINT64));
+    PatchInstructionX86 (mPatchCetPl0Ssp, mCetPl0Ssp, 4);
+    DEBUG ((DEBUG_INFO, "mCetPl0Ssp - 0x%x\n", mCetPl0Ssp));
+    DEBUG ((DEBUG_INFO, "ShadowStack - 0x%x\n", ShadowStack));
+    DEBUG ((DEBUG_INFO, "  SmmShadowStackSize - 0x%x\n", SmmShadowStackSize));
+
+    if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
+      mCetInterruptSsp = (UINT32)((UINTN)ShadowStack + EFI_PAGES_TO_SIZE(1) - sizeof(UINT64));
+      PatchInstructionX86 (mPatchCetInterruptSsp, mCetInterruptSsp, 4);
+      DEBUG ((DEBUG_INFO, "mCetInterruptSsp - 0x%x\n", mCetInterruptSsp));
+    }
+  }
+}
+
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c b/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
index abcc3eea05..3b0b3b52ac 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
@@ -1,7 +1,7 @@
 /** @file
 SMM MP service implementation
 
-Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
 Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
 
 This program and the accompanying materials
@@ -1369,14 +1369,16 @@ InitializeMpSyncData (
 /**
   Initialize global data for MP synchronization.
 
-  @param Stacks       Base address of SMI stack buffer for all processors.
-  @param StackSize    Stack size for each processor in SMM.
+  @param Stacks             Base address of SMI stack buffer for all processors.
+  @param StackSize          Stack size for each processor in SMM.
+  @param ShadowStackSize    Shadow Stack size for each processor in SMM.
 
 **/
 UINT32
 InitializeMpServiceData (
   IN VOID        *Stacks,
-  IN UINTN       StackSize
+  IN UINTN       StackSize,
+  IN UINTN       ShadowStackSize
   )
 {
   UINT32                    Cr3;
@@ -1428,7 +1430,7 @@ InitializeMpServiceData (
     InstallSmiHandler (
       Index,
       (UINT32)mCpuHotPlugData.SmBase[Index],
-      (VOID*)((UINTN)Stacks + (StackSize * Index)),
+      (VOID*)((UINTN)Stacks + (StackSize + ShadowStackSize) * Index),
       StackSize,
       (UINTN)(GdtTssTables + GdtTableStepSize * Index),
       gcSmiGdtr.Limit + 1,
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
index 8c9fa14b5b..80dbf152b0 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
@@ -1,7 +1,7 @@
 /** @file
 Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.
 
-Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
 Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
 
 This program and the accompanying materials
@@ -94,6 +94,9 @@ UINTN mSmmStackArrayBase;
 UINTN mSmmStackArrayEnd;
 UINTN mSmmStackSize;
 
+UINTN mSmmShadowStackSize;
+BOOLEAN mCetSupported = TRUE;
+
 UINTN mMaxNumberOfCpus = 1;
 UINTN mNumberOfCpus = 1;
 
@@ -420,7 +423,7 @@ SmmRelocateBases (
   PatchInstructionX86 (gPatchSmmCr0, mSmmCr0, 4);
   PatchInstructionX86 (gPatchSmmCr3, AsmReadCr3 (), 4);
   mSmmCr4 = (UINT32)AsmReadCr4 ();
-  PatchInstructionX86 (gPatchSmmCr4, mSmmCr4, 4);
+  PatchInstructionX86 (gPatchSmmCr4, mSmmCr4 & (~CR4_CET_ENABLE), 4);
 
   //
   // Patch GDTR for SMM base relocation
@@ -550,6 +553,8 @@ PiCpuSmmEntry (
   UINT8                      *Stacks;
   VOID                       *Registration;
   UINT32                     RegEax;
+  UINT32                     RegEbx;
+  UINT32                     RegEcx;
   UINT32                     RegEdx;
   UINTN                      FamilyId;
   UINTN                      ModelId;
@@ -726,6 +731,32 @@ PiCpuSmmEntry (
     }
   }
 
+  DEBUG ((DEBUG_INFO, "PcdControlFlowEnforcementPropertyMask = %d\n", PcdGet32 (PcdControlFlowEnforcementPropertyMask)));
+  if (PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) {
+    AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
+    if (RegEax > CPUID_EXTENDED_FUNCTION) {
+      AsmCpuidEx (CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO, NULL, NULL, &RegEcx, &RegEdx);
+      DEBUG ((DEBUG_INFO, "CPUID[7/0] ECX - 0x%08x\n", RegEcx));
+      DEBUG ((DEBUG_INFO, "  CET_SS  - 0x%08x\n", RegEcx & CPUID_CET_SS));
+      DEBUG ((DEBUG_INFO, "  CET_IBT - 0x%08x\n", RegEdx & CPUID_CET_IBT));
+      if ((RegEcx & CPUID_CET_SS) == 0) {
+        mCetSupported = FALSE;
+        PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);
+      }
+      if (mCetSupported) {
+        AsmCpuidEx (CPUID_EXTENDED_STATE, CPUID_EXTENDED_STATE_SUB_LEAF, NULL, &RegEbx, &RegEcx, NULL);
+        DEBUG ((DEBUG_INFO, "CPUID[D/1] EBX - 0x%08x, ECX - 0x%08x\n", RegEbx, RegEcx));
+        AsmCpuidEx (CPUID_EXTENDED_STATE, 11, &RegEax, NULL, &RegEcx, NULL);
+        DEBUG ((DEBUG_INFO, "CPUID[D/11] EAX - 0x%08x, ECX - 0x%08x\n", RegEax, RegEcx));
+        AsmCpuidEx(CPUID_EXTENDED_STATE, 12, &RegEax, NULL, &RegEcx, NULL);
+        DEBUG ((DEBUG_INFO, "CPUID[D/12] EAX - 0x%08x, ECX - 0x%08x\n", RegEax, RegEcx));
+      }
+    }
+  } else {
+    mCetSupported = FALSE;
+    PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);
+  }
+
   //
   // Compute tile size of buffer required to hold the CPU SMRAM Save State Map, extra CPU
   // specific context start starts at SMBASE + SMM_PSD_OFFSET, and the SMI entry point.
@@ -828,6 +859,7 @@ PiCpuSmmEntry (
   //
   // Allocate SMI stacks for all processors.
   //
+  mSmmStackSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmStackSize)));
   if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
     //
     // 2 more pages is allocated for each processor.
@@ -839,15 +871,39 @@ PiCpuSmmEntry (
     // |                                           |     |                                           |
     // |<-------------- Processor 0 -------------->|     |<-------------- Processor n -------------->|
     //
-    mSmmStackSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmStackSize)) + 2);
-    Stacks = (UINT8 *) AllocatePages (gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus * (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmStackSize)) + 2));
-    ASSERT (Stacks != NULL);
-    mSmmStackArrayBase = (UINTN)Stacks;
-    mSmmStackArrayEnd = mSmmStackArrayBase + gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus * mSmmStackSize - 1;
-  } else {
-    mSmmStackSize = PcdGet32 (PcdCpuSmmStackSize);
-    Stacks = (UINT8 *) AllocatePages (EFI_SIZE_TO_PAGES (gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus * mSmmStackSize));
-    ASSERT (Stacks != NULL);
+    mSmmStackSize += EFI_PAGES_TO_SIZE (2);
+  }
+
+  mSmmShadowStackSize = 0;
+  if ((PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) && mCetSupported) {
+    //
+    // Append Shadow Stack after normal stack
+    //
+    // |= Stacks
+    // +--------------------------------------------------+---------------------------------------------------------------+
+    // | Known Good Stack | Guard Page |    SMM Stack     | Known Good Shadow Stack | Guard Page |    SMM Shadow Stack    |
+    // +--------------------------------------------------+---------------------------------------------------------------+
+    // |                               |PcdCpuSmmStackSize|                                      |PcdCpuSmmShadowStackSize|
+    // |<---------------- mSmmStackSize ----------------->|<--------------------- mSmmShadowStackSize ------------------->|
+    // |                                                                                                                  |
+    // |<-------------------------------------------- Processor N ------------------------------------------------------->|
+    //
+    mSmmShadowStackSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmShadowStackSize)));
+    if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
+      mSmmShadowStackSize += EFI_PAGES_TO_SIZE (2);
+    }
+  }
+
+  Stacks = (UINT8 *) AllocatePages (gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus * (EFI_SIZE_TO_PAGES (mSmmStackSize + mSmmShadowStackSize)));
+  ASSERT (Stacks != NULL);
+  mSmmStackArrayBase = (UINTN)Stacks;
+  mSmmStackArrayEnd = mSmmStackArrayBase + gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus * (mSmmStackSize + mSmmShadowStackSize) - 1;
+
+  DEBUG ((DEBUG_INFO, "Stacks                   - 0x%x\n", Stacks));
+  DEBUG ((DEBUG_INFO, "mSmmStackSize            - 0x%x\n", mSmmStackSize));
+  DEBUG ((DEBUG_INFO, "PcdCpuSmmStackGuard      - 0x%x\n", FeaturePcdGet (PcdCpuSmmStackGuard)));
+  if ((PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) && mCetSupported) {
+    DEBUG ((DEBUG_INFO, "mSmmShadowStackSize      - 0x%x\n", mSmmShadowStackSize));
   }
 
   //
@@ -887,7 +943,24 @@ PiCpuSmmEntry (
   //
   // Initialize MP globals
   //
-  Cr3 = InitializeMpServiceData (Stacks, mSmmStackSize);
+  Cr3 = InitializeMpServiceData (Stacks, mSmmStackSize, mSmmShadowStackSize);
+
+  if ((PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) && mCetSupported) {
+    for (Index = 0; Index < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; Index++) {
+      SetShadowStack (
+        Cr3,
+        (EFI_PHYSICAL_ADDRESS)(UINTN)Stacks + mSmmStackSize + (mSmmStackSize + mSmmShadowStackSize) * Index,
+        mSmmShadowStackSize
+        );
+      if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
+        SetNotPresentPage (
+          Cr3,
+          (EFI_PHYSICAL_ADDRESS)(UINTN)Stacks + mSmmStackSize + EFI_PAGES_TO_SIZE(1) + (mSmmStackSize + mSmmShadowStackSize) * Index,
+          EFI_PAGES_TO_SIZE(1)
+          );
+      }
+    }
+  }
 
   //
   // Fill in SMM Reserved Regions
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
index 61d4bd3085..84efb22981 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
@@ -1,7 +1,7 @@
 /** @file
 Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.
 
-Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
 Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
 
 This program and the accompanying materials
@@ -64,6 +64,51 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "CpuService.h"
 #include "SmmProfile.h"
 
+//
+// CET definition
+//
+#define CPUID_CET_SS   BIT7
+#define CPUID_CET_IBT  BIT20
+
+#define CR4_CET_ENABLE  BIT23
+
+#define MSR_IA32_S_CET                     0x6A2
+#define MSR_IA32_PL0_SSP                   0x6A4
+#define MSR_IA32_INTERRUPT_SSP_TABLE_ADDR  0x6A8
+
+typedef union {
+  struct {
+    // enable shadow stacks
+    UINT32  SH_STK_ENP:1;
+    // enable the WRSS{D,Q}W instructions.
+    UINT32  WR_SHSTK_EN:1;
+    // enable tracking of indirect call/jmp targets to be ENDBRANCH instruction.
+    UINT32  ENDBR_EN:1;
+    // enable legacy compatibility treatment for indirect call/jmp tracking.
+    UINT32  LEG_IW_EN:1;
+    // enable use of no-track prefix on indirect call/jmp.
+    UINT32  NO_TRACK_EN:1;
+    // disable suppression of CET indirect branch tracking on legacy compatibility.
+    UINT32  SUPPRESS_DIS:1;
+    UINT32  RSVD:4;
+    // indirect branch tracking is suppressed.
+    // This bit can be written to 1 only if TRACKER is written as IDLE.
+    UINT32  SUPPRESS:1;
+    // Value of the endbranch state machine
+    // Values: IDLE (0), WAIT_FOR_ENDBRANCH(1).
+    UINT32  TRACKER:1;
+    // linear address of a bitmap in memory indicating valid
+    // pages as target of CALL/JMP_indirect that do not land on ENDBRANCH when CET is enabled
+    // and not suppressed. Valid when ENDBR_EN is 1. Must be machine canonical when written on
+    // parts that support 64 bit mode. On parts that do not support 64 bit mode, the bits 63:32 are
+    // reserved and must be 0. This value is extended by 12 bits at the low end to form the base address
+    // (this automatically aligns the address on a 4-Kbyte boundary).
+    UINT32  EB_LEG_BITMAP_BASE_low:12;
+    UINT32  EB_LEG_BITMAP_BASE_high:32;
+  } Bits;
+  UINT64   Uint64;
+} MSR_IA32_CET;
+
 //
 // MSRs required for configuration of SMM Code Access Check
 //
@@ -127,9 +172,11 @@ typedef struct {
 // Size of Task-State Segment defined in IA32 Manual
 //
 #define TSS_SIZE              104
+#define EXCEPTION_TSS_SIZE    (TSS_SIZE + 4) // Add 4 bytes SSP
 #define TSS_X64_IST1_OFFSET   36
 #define TSS_IA32_CR3_OFFSET   28
 #define TSS_IA32_ESP_OFFSET   56
+#define TSS_IA32_SSP_OFFSET   104
 
 #define CR0_WP                BIT16
 
@@ -305,6 +352,8 @@ X86_ASSEMBLY_PATCH_LABEL            gPatchSmmCr3;
 extern UINT32                       mSmmCr4;
 X86_ASSEMBLY_PATCH_LABEL            gPatchSmmCr4;
 X86_ASSEMBLY_PATCH_LABEL            gPatchSmmInitStack;
+X86_ASSEMBLY_PATCH_LABEL            mPatchCetSupported;
+extern BOOLEAN                      mCetSupported;
 
 /**
   Semaphore operation for all processor relocate SMMBase.
@@ -418,14 +467,16 @@ Gen4GPageTable (
 /**
   Initialize global data for MP synchronization.
 
-  @param Stacks       Base address of SMI stack buffer for all processors.
-  @param StackSize    Stack size for each processor in SMM.
+  @param Stacks             Base address of SMI stack buffer for all processors.
+  @param StackSize          Stack size for each processor in SMM.
+  @param ShadowStackSize    Shadow Stack size for each processor in SMM.
 
 **/
 UINT32
 InitializeMpServiceData (
   IN VOID        *Stacks,
-  IN UINTN       StackSize
+  IN UINTN       StackSize,
+  IN UINTN       ShadowStackSize
   );
 
 /**
@@ -1036,6 +1087,50 @@ TransferApToSafeState (
   IN UINTN  NumberToFinishAddress
   );
 
+/**
+  Set ShadowStack memory.
+
+  @param[in]  Cr3              The page table base address.
+  @param[in]  BaseAddress      The physical address that is the start address of a memory region.
+  @param[in]  Length           The size in bytes of the memory region.
+
+  @retval EFI_SUCCESS           The shadow stack memory is set.
+**/
+EFI_STATUS
+SetShadowStack (
+  IN  UINTN                                      Cr3,
+  IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,
+  IN  UINT64                                     Length
+  );
+
+/**
+  Set not present memory.
+
+  @param[in]  Cr3              The page table base address.
+  @param[in]  BaseAddress      The physical address that is the start address of a memory region.
+  @param[in]  Length           The size in bytes of the memory region.
+
+  @retval EFI_SUCCESS           The not present memory is set.
+**/
+EFI_STATUS
+SetNotPresentPage (
+  IN  UINTN                                      Cr3,
+  IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,
+  IN  UINT64                                     Length
+  );
+
+/**
+  Initialize the shadow stack related data structure.
+
+  @param CpuIndex     The index of CPU.
+  @param ShadowStack  The bottom of the shadow stack for this CPU.
+**/
+VOID
+InitShadowStack (
+  IN UINTN  CpuIndex,
+  IN VOID   *ShadowStack
+  );
+
 /**
   This function set given attributes of the memory region specified by
   BaseAddress and Length.
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
index 666f851faf..fe6a41d3bd 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
@@ -4,7 +4,7 @@
 # This SMM driver performs SMM initialization, deploy SMM Entry Vector,
 # provides CPU specific services in SMM.
 #
-# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
 # Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
 #
 # This program and the accompanying materials
@@ -57,6 +57,7 @@
   Ia32/SmiEntry.nasm
   Ia32/SmiException.nasm
   Ia32/MpFuncs.nasm
+  Ia32/Cet.nasm
 
 [Sources.X64]
   X64/Semaphore.c
@@ -68,6 +69,7 @@
   X64/SmiEntry.nasm
   X64/SmiException.nasm
   X64/MpFuncs.nasm
+  X64/Cet.nasm
 
 [Packages]
   MdePkg/MdePkg.dec
@@ -135,10 +137,12 @@
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmCodeAccessCheckEnable         ## CONSUMES
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmSyncMode                      ## CONSUMES
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStaticPageTable               ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmShadowStackSize               ## SOMETIMES_CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable                   ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask    ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask    ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask               ## CONSUMES
+  gEfiMdePkgTokenSpaceGuid.PcdControlFlowEnforcementPropertyMask        ## CONSUMES
 
 [Depex]
   gEfiMpServiceProtocolGuid
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
index 684b14dc28..48f5f954cb 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
@@ -1,6 +1,6 @@
 /** @file
 
-Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
 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
@@ -38,6 +38,23 @@ PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] = {
   {Page1G,  SIZE_1GB, PAGING_1G_ADDRESS_MASK_64},
 };
 
+UINTN  mInternalGr3;
+
+/**
+  Set the internal page table base address.
+  If it is non zero, further MemoryAttribute modification will be on this page table.
+  If it is zero, further MemoryAttribute modification will be on real page table.
+
+  @param Cr3 page table base.
+**/
+VOID
+SetPageTableBase (
+  IN UINTN   Cr3
+  )
+{
+  mInternalGr3 = Cr3;
+}
+
 /**
   Return page table base.
 
@@ -48,6 +65,9 @@ GetPageTableBase (
   VOID
   )
 {
+  if (mInternalGr3 != 0) {
+    return mInternalGr3;
+  }
   return (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64);
 }
 
@@ -220,6 +240,17 @@ ConvertPageEntryAttribute (
   if ((Attributes & EFI_MEMORY_RO) != 0) {
     if (IsSet) {
       NewPageEntry &= ~(UINT64)IA32_PG_RW;
+      if (mInternalGr3 != 0) {
+        // Environment setup
+        // ReadOnly page need set Dirty bit for shadow stack
+        NewPageEntry |= IA32_PG_D;
+        // Clear user bit for supervisor shadow stack
+        NewPageEntry &= ~(UINT64)IA32_PG_U;
+      } else {
+        // Runtime update
+        // Clear dirty bit for non shadow stack, to protect RO page.
+        NewPageEntry &= ~(UINT64)IA32_PG_D;
+      }
     } else {
       NewPageEntry |= IA32_PG_RW;
     }
@@ -661,7 +692,59 @@ SmmClearMemoryAttributes (
   return SmmClearMemoryAttributesEx (BaseAddress, Length, Attributes, NULL);
 }
 
+/**
+  Set ShadowStack memory.
+
+  @param[in]  Cr3              The page table base address.
+  @param[in]  BaseAddress      The physical address that is the start address of a memory region.
+  @param[in]  Length           The size in bytes of the memory region.
+
+  @retval EFI_SUCCESS           The shadow stack memory is set.
+**/
+EFI_STATUS
+SetShadowStack (
+  IN  UINTN                                      Cr3,
+  IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,
+  IN  UINT64                                     Length
+  )
+{
+  EFI_STATUS  Status;
+
+  SetPageTableBase (Cr3);
+
+  Status = SmmSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_RO);
+
+  SetPageTableBase (0);
+
+  return Status;
+}
+
+/**
+  Set not present memory.
+
+  @param[in]  Cr3              The page table base address.
+  @param[in]  BaseAddress      The physical address that is the start address of a memory region.
+  @param[in]  Length           The size in bytes of the memory region.
 
+  @retval EFI_SUCCESS           The not present memory is set.
+**/
+EFI_STATUS
+SetNotPresentPage (
+  IN  UINTN                                      Cr3,
+  IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,
+  IN  UINT64                                     Length
+  )
+{
+  EFI_STATUS  Status;
+
+  SetPageTableBase (Cr3);
+
+  Status = SmmSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_RP);
+
+  SetPageTableBase (0);
+
+  return Status;
+}
 
 /**
   Retrieves a pointer to the system configuration table from the SMM System Table
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
index 91b8e7ddb9..3abc87c977 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
@@ -1,7 +1,7 @@
 /** @file
 Enable SMM profile.
 
-Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2012 - 2019, Intel Corporation. All rights reserved.<BR>
 Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
 
 This program and the accompanying materials
@@ -927,7 +927,7 @@ InitSmmProfileInternal (
 }
 
 /**
-  Check if XD feature is supported by a processor.
+  Check if feature is supported by a processor.
 
 **/
 VOID
@@ -936,9 +936,23 @@ CheckFeatureSupported (
   )
 {
   UINT32                         RegEax;
+  UINT32                         RegEcx;
   UINT32                         RegEdx;
   MSR_IA32_MISC_ENABLE_REGISTER  MiscEnableMsr;
 
+  if ((PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) && mCetSupported) {
+    AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
+    if (RegEax <= CPUID_EXTENDED_FUNCTION) {
+      mCetSupported = FALSE;
+      PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);
+    }
+    AsmCpuidEx (CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO, NULL, NULL, &RegEcx, NULL);
+    if ((RegEcx & CPUID_CET_SS) == 0) {
+      mCetSupported = FALSE;
+      PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);
+    }
+  }
+
   if (mXdSupported) {
     AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
     if (RegEax <= CPUID_EXTENDED_FUNCTION) {
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.h b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.h
index c2a48235ab..a2db0d9eb9 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.h
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.h
@@ -1,7 +1,7 @@
 /** @file
 SMM profile header file.
 
-Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2012 - 2019, Intel Corporation. All rights reserved.<BR>
 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
@@ -88,7 +88,7 @@ PageFaultIdtHandlerSmmProfile (
 
 
 /**
-  Check if XD feature is supported by a processor.
+  Check if feature is supported by a processor.
 
 **/
 VOID
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c
index 5c2eb9ab6a..8f34875e17 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c
@@ -1,7 +1,7 @@
 /** @file
 Provides services to access SMRAM Save State Map
 
-Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
 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
@@ -714,6 +714,8 @@ InstallSmiHandler (
     return;
   }
 
+  InitShadowStack (CpuIndex, (VOID *)((UINTN)SmiStack + StackSize));
+
   //
   // Initialize values in template before copy
   //
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/Cet.nasm b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/Cet.nasm
new file mode 100644
index 0000000000..61336c9096
--- /dev/null
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/Cet.nasm
@@ -0,0 +1,40 @@
+;------------------------------------------------------------------------------ ;
+; Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+; 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
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+;-------------------------------------------------------------------------------
+
+%include "Nasm.inc"
+
+DEFAULT REL
+SECTION .text
+
+global ASM_PFX(DisableCet)
+ASM_PFX(DisableCet):
+
+    ; Skip the pushed data for call
+    mov     rax, 1
+    INCSSP_RAX
+
+    mov     rax, cr4
+    btr     eax, 23                      ; clear CET
+    mov     cr4, rax
+    ret
+
+global ASM_PFX(EnableCet)
+ASM_PFX(EnableCet):
+
+    mov     rax, cr4
+    bts     eax, 23                      ; set CET
+    mov     cr4, rax
+
+    ; use jmp to skip the check for ret
+    pop     rax
+    jmp     rax
+
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
index 117502dafa..2c77cb47a4 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
@@ -1,7 +1,7 @@
 /** @file
 Page Fault (#PF) handler for X64 processors
 
-Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
 Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
 
 This program and the accompanying materials
@@ -23,6 +23,24 @@ LIST_ENTRY                          mPagePool = INITIALIZE_LIST_HEAD_VARIABLE (m
 BOOLEAN                             m1GPageTableSupport = FALSE;
 BOOLEAN                             mCpuSmmStaticPageTable;
 
+/**
+  Disable CET.
+**/
+VOID
+EFIAPI
+DisableCet (
+  VOID
+  );
+
+/**
+  Enable CET.
+**/
+VOID
+EFIAPI
+EnableCet (
+  VOID
+  );
+
 /**
   Check if 1-GByte pages is supported by processor or not.
 
@@ -821,6 +839,7 @@ SmiPFHandler (
     DumpCpuContext (InterruptType, SystemContext);
     DEBUG ((DEBUG_ERROR, "Do not support address 0x%lx by processor!\n", PFAddress));
     CpuDeadLoop ();
+    goto Exit;
   }
 
   //
@@ -855,6 +874,7 @@ SmiPFHandler (
       }
     }
     CpuDeadLoop ();
+    goto Exit;
   }
 
   //
@@ -869,6 +889,7 @@ SmiPFHandler (
         DumpModuleInfoByIp (*(UINTN *)(UINTN)SystemContext.SystemContextX64->Rsp);
       );
       CpuDeadLoop ();
+      goto Exit;
     }
 
     //
@@ -888,6 +909,7 @@ SmiPFHandler (
       }
 
       CpuDeadLoop ();
+      goto Exit;
     }
 
     if (mCpuSmmStaticPageTable && IsSmmCommBufferForbiddenAddress (PFAddress)) {
@@ -897,6 +919,7 @@ SmiPFHandler (
         DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextX64->Rip);
       );
       CpuDeadLoop ();
+      goto Exit;
     }
   }
 
@@ -930,6 +953,7 @@ SetPageTableAttributes (
   UINT64                *L4PageTable;
   BOOLEAN               IsSplitted;
   BOOLEAN               PageTableSplitted;
+  BOOLEAN               CetEnabled;
 
   //
   // Don't do this if
@@ -961,6 +985,13 @@ SetPageTableAttributes (
   // Disable write protection, because we need mark page table to be write protected.
   // We need *write* page table memory, to mark itself to be *read only*.
   //
+  CetEnabled = ((AsmReadCr4() & CR4_CET_ENABLE) != 0) ? TRUE : FALSE;
+  if (CetEnabled) {
+    //
+    // CET must be disabled if WP is disabled.
+    //
+    DisableCet();
+  }
   AsmWriteCr0 (AsmReadCr0() & ~CR0_WP);
 
   do {
@@ -1013,6 +1044,12 @@ SetPageTableAttributes (
   // Enable write protection, after page table updated.
   //
   AsmWriteCr0 (AsmReadCr0() | CR0_WP);
+  if (CetEnabled) {
+    //
+    // re-enable CET.
+    //
+    EnableCet();
+  }
 
   return ;
 }
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm
index 807b309b27..73febcea63 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm
@@ -1,5 +1,5 @@
 ;------------------------------------------------------------------------------ ;
-; Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
 ; 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,11 +19,26 @@
 ;-------------------------------------------------------------------------------
 
 %include "StuffRsbNasm.inc"
+%include "Nasm.inc"
 
 ;
 ; Variables referrenced by C code
 ;
 
+%define MSR_IA32_S_CET                     0x6A2
+%define   MSR_IA32_CET_SH_STK_EN             0x1
+%define   MSR_IA32_CET_WR_SHSTK_EN           0x2
+%define   MSR_IA32_CET_ENDBR_EN              0x4
+%define   MSR_IA32_CET_LEG_IW_EN             0x8
+%define   MSR_IA32_CET_NO_TRACK_EN           0x10
+%define   MSR_IA32_CET_SUPPRESS_DIS          0x20
+%define   MSR_IA32_CET_SUPPRESS              0x400
+%define   MSR_IA32_CET_TRACKER               0x800
+%define MSR_IA32_PL0_SSP                   0x6A4
+%define MSR_IA32_INTERRUPT_SSP_TABLE_ADDR  0x6A8
+
+%define CR4_CET                            0x800000
+
 %define MSR_IA32_MISC_ENABLE 0x1A0
 %define MSR_EFER      0xc0000080
 %define MSR_EFER_XD   0x800
@@ -63,6 +78,12 @@ global ASM_PFX(gPatchSmiCr3)
 global ASM_PFX(gcSmiHandlerTemplate)
 global ASM_PFX(gcSmiHandlerSize)
 
+extern ASM_PFX(mCetSupported)
+global ASM_PFX(mPatchCetSupported)
+global ASM_PFX(mPatchCetPl0Ssp)
+global ASM_PFX(mPatchCetInterruptSsp)
+global ASM_PFX(mPatchCetInterruptSspTable)
+
     DEFAULT REL
     SECTION .text
 
@@ -174,8 +195,71 @@ SmiHandlerIdtrAbsAddr:
     mov     ax, [rbx + DSC_SS]
     mov     ss, eax
 
-_SmiHandler:
-    mov     rbx, [rsp + 0x8]             ; rcx <- CpuIndex
+    mov     rbx, [rsp + 0x8]             ; rbx <- CpuIndex
+
+; enable CET if supported
+    mov     al, strict byte 1           ; source operand may be patched
+ASM_PFX(mPatchCetSupported):
+    cmp     al, 0
+    jz      CetDone
+
+    mov     ecx, MSR_IA32_S_CET
+    rdmsr
+    push    rdx
+    push    rax
+
+    mov     ecx, MSR_IA32_PL0_SSP
+    rdmsr
+    push    rdx
+    push    rax
+
+    mov     ecx, MSR_IA32_INTERRUPT_SSP_TABLE_ADDR
+    rdmsr
+    push    rdx
+    push    rax
+
+    mov     ecx, MSR_IA32_S_CET
+    mov     eax, MSR_IA32_CET_SH_STK_EN
+    xor     edx, edx
+    wrmsr
+
+    mov     ecx, MSR_IA32_PL0_SSP
+    mov     eax, strict dword 0         ; source operand will be patched
+ASM_PFX(mPatchCetPl0Ssp):
+    xor     edx, edx
+    wrmsr
+    mov     rcx, cr0
+    btr     ecx, 16                     ; clear WP
+    mov     cr0, rcx
+    mov     [eax], eax                  ; reload SSP, and clear busyflag.
+    xor     ecx, ecx
+    mov     [eax + 4], ecx
+
+    mov     ecx, MSR_IA32_INTERRUPT_SSP_TABLE_ADDR
+    mov     eax, strict dword 0         ; source operand will be patched
+ASM_PFX(mPatchCetInterruptSspTable):
+    xor     edx, edx
+    wrmsr
+
+    mov     eax, strict dword 0         ; source operand will be patched
+ASM_PFX(mPatchCetInterruptSsp):
+    cmp     eax, 0
+    jz      CetInterruptDone
+    mov     [eax], eax                  ; reload SSP, and clear busyflag.
+    xor     ecx, ecx
+    mov     [eax + 4], ecx
+CetInterruptDone:
+
+    mov     rcx, cr0
+    bts     ecx, 16                     ; set WP
+    mov     cr0, rcx
+
+    mov     eax, 0x668 | CR4_CET
+    mov     cr4, rax
+
+    SETSSBSY
+
+CetDone:
 
     ;
     ; Save FP registers
@@ -209,6 +293,31 @@ CpuSmmDebugExitAbsAddr:
 
     add     rsp, 0x200
 
+    mov     rax, strict qword 0        ;    mov     rax, ASM_PFX(mCetSupported)
+mCetSupportedAbsAddr:
+    mov     al, [rax]
+    cmp     al, 0
+    jz      CetDone2
+
+    mov     eax, 0x668
+    mov     cr4, rax       ; disable CET
+
+    mov     ecx, MSR_IA32_INTERRUPT_SSP_TABLE_ADDR
+    pop     rax
+    pop     rdx
+    wrmsr
+
+    mov     ecx, MSR_IA32_PL0_SSP
+    pop     rax
+    pop     rdx
+    wrmsr
+
+    mov     ecx, MSR_IA32_S_CET
+    pop     rax
+    pop     rdx
+    wrmsr
+CetDone2:
+
     mov     rax, strict qword 0         ;       lea     rax, [ASM_PFX(mXdSupported)]
 mXdSupportedAbsAddr:
     mov     al, [rax]
@@ -223,6 +332,7 @@ mXdSupportedAbsAddr:
     wrmsr
 
 .1:
+
     StuffRsb64
     rsm
 
@@ -257,4 +367,8 @@ ASM_PFX(PiSmmCpuSmiEntryFixupAddress):
     lea    rax, [ASM_PFX(mXdSupported)]
     lea    rcx, [mXdSupportedAbsAddr]
     mov    qword [rcx - 8], rax
+
+    lea    rax, [ASM_PFX(mCetSupported)]
+    lea    rcx, [mCetSupportedAbsAddr]
+    mov    qword [rcx - 8], rax
     ret
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c
index 89b3f2b725..c28c15b0ba 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c
@@ -1,7 +1,7 @@
 /** @file
   SMM CPU misc functions for x64 arch specific.
 
-Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
 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
@@ -17,6 +17,18 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 EFI_PHYSICAL_ADDRESS                mGdtBuffer;
 UINTN                               mGdtBufferSize;
 
+extern BOOLEAN mCetSupported;
+extern UINTN mSmmShadowStackSize;
+
+X86_ASSEMBLY_PATCH_LABEL mPatchCetPl0Ssp;
+X86_ASSEMBLY_PATCH_LABEL mPatchCetInterruptSsp;
+X86_ASSEMBLY_PATCH_LABEL mPatchCetInterruptSspTable;
+UINT32 mCetPl0Ssp;
+UINT32 mCetInterruptSsp;
+UINT32 mCetInterruptSspTable;
+
+UINTN  mSmmInterruptSspTables;
+
 /**
   Initialize IDT for SMM Stack Guard.
 
@@ -153,3 +165,47 @@ TransferApToSafeState (
   ASSERT (FALSE);
 }
 
+/**
+  Initialize the shadow stack related data structure.
+
+  @param CpuIndex     The index of CPU.
+  @param ShadowStack  The bottom of the shadow stack for this CPU.
+**/
+VOID
+InitShadowStack (
+  IN UINTN  CpuIndex,
+  IN VOID   *ShadowStack
+  )
+{
+  UINTN       SmmShadowStackSize;
+  UINT64      *InterruptSspTable;
+
+  if ((PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) && mCetSupported) {
+    SmmShadowStackSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmShadowStackSize)));
+    if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
+      SmmShadowStackSize += EFI_PAGES_TO_SIZE (2);
+    }
+    mCetPl0Ssp = (UINT32)((UINTN)ShadowStack + SmmShadowStackSize - sizeof(UINT64));
+    PatchInstructionX86 (mPatchCetPl0Ssp, mCetPl0Ssp, 4);
+    DEBUG ((DEBUG_INFO, "mCetPl0Ssp - 0x%x\n", mCetPl0Ssp));
+    DEBUG ((DEBUG_INFO, "ShadowStack - 0x%x\n", ShadowStack));
+    DEBUG ((DEBUG_INFO, "  SmmShadowStackSize - 0x%x\n", SmmShadowStackSize));
+
+    if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
+      if (mSmmInterruptSspTables == 0) {
+        mSmmInterruptSspTables = (UINTN)AllocateZeroPool(sizeof(UINT64) * 8 * gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus);
+        ASSERT (mSmmInterruptSspTables != 0);
+        DEBUG ((DEBUG_INFO, "mSmmInterruptSspTables - 0x%x\n", mSmmInterruptSspTables));
+      }
+      mCetInterruptSsp = (UINT32)((UINTN)ShadowStack + EFI_PAGES_TO_SIZE(1) - sizeof(UINT64));
+      mCetInterruptSspTable = (UINT32)(UINTN)(mSmmInterruptSspTables + sizeof(UINT64) * 8 * CpuIndex);
+      InterruptSspTable = (UINT64 *)(UINTN)mCetInterruptSspTable;
+      InterruptSspTable[1] = mCetInterruptSsp;
+      PatchInstructionX86 (mPatchCetInterruptSsp, mCetInterruptSsp, 4);
+      PatchInstructionX86 (mPatchCetInterruptSspTable, mCetInterruptSspTable, 4);
+      DEBUG ((DEBUG_INFO, "mCetInterruptSsp - 0x%x\n", mCetInterruptSsp));
+      DEBUG ((DEBUG_INFO, "mCetInterruptSspTable - 0x%x\n", mCetInterruptSspTable));
+    }
+  }
+}
+
diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index 69d777aa65..d51f3de114 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -1,7 +1,7 @@
 ## @file  UefiCpuPkg.dec
 # This Package provides UEFI compatible CPU modules and libraries.
 #
-# Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
 #
 # This program and the accompanying materials are licensed and made available under
 # the terms and conditions of the BSD License which accompanies this distribution.
@@ -177,6 +177,10 @@
   # @Prompt Processor stack size in SMM.
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackSize|0x2000|UINT32|0x32132105
 
+  ## Specifies shadow stack size in bytes for each processor in SMM.
+  # @Prompt Processor shadow stack size in SMM.
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmShadowStackSize|0x2000|UINT32|0x3213210E
+
   ## Indicates if SMM Code Access Check is enabled.
   #  If enabled, the SMM handler cannot execute the code outside SMM regions.
   #  This PCD is suggested to TRUE in production image.<BR><BR>
-- 
2.19.2.windows.1



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH V3 0/4] Add SMM CET support
  2019-02-22 13:30 [PATCH V3 0/4] Add SMM CET support Jiewen Yao
                   ` (3 preceding siblings ...)
  2019-02-22 13:30 ` [PATCH V3 4/4] UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM Jiewen Yao
@ 2019-02-22 14:29 ` Ni, Ray
  2019-02-22 21:41 ` Laszlo Ersek
  5 siblings, 0 replies; 8+ messages in thread
From: Ni, Ray @ 2019-02-22 14:29 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org
  Cc: Kinney, Michael D, Gao, Liming, Dong, Eric, Laszlo Ersek

Reviewed-by: Ray Ni <ray.ni@intel.com>

> -----Original Message-----
> From: Yao, Jiewen
> Sent: Friday, February 22, 2019 9:31 PM
> To: edk2-devel@lists.01.org
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Gao, Liming
> <liming.gao@intel.com>; Dong, Eric <eric.dong@intel.com>; Ni, Ray
> <ray.ni@intel.com>; Laszlo Ersek <lersek@redhat.com>; Yao, Jiewen
> <jiewen.yao@intel.com>
> Subject: [PATCH V3 0/4] Add SMM CET support
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1521
> 
> V3:
> Add Nasm.inc to include CET related instruction as MACRO.
> This is the only place to use DB.
> Any other NASM just use the MACRO -
> SETSSBSY, READSSP_[E|R]AX, INCSSP_[E|R]AX =====================
> 
> V2:
> Fix emulation platform issue.
> The NT32 platform cannot access CR4 register.
> So we add a global PCD to choose disable CR4 access in SetJump/LongJump.
> gEfiMdePkgTokenSpaceGuid.PcdControlFlowEnforcementPropertyMask
> =====================
> 
> This patch series implement add CET ShadowStack support for SMM.
> 
> The CET document can be found at:
> https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-
> enforcement-technology-preview.pdf
> 
> Patch 1 adds SSP (ShadowStackPointer) to JUMP_BUFFER.
> Patch 2 adds Control Protection exception (CP#) dump info.
> Patch 3 adds CET ShadowStack support in SMM.
> 
> For more detail please refer to each patch.
> 
> I also post all update to https://github.com/jyao1/edk2/tree/CET_V2
> 
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Yao Jiewen <jiewen.yao@intel.com>
> 
> Jiewen Yao (4):
>   MdePkg/Include: Add Nasm.inc
>   MdePkg/BaseLib: Add Shadow Stack Support for X86.
>   UefiCpuPkg/ExceptionLib: Add CET support.
>   UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.
> 
>  MdePkg/Include/Ia32/Nasm.inc                  |  28 ++++
>  MdePkg/Include/Library/BaseLib.h              |   2 +
>  MdePkg/Include/X64/Nasm.inc                   |  28 ++++
>  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 +
>  .../Include/Library/SmmCpuFeaturesLib.h       |  23 +++-
>  .../CpuExceptionCommon.c                      |   7 +-
>  .../CpuExceptionCommon.h                      |   3 +-
>  .../Ia32/ArchExceptionHandler.c               |   5 +-
>  .../X64/ArchExceptionHandler.c                |   5 +-
>  UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/Cet.nasm       |  39 ++++++
>  UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c      |  38 +++++-
>  UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.nasm  |  99 ++++++++++++++-
>  .../PiSmmCpuDxeSmm/Ia32/SmiException.nasm     |   6 +-
>  UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c |  57 ++++++++-
>  UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c         |  12 +-
>  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c    |  97 ++++++++++++--
>  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h    | 103
> ++++++++++++++-
>  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf  |   6 +-
>  .../PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c   |  85 ++++++++++++-
>  UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c        |  18 ++-
>  UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.h        |   4 +-
>  UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c    |   4 +-
>  UefiCpuPkg/PiSmmCpuDxeSmm/X64/Cet.nasm        |  40 ++++++
>  UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c       |  39 +++++-
>  UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm   | 120
> +++++++++++++++++-
>  UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c  |  58 ++++++++-
>  UefiCpuPkg/UefiCpuPkg.dec                     |   6 +-
>  34 files changed, 1034 insertions(+), 62 deletions(-)  create mode 100644
> MdePkg/Include/Ia32/Nasm.inc  create mode 100644
> MdePkg/Include/X64/Nasm.inc  create mode 100644
> UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/Cet.nasm
>  create mode 100644 UefiCpuPkg/PiSmmCpuDxeSmm/X64/Cet.nasm
> 
> --
> 2.19.2.windows.1



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH V3 0/4] Add SMM CET support
  2019-02-22 13:30 [PATCH V3 0/4] Add SMM CET support Jiewen Yao
                   ` (4 preceding siblings ...)
  2019-02-22 14:29 ` [PATCH V3 0/4] Add SMM CET support Ni, Ray
@ 2019-02-22 21:41 ` Laszlo Ersek
  2019-02-23  1:08   ` Yao, Jiewen
  5 siblings, 1 reply; 8+ messages in thread
From: Laszlo Ersek @ 2019-02-22 21:41 UTC (permalink / raw)
  To: Jiewen Yao, edk2-devel; +Cc: Eric Dong, Liming Gao, Michael D Kinney

Hi Jiewen,

On 02/22/19 14:30, Jiewen Yao wrote:
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1521
> 
> V3:
> Add Nasm.inc to include CET related instruction as MACRO.
> This is the only place to use DB.
> Any other NASM just use the MACRO - 
> SETSSBSY, READSSP_[E|R]AX, INCSSP_[E|R]AX
> =====================
> 
> V2:
> Fix emulation platform issue.
> The NT32 platform cannot access CR4 register.
> So we add a global PCD to choose disable CR4 access in SetJump/LongJump.
> gEfiMdePkgTokenSpaceGuid.PcdControlFlowEnforcementPropertyMask
> =====================

(1) I think there is another difference (I don't know if it was
introduced in v2 or in v3; I only compared v1<->v3). It seems that the
LongJump / SetJump changes for IA32 MSFT were implemented in v2/v3 as well.

(2) When we introduce another bit for
PcdControlFlowEnforcementPropertyMask, we'll have to update the checks,
because currently we check the whole PCD against zero. When the next bit
is introduced, we'll have to use a bitmask (with value 1) for checking.
Anyway that can indeed be a later enhancement, just stating what I've
noticed.

(3) For the series:

Regression-tested-by: Laszlo Ersek <lersek@redhat.com>

Thanks,
Laszlo

> 
> This patch series implement add CET ShadowStack support for SMM.
> 
> The CET document can be found at:
> https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-enforcement-technology-preview.pdf
> 
> Patch 1 adds SSP (ShadowStackPointer) to JUMP_BUFFER.
> Patch 2 adds Control Protection exception (CP#) dump info.
> Patch 3 adds CET ShadowStack support in SMM.
> 
> For more detail please refer to each patch. 
> 
> I also post all update to https://github.com/jyao1/edk2/tree/CET_V2
> 
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Yao Jiewen <jiewen.yao@intel.com>
> 
> Jiewen Yao (4):
>   MdePkg/Include: Add Nasm.inc
>   MdePkg/BaseLib: Add Shadow Stack Support for X86.
>   UefiCpuPkg/ExceptionLib: Add CET support.
>   UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.
> 
>  MdePkg/Include/Ia32/Nasm.inc                  |  28 ++++
>  MdePkg/Include/Library/BaseLib.h              |   2 +
>  MdePkg/Include/X64/Nasm.inc                   |  28 ++++
>  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 +
>  .../Include/Library/SmmCpuFeaturesLib.h       |  23 +++-
>  .../CpuExceptionCommon.c                      |   7 +-
>  .../CpuExceptionCommon.h                      |   3 +-
>  .../Ia32/ArchExceptionHandler.c               |   5 +-
>  .../X64/ArchExceptionHandler.c                |   5 +-
>  UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/Cet.nasm       |  39 ++++++
>  UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c      |  38 +++++-
>  UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.nasm  |  99 ++++++++++++++-
>  .../PiSmmCpuDxeSmm/Ia32/SmiException.nasm     |   6 +-
>  UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c |  57 ++++++++-
>  UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c         |  12 +-
>  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c    |  97 ++++++++++++--
>  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h    | 103 ++++++++++++++-
>  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf  |   6 +-
>  .../PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c   |  85 ++++++++++++-
>  UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c        |  18 ++-
>  UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.h        |   4 +-
>  UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c    |   4 +-
>  UefiCpuPkg/PiSmmCpuDxeSmm/X64/Cet.nasm        |  40 ++++++
>  UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c       |  39 +++++-
>  UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm   | 120 +++++++++++++++++-
>  UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c  |  58 ++++++++-
>  UefiCpuPkg/UefiCpuPkg.dec                     |   6 +-
>  34 files changed, 1034 insertions(+), 62 deletions(-)
>  create mode 100644 MdePkg/Include/Ia32/Nasm.inc
>  create mode 100644 MdePkg/Include/X64/Nasm.inc
>  create mode 100644 UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/Cet.nasm
>  create mode 100644 UefiCpuPkg/PiSmmCpuDxeSmm/X64/Cet.nasm
> 



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH V3 0/4] Add SMM CET support
  2019-02-22 21:41 ` Laszlo Ersek
@ 2019-02-23  1:08   ` Yao, Jiewen
  0 siblings, 0 replies; 8+ messages in thread
From: Yao, Jiewen @ 2019-02-23  1:08 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: edk2-devel@lists.01.org

Good comment!
Response inline


thank you!
Yao, Jiewen


> 在 2019年2月23日,上午5:42,Laszlo Ersek <lersek@redhat.com> 写道:
> 
> Hi Jiewen,
> 
>> On 02/22/19 14:30, Jiewen Yao wrote:
>> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1521
>> 
>> V3:
>> Add Nasm.inc to include CET related instruction as MACRO.
>> This is the only place to use DB.
>> Any other NASM just use the MACRO - 
>> SETSSBSY, READSSP_[E|R]AX, INCSSP_[E|R]AX
>> =====================
>> 
>> V2:
>> Fix emulation platform issue.
>> The NT32 platform cannot access CR4 register.
>> So we add a global PCD to choose disable CR4 access in SetJump/LongJump.
>> gEfiMdePkgTokenSpaceGuid.PcdControlFlowEnforcementPropertyMask
>> =====================
> 
> (1) I think there is another difference (I don't know if it was
> introduced in v2 or in v3; I only compared v1<->v3). It seems that the
> LongJump / SetJump changes for IA32 MSFT were implemented in v2/v3 as well.
[jiewen] you are right. I realize that I forgot to Chang the C file. I only changed the nasm file in V1. This is not caught because we don’t have IA32 CET enabled platform, as I mentioned in V1 comment.
I think we should only have 1 solution. Both C and Nasm is a bad choice, that increase the maintenance effort and validation effort. 
I have talked with Liming. Hope we will do sth after Q1 release. 

> 
> (2) When we introduce another bit for
> PcdControlFlowEnforcementPropertyMask, we'll have to update the checks,
> because currently we check the whole PCD against zero. When the next bit
> is introduced, we'll have to use a bitmask (with value 1) for checking.
> Anyway that can indeed be a later enhancement, just stating what I've
> noticed.
[jiewen] Yes I did think a lot what check we should do.
The potential future bit is: 1) SMM IBT support. 2) DXE SSP support. 3) DXE IBT support. We have not done IBT yet today because it depends upon compiler update. For DXE I did POC as test environment. 
If we add SMM IBT, some check should be global CET. Some should be SSP specific. Case by case. I think we can cross the bridge when we come to it. 

Anyway both 1 and 2 are excellent feedback. Appreciate your review.  


> 
> (3) For the series:
> 
> Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
[jiewen] thank you!
> 
> Thanks,
> Laszlo
> 
>> 
>> This patch series implement add CET ShadowStack support for SMM.
>> 
>> The CET document can be found at:
>> https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-enforcement-technology-preview.pdf
>> 
>> Patch 1 adds SSP (ShadowStackPointer) to JUMP_BUFFER.
>> Patch 2 adds Control Protection exception (CP#) dump info.
>> Patch 3 adds CET ShadowStack support in SMM.
>> 
>> For more detail please refer to each patch. 
>> 
>> I also post all update to https://github.com/jyao1/edk2/tree/CET_V2
>> 
>> Cc: Michael D Kinney <michael.d.kinney@intel.com>
>> Cc: Liming Gao <liming.gao@intel.com>
>> Cc: Eric Dong <eric.dong@intel.com>
>> Cc: Ray Ni <ray.ni@intel.com>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Contributed-under: TianoCore Contribution Agreement 1.1
>> Signed-off-by: Yao Jiewen <jiewen.yao@intel.com>
>> 
>> Jiewen Yao (4):
>>  MdePkg/Include: Add Nasm.inc
>>  MdePkg/BaseLib: Add Shadow Stack Support for X86.
>>  UefiCpuPkg/ExceptionLib: Add CET support.
>>  UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.
>> 
>> MdePkg/Include/Ia32/Nasm.inc                  |  28 ++++
>> MdePkg/Include/Library/BaseLib.h              |   2 +
>> MdePkg/Include/X64/Nasm.inc                   |  28 ++++
>> 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 +
>> .../Include/Library/SmmCpuFeaturesLib.h       |  23 +++-
>> .../CpuExceptionCommon.c                      |   7 +-
>> .../CpuExceptionCommon.h                      |   3 +-
>> .../Ia32/ArchExceptionHandler.c               |   5 +-
>> .../X64/ArchExceptionHandler.c                |   5 +-
>> UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/Cet.nasm       |  39 ++++++
>> UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c      |  38 +++++-
>> UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.nasm  |  99 ++++++++++++++-
>> .../PiSmmCpuDxeSmm/Ia32/SmiException.nasm     |   6 +-
>> UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c |  57 ++++++++-
>> UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c         |  12 +-
>> UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c    |  97 ++++++++++++--
>> UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h    | 103 ++++++++++++++-
>> UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf  |   6 +-
>> .../PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c   |  85 ++++++++++++-
>> UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c        |  18 ++-
>> UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.h        |   4 +-
>> UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c    |   4 +-
>> UefiCpuPkg/PiSmmCpuDxeSmm/X64/Cet.nasm        |  40 ++++++
>> UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c       |  39 +++++-
>> UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm   | 120 +++++++++++++++++-
>> UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c  |  58 ++++++++-
>> UefiCpuPkg/UefiCpuPkg.dec                     |   6 +-
>> 34 files changed, 1034 insertions(+), 62 deletions(-)
>> create mode 100644 MdePkg/Include/Ia32/Nasm.inc
>> create mode 100644 MdePkg/Include/X64/Nasm.inc
>> create mode 100644 UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/Cet.nasm
>> create mode 100644 UefiCpuPkg/PiSmmCpuDxeSmm/X64/Cet.nasm
>> 
> 


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2019-02-23  1:08 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-02-22 13:30 [PATCH V3 0/4] Add SMM CET support Jiewen Yao
2019-02-22 13:30 ` [PATCH V3 1/4] MdePkg/Include: Add Nasm.inc Jiewen Yao
2019-02-22 13:30 ` [PATCH V3 2/4] MdePkg/BaseLib: Add Shadow Stack Support for X86 Jiewen Yao
2019-02-22 13:30 ` [PATCH V3 3/4] UefiCpuPkg/ExceptionLib: Add CET support Jiewen Yao
2019-02-22 13:30 ` [PATCH V3 4/4] UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM Jiewen Yao
2019-02-22 14:29 ` [PATCH V3 0/4] Add SMM CET support Ni, Ray
2019-02-22 21:41 ` Laszlo Ersek
2019-02-23  1:08   ` Yao, Jiewen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox