[libcxx-commits] [PATCH] D136667: Check return address stored in normal stack and CET shadow stack in unwind process phase2

xiongji90 via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Tue Nov 8 22:12:47 PST 2022


This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG4db687155bc1: [libunwind] Check corrupted return address in unwind_phase2 when CET is enabled. (authored by xiongji90).

Changed prior to commit:
  https://reviews.llvm.org/D136667?vs=472226&id=474154#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136667/new/

https://reviews.llvm.org/D136667

Files:
  libunwind/src/UnwindLevel1.c


Index: libunwind/src/UnwindLevel1.c
===================================================================
--- libunwind/src/UnwindLevel1.c
+++ libunwind/src/UnwindLevel1.c
@@ -50,6 +50,7 @@
     __unw_resume((cursor));                                                    \
   } while (0)
 #elif defined(_LIBUNWIND_TARGET_I386)
+#define __cet_ss_step_size 4
 #define __unw_phase2_resume(cursor, fn)                                        \
   do {                                                                         \
     _LIBUNWIND_POP_CET_SSP((fn));                                              \
@@ -61,6 +62,7 @@
                      "d"(cetJumpAddress));                                     \
   } while (0)
 #elif defined(_LIBUNWIND_TARGET_X86_64)
+#define __cet_ss_step_size 8
 #define __unw_phase2_resume(cursor, fn)                                        \
   do {                                                                         \
     _LIBUNWIND_POP_CET_SSP((fn));                                              \
@@ -177,6 +179,9 @@
   // uc is initialized by __unw_getcontext in the parent frame. The first stack
   // frame walked is unwind_phase2.
   unsigned framesWalked = 1;
+#ifdef _LIBUNWIND_USE_CET
+  unsigned long shadowStackTop = _get_ssp();
+#endif
   // Walk each frame until we reach where search phase said to stop.
   while (true) {
 
@@ -228,6 +233,20 @@
     }
 #endif
 
+// In CET enabled environment, we check return address stored in normal stack
+// against return address stored in CET shadow stack, if the 2 addresses don't
+// match, it means return address in normal stack has been corrupted, we return
+// _URC_FATAL_PHASE2_ERROR.
+#ifdef _LIBUNWIND_USE_CET
+    if (shadowStackTop != 0) {
+      unw_word_t retInNormalStack;
+      __unw_get_reg(cursor, UNW_REG_IP, &retInNormalStack);
+      unsigned long retInShadowStack = *(
+          unsigned long *)(shadowStackTop + __cet_ss_step_size * framesWalked);
+      if (retInNormalStack != retInShadowStack)
+        return _URC_FATAL_PHASE2_ERROR;
+    }
+#endif
     ++framesWalked;
     // If there is a personality routine, tell it we are unwinding.
     if (frameInfo.handler != 0) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D136667.474154.patch
Type: text/x-patch
Size: 2188 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20221109/45ddb0d7/attachment.bin>


More information about the libcxx-commits mailing list