[libunwind][NFC] Remove the CET keyword in shadow stack-related stuffs (#126663)
libunwind currently supports shadow stack based on the Intel CET and AArch64 GCS technology, but throughout related codes, the Intel-specific keyword, "CET", is used to refer to the generic concept of control-flow integrity/shadow stack. This patch replaces such wordings with architecture-neutral term "shadow stack" (abbr. "shstk") to allow future implementation to avoid using the Intel-specific "CET" term.
This commit is contained in:
@@ -36,7 +36,6 @@ set(LIBUNWIND_HEADERS
|
||||
AddressSpace.hpp
|
||||
assembly.h
|
||||
CompactUnwinder.hpp
|
||||
cet_unwind.h
|
||||
config.h
|
||||
dwarf2.h
|
||||
DwarfInstructions.hpp
|
||||
@@ -46,6 +45,7 @@ set(LIBUNWIND_HEADERS
|
||||
libunwind_ext.h
|
||||
Registers.hpp
|
||||
RWMutex.hpp
|
||||
shadow_stack_unwind.h
|
||||
Unwind-EHABI.h
|
||||
UnwindCursor.hpp
|
||||
../include/libunwind.h
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cet_unwind.h"
|
||||
#include "config.h"
|
||||
#include "libunwind.h"
|
||||
#include "shadow_stack_unwind.h"
|
||||
|
||||
namespace libunwind {
|
||||
|
||||
@@ -48,7 +48,7 @@ class _LIBUNWIND_HIDDEN Registers_x86;
|
||||
extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *);
|
||||
|
||||
#if defined(_LIBUNWIND_USE_CET)
|
||||
extern "C" void *__libunwind_cet_get_jump_target() {
|
||||
extern "C" void *__libunwind_shstk_get_jump_target() {
|
||||
return reinterpret_cast<void *>(&__libunwind_Registers_x86_jumpto);
|
||||
}
|
||||
#endif
|
||||
@@ -268,7 +268,7 @@ class _LIBUNWIND_HIDDEN Registers_x86_64;
|
||||
extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *);
|
||||
|
||||
#if defined(_LIBUNWIND_USE_CET)
|
||||
extern "C" void *__libunwind_cet_get_jump_target() {
|
||||
extern "C" void *__libunwind_shstk_get_jump_target() {
|
||||
return reinterpret_cast<void *>(&__libunwind_Registers_x86_64_jumpto);
|
||||
}
|
||||
#endif
|
||||
@@ -1817,7 +1817,7 @@ class _LIBUNWIND_HIDDEN Registers_arm64;
|
||||
extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);
|
||||
|
||||
#if defined(_LIBUNWIND_USE_GCS)
|
||||
extern "C" void *__libunwind_cet_get_jump_target() {
|
||||
extern "C" void *__libunwind_shstk_get_jump_target() {
|
||||
return reinterpret_cast<void *>(&__libunwind_Registers_arm64_jumpto);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#ifndef __UNWINDCURSOR_HPP__
|
||||
#define __UNWINDCURSOR_HPP__
|
||||
|
||||
#include "cet_unwind.h"
|
||||
#include "shadow_stack_unwind.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -3122,7 +3122,7 @@ bool UnwindCursor<A, R>::isReadableAddr(const pint_t addr) const {
|
||||
#endif
|
||||
|
||||
#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)
|
||||
extern "C" void *__libunwind_cet_get_registers(unw_cursor_t *cursor) {
|
||||
extern "C" void *__libunwind_shstk_get_registers(unw_cursor_t *cursor) {
|
||||
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
|
||||
return co->get_registers();
|
||||
}
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cet_unwind.h"
|
||||
#include "config.h"
|
||||
#include "libunwind.h"
|
||||
#include "libunwind_ext.h"
|
||||
#include "shadow_stack_unwind.h"
|
||||
#include "unwind.h"
|
||||
|
||||
#if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__) && \
|
||||
@@ -36,14 +36,17 @@
|
||||
|
||||
#ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND
|
||||
|
||||
// When CET is enabled, each "call" instruction will push return address to
|
||||
// CET shadow stack, each "ret" instruction will pop current CET shadow stack
|
||||
// top and compare it with target address which program will return.
|
||||
// In exception handing, some stack frames will be skipped before jumping to
|
||||
// landing pad and we must adjust CET shadow stack accordingly.
|
||||
// _LIBUNWIND_POP_CET_SSP is used to adjust CET shadow stack pointer and we
|
||||
// directly jump to __libunwind_Registers_x86/x86_64_jumpto instead of using
|
||||
// a regular function call to avoid pushing to CET shadow stack again.
|
||||
// When shadow stack is enabled, a separate stack containing only return
|
||||
// addresses would be maintained. On function return, the return address would
|
||||
// be compared to the popped address from shadow stack to ensure the return
|
||||
// target is not tempered with. When unwinding, we're skipping the normal return
|
||||
// procedure for multiple frames and thus need to pop the return addresses of
|
||||
// the skipped frames from shadow stack to avoid triggering an exception (using
|
||||
// `_LIBUNWIND_POP_SHSTK_SSP()`). Also, some architectures, like the x86-family
|
||||
// CET, push the return adddresses onto shadow stack with common call
|
||||
// instructions, so for these architectures, normal function calls should be
|
||||
// avoided when invoking the `jumpto()` function. To do this, we use inline
|
||||
// assemblies to "goto" the `jumpto()` for these architectures.
|
||||
#if !defined(_LIBUNWIND_USE_CET) && !defined(_LIBUNWIND_USE_GCS)
|
||||
#define __unw_phase2_resume(cursor, fn) \
|
||||
do { \
|
||||
@@ -51,38 +54,38 @@
|
||||
__unw_resume((cursor)); \
|
||||
} while (0)
|
||||
#elif defined(_LIBUNWIND_TARGET_I386)
|
||||
#define __cet_ss_step_size 4
|
||||
#define __shstk_step_size (4)
|
||||
#define __unw_phase2_resume(cursor, fn) \
|
||||
do { \
|
||||
_LIBUNWIND_POP_CET_SSP((fn)); \
|
||||
void *cetRegContext = __libunwind_cet_get_registers((cursor)); \
|
||||
void *cetJumpAddress = __libunwind_cet_get_jump_target(); \
|
||||
_LIBUNWIND_POP_SHSTK_SSP((fn)); \
|
||||
void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \
|
||||
void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \
|
||||
__asm__ volatile("push %%edi\n\t" \
|
||||
"sub $4, %%esp\n\t" \
|
||||
"jmp *%%edx\n\t" :: "D"(cetRegContext), \
|
||||
"d"(cetJumpAddress)); \
|
||||
"jmp *%%edx\n\t" ::"D"(shstkRegContext), \
|
||||
"d"(shstkJumpAddress)); \
|
||||
} while (0)
|
||||
#elif defined(_LIBUNWIND_TARGET_X86_64)
|
||||
#define __cet_ss_step_size 8
|
||||
#define __shstk_step_size (8)
|
||||
#define __unw_phase2_resume(cursor, fn) \
|
||||
do { \
|
||||
_LIBUNWIND_POP_CET_SSP((fn)); \
|
||||
void *cetRegContext = __libunwind_cet_get_registers((cursor)); \
|
||||
void *cetJumpAddress = __libunwind_cet_get_jump_target(); \
|
||||
__asm__ volatile("jmpq *%%rdx\n\t" :: "D"(cetRegContext), \
|
||||
"d"(cetJumpAddress)); \
|
||||
_LIBUNWIND_POP_SHSTK_SSP((fn)); \
|
||||
void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \
|
||||
void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \
|
||||
__asm__ volatile("jmpq *%%rdx\n\t" ::"D"(shstkRegContext), \
|
||||
"d"(shstkJumpAddress)); \
|
||||
} while (0)
|
||||
#elif defined(_LIBUNWIND_TARGET_AARCH64)
|
||||
#define __cet_ss_step_size 8
|
||||
#define __shstk_step_size (8)
|
||||
#define __unw_phase2_resume(cursor, fn) \
|
||||
do { \
|
||||
_LIBUNWIND_POP_CET_SSP((fn)); \
|
||||
void *cetRegContext = __libunwind_cet_get_registers((cursor)); \
|
||||
void *cetJumpAddress = __libunwind_cet_get_jump_target(); \
|
||||
_LIBUNWIND_POP_SHSTK_SSP((fn)); \
|
||||
void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \
|
||||
void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \
|
||||
__asm__ volatile("mov x0, %0\n\t" \
|
||||
"br %1\n\t" \
|
||||
: \
|
||||
: "r"(cetRegContext), "r"(cetJumpAddress) \
|
||||
: "r"(shstkRegContext), "r"(shstkJumpAddress) \
|
||||
: "x0"); \
|
||||
} while (0)
|
||||
#endif
|
||||
@@ -255,16 +258,16 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
|
||||
}
|
||||
#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
|
||||
// In shadow stack enabled environment, we check return address stored in normal
|
||||
// stack against return address stored in 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.
|
||||
#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)
|
||||
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);
|
||||
unsigned long retInShadowStack =
|
||||
*(unsigned long *)(shadowStackTop + __shstk_step_size * framesWalked);
|
||||
if (retInNormalStack != retInShadowStack)
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LIBUNWIND_CET_UNWIND_H
|
||||
#define LIBUNWIND_CET_UNWIND_H
|
||||
#ifndef LIBUNWIND_SHADOW_STACK_UNWIND_H
|
||||
#define LIBUNWIND_SHADOW_STACK_UNWIND_H
|
||||
|
||||
#include "libunwind.h"
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <cet.h>
|
||||
#include <immintrin.h>
|
||||
|
||||
#define _LIBUNWIND_POP_CET_SSP(x) \
|
||||
#define _LIBUNWIND_POP_SHSTK_SSP(x) \
|
||||
do { \
|
||||
unsigned long ssp = _get_ssp(); \
|
||||
if (ssp != 0) { \
|
||||
@@ -46,7 +46,7 @@
|
||||
#define _LIBUNWIND_USE_GCS 1
|
||||
#endif
|
||||
|
||||
#define _LIBUNWIND_POP_CET_SSP(x) \
|
||||
#define _LIBUNWIND_POP_SHSTK_SSP(x) \
|
||||
do { \
|
||||
if (__chkfeat(_CHKFEAT_GCS)) { \
|
||||
unsigned tmp = (x); \
|
||||
@@ -57,7 +57,7 @@
|
||||
|
||||
#endif
|
||||
|
||||
extern void *__libunwind_cet_get_registers(unw_cursor_t *);
|
||||
extern void *__libunwind_cet_get_jump_target(void);
|
||||
extern void *__libunwind_shstk_get_registers(unw_cursor_t *);
|
||||
extern void *__libunwind_shstk_get_jump_target(void);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user