Skip to content

Commit

Permalink
[libunwind] Fix problems caused by combining BTI and GCS (#102322)
Browse files Browse the repository at this point in the history
The libunwind assembly files need adjustment in order to work correctly
when both BTI and GCS are both enabled (which will be the case when
using -mbranch-protection=standard):
* __libunwind_Registers_arm64_jumpto can't use br to jump to the return
location, instead we need to use gcspush then ret.
* Because we indirectly call __libunwind_Registers_arm64_jumpto it needs
to start with bti jc.
 * We need to set the GCS GNU property bit when it's enabled.

---------

Co-authored-by: Daniel Kiss <[email protected]>
  • Loading branch information
john-brawn-arm and DanielKristofKiss authored Aug 8, 2024
1 parent 00f90d3 commit 3952910
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 6 deletions.
16 changes: 15 additions & 1 deletion libunwind/src/UnwindRegistersRestore.S
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,10 @@ Lnovec:

#elif defined(__aarch64__)

#if defined(__ARM_FEATURE_GCS_DEFAULT)
.arch_extension gcs
#endif

//
// extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);
//
Expand Down Expand Up @@ -680,7 +684,17 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
ldr x16, [x0, #0x0F8]
ldp x0, x1, [x0, #0x000] // restore x0,x1
mov sp,x16 // restore sp
br x30 // jump to pc
#if defined(__ARM_FEATURE_GCS_DEFAULT)
// If GCS is enabled we need to push the address we're returning to onto the
// GCS stack. We can't just return using br, as there won't be a BTI landing
// pad instruction at the destination.
mov x16, #1
chkfeat x16
cbnz x16, Lnogcs
gcspushm x30
Lnogcs:
#endif
ret x30 // jump to pc

#elif defined(__arm__) && !defined(__APPLE__)

Expand Down
25 changes: 20 additions & 5 deletions libunwind/src/assembly.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,22 @@
#define PPC64_OPD2
#endif

#if defined(__aarch64__) && defined(__ARM_FEATURE_BTI_DEFAULT)
#if defined(__aarch64__)
#if defined(__ARM_FEATURE_GCS_DEFAULT) && defined(__ARM_FEATURE_BTI_DEFAULT)
// Set BTI, PAC, and GCS gnu property bits
#define GNU_PROPERTY 7
// We indirectly branch to __libunwind_Registers_arm64_jumpto from
// __unw_phase2_resume, so we need to use bti jc.
#define AARCH64_BTI bti jc
#elif defined(__ARM_FEATURE_GCS_DEFAULT)
// Set GCS gnu property bit
#define GNU_PROPERTY 4
#elif defined(__ARM_FEATURE_BTI_DEFAULT)
// Set BTI and PAC gnu property bits
#define GNU_PROPERTY 3
#define AARCH64_BTI bti c
#endif
#ifdef GNU_PROPERTY
.pushsection ".note.gnu.property", "a" SEPARATOR \
.balign 8 SEPARATOR \
.long 4 SEPARATOR \
Expand All @@ -91,12 +106,12 @@
.asciz "GNU" SEPARATOR \
.long 0xc0000000 SEPARATOR /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ \
.long 4 SEPARATOR \
.long 3 SEPARATOR /* GNU_PROPERTY_AARCH64_FEATURE_1_BTI AND */ \
/* GNU_PROPERTY_AARCH64_FEATURE_1_PAC */ \
.long GNU_PROPERTY SEPARATOR \
.long 0 SEPARATOR \
.popsection SEPARATOR
#define AARCH64_BTI bti c
#else
#endif
#endif
#if !defined(AARCH64_BTI)
#define AARCH64_BTI
#endif

Expand Down

0 comments on commit 3952910

Please sign in to comment.