summaryrefslogtreecommitdiffstats
path: root/BaseTools
diff options
context:
space:
mode:
authorJiaxin Wu <jiaxin.wu@intel.com>2023-10-27 15:20:25 +0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2023-11-10 01:21:12 +0000
commit589f2e49e5f9ff998bd4f08cbf28a1572ab7b544 (patch)
treec1c6a966c1e155fd167514f7ec5be8119e0203bb /BaseTools
parent35c0c63edbab6a37d6c019d613a4b06529941a80 (diff)
downloadedk2-589f2e49e5f9ff998bd4f08cbf28a1572ab7b544.tar.gz
edk2-589f2e49e5f9ff998bd4f08cbf28a1572ab7b544.tar.bz2
edk2-589f2e49e5f9ff998bd4f08cbf28a1572ab7b544.zip
UefiCpuPkg/PiSmmCpuDxeSmm: Fix CP Exception when CET enable
Root cause: 1. Before DisableReadonlyPageWriteProtect() is called, the return address (#1) is pushed in shadow stack. 2. CET is disabled. 3. DisableReadonlyPageWriteProtect() returns to #1. 4. Page table is modified. 5. EnableReadonlyPageWriteProtect() is called, but the return address (#2) is not pushed in shadow stack. 6. CET is enabled. 7. EnableReadonlyPageWriteProtect() returns to #2. #CP exception happens because the actual return address (#2) doesn't match the return address stored in shadow stack (#1). Analysis: Shadow stack will stop update after CET disable (DisableCet() in DisableReadOnlyPageWriteProtect), but normal smi stack will be continue updated with the function called and return (DisableReadOnlyPageWriteProtect & EnableReadOnlyPageWriteProtect), thus leading stack mismatch after CET re-enabled (EnableCet() in EnableReadOnlyPageWriteProtect). According SDM Vol 3, 6.15-Control Protection Exception: Normal smi stack and shadow stack must be matched when CET enable, otherwise CP Exception will happen, which is caused by a near RET instruction. CET is disabled in DisableCet(), while can be enabled in EnableCet(). This way won't cause the problem because they are implemented in a way that return address of DisableCet() is poped out from shadow stack (Incsspq performs a pop to increases the shadow stack) and EnableCet() doesn't use "RET" but "JMP" to return to caller. So calling EnableCet() and DisableCet() doesn't have the same issue as calling DisableReadonlyPageWriteProtect() and EnableReadonlyPageWriteProtect(). With above root cause & analysis, define below 2 macros instead of functions for WP & CET operation: WRITE_UNPROTECT_RO_PAGES (Wp, Cet) WRITE_PROTECT_RO_PAGES (Wp, Cet) Because DisableCet() & EnableCet() must be in the same function to avoid shadow stack and normal SMI stack mismatch. Note: WRITE_UNPROTECT_RO_PAGES () must be called pair with WRITE_PROTECT_RO_PAGES () in same function. Change-Id: I4e126697efcd8dbfb4887da034d8691bfca969e3 Cc: Eric Dong <eric.dong@intel.com> Cc: Ray Ni <ray.ni@intel.com> Cc: Zeng Star <star.zeng@intel.com> Cc: Gerd Hoffmann <kraxel@redhat.com> Cc: Rahul Kumar <rahul1.kumar@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Signed-off-by: Jiaxin Wu <jiaxin.wu@intel.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Ray Ni <ray.ni@intel.com> Reviewed-by: Eric Dong <eric.dong@intel.com>
Diffstat (limited to 'BaseTools')
0 files changed, 0 insertions, 0 deletions