[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 1 01:10:50 PDT 2022
xiongji90 updated this revision to Diff 472225.
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;
+#if defined(_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,21 @@
}
#endif
+// In CET enabled environment, we check return address stored in normal stack
+// agains 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. We don't do that check for non-catchable exception
+// since process will be terminated.
+#if defined(_LIBUNWIND_USE_CET)
+ if (shadowStackTop != 0 && exception_object->exception_class != 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) {
@@ -295,6 +315,10 @@
// uc is initialized by __unw_getcontext in the parent frame. The first stack
// frame walked is unwind_phase2_forced.
unsigned framesWalked = 1;
+#if defined(_LIBUNWIND_USE_CET)
+ unsigned long shadowStackTop = _get_ssp();
+#endif
+
// Walk each frame until we reach where search phase said to stop
while (__unw_step_stage2(cursor) > 0) {
@@ -342,6 +366,16 @@
return _URC_FATAL_PHASE2_ERROR;
}
+#if defined(_LIBUNWIND_USE_CET)
+ if (shadowStackTop != 0 && exception_object->exception_class != 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.472225.patch
Type: text/x-patch
Size: 3336 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20221101/f529565c/attachment-0001.bin>
More information about the libcxx-commits
mailing list