aligned. If the original shadow stack is 8 byte aligned, we just
need to pop 2 slots, one restore token, from shadow stack. Otherwise,
we need to pop 3 slots, one restore token + 4 byte padding, from
- shadow stack. */
-#ifndef __x86_64__
+ shadow stack.
+
+ When popping a stack frame, we compare the return address on normal
+ stack against the return address on shadow stack. If they don't match,
+ return _URC_FATAL_PHASE2_ERROR for the corrupted return address on
+ normal stack. Don't check the return address for
+ 1. Non-catchable exception where exception_class == 0. Process will
+ be terminated.
+ 2. Zero return address which marks the outermost stack frame.
+ 3. Signal stack frame since kernel puts a restore token on shadow
+ stack.
+ */
#undef _Unwind_Frames_Increment
-#define _Unwind_Frames_Increment(context, frames) \
+#ifdef __x86_64__
+#define _Unwind_Frames_Increment(exc, context, frames) \
+ { \
+ frames++; \
+ if (exc->exception_class != 0 \
+ && _Unwind_GetIP (context) != 0 \
+ && !_Unwind_IsSignalFrame (context)) \
+ { \
+ _Unwind_Word ssp = _get_ssp (); \
+ if (ssp != 0) \
+ { \
+ ssp += 8 * frames; \
+ _Unwind_Word ra = *(_Unwind_Word *) ssp; \
+ if (ra != _Unwind_GetIP (context)) \
+ return _URC_FATAL_PHASE2_ERROR; \
+ } \
+ } \
+ }
+#else
+#define _Unwind_Frames_Increment(exc, context, frames) \
if (_Unwind_IsSignalFrame (context)) \
do \
{ \
} \
while (0); \
else \
- frames++;
+ { \
+ frames++; \
+ if (exc->exception_class != 0 \
+ && _Unwind_GetIP (context) != 0) \
+ { \
+ _Unwind_Word ssp = _get_ssp (); \
+ if (ssp != 0) \
+ { \
+ ssp += 4 * frames; \
+ _Unwind_Word ra = *(_Unwind_Word *) ssp; \
+ if (ra != _Unwind_GetIP (context)) \
+ return _URC_FATAL_PHASE2_ERROR; \
+ } \
+ } \
+ }
#endif
gcc_assert (!match_handler);
uw_update_context (context, &fs);
- _Unwind_Frames_Increment (context, frames);
+ _Unwind_Frames_Increment (exc, context, frames);
}
*frames_p = frames;
/* Update cur_context to describe the same frame as fs, and discard
the previous context if necessary. */
uw_advance_context (context, &fs);
- _Unwind_Frames_Increment (context, frames);
+ _Unwind_Frames_Increment (exc, context, frames);
}
*frames_p = frames;