Skip to content

Commit 3952910

Browse files
[libunwind] Fix problems caused by combining BTI and GCS (#102322)
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 <daniel.kristof.kiss@gmail.com>
1 parent 00f90d3 commit 3952910

File tree

2 files changed

+35
-6
lines changed

2 files changed

+35
-6
lines changed

libunwind/src/UnwindRegistersRestore.S

+15-1
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,10 @@ Lnovec:
629629

630630
#elif defined(__aarch64__)
631631

632+
#if defined(__ARM_FEATURE_GCS_DEFAULT)
633+
.arch_extension gcs
634+
#endif
635+
632636
//
633637
// extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);
634638
//
@@ -680,7 +684,17 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
680684
ldr x16, [x0, #0x0F8]
681685
ldp x0, x1, [x0, #0x000] // restore x0,x1
682686
mov sp,x16 // restore sp
683-
br x30 // jump to pc
687+
#if defined(__ARM_FEATURE_GCS_DEFAULT)
688+
// If GCS is enabled we need to push the address we're returning to onto the
689+
// GCS stack. We can't just return using br, as there won't be a BTI landing
690+
// pad instruction at the destination.
691+
mov x16, #1
692+
chkfeat x16
693+
cbnz x16, Lnogcs
694+
gcspushm x30
695+
Lnogcs:
696+
#endif
697+
ret x30 // jump to pc
684698

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

libunwind/src/assembly.h

+20-5
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,22 @@
8282
#define PPC64_OPD2
8383
#endif
8484

85-
#if defined(__aarch64__) && defined(__ARM_FEATURE_BTI_DEFAULT)
85+
#if defined(__aarch64__)
86+
#if defined(__ARM_FEATURE_GCS_DEFAULT) && defined(__ARM_FEATURE_BTI_DEFAULT)
87+
// Set BTI, PAC, and GCS gnu property bits
88+
#define GNU_PROPERTY 7
89+
// We indirectly branch to __libunwind_Registers_arm64_jumpto from
90+
// __unw_phase2_resume, so we need to use bti jc.
91+
#define AARCH64_BTI bti jc
92+
#elif defined(__ARM_FEATURE_GCS_DEFAULT)
93+
// Set GCS gnu property bit
94+
#define GNU_PROPERTY 4
95+
#elif defined(__ARM_FEATURE_BTI_DEFAULT)
96+
// Set BTI and PAC gnu property bits
97+
#define GNU_PROPERTY 3
98+
#define AARCH64_BTI bti c
99+
#endif
100+
#ifdef GNU_PROPERTY
86101
.pushsection ".note.gnu.property", "a" SEPARATOR \
87102
.balign 8 SEPARATOR \
88103
.long 4 SEPARATOR \
@@ -91,12 +106,12 @@
91106
.asciz "GNU" SEPARATOR \
92107
.long 0xc0000000 SEPARATOR /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ \
93108
.long 4 SEPARATOR \
94-
.long 3 SEPARATOR /* GNU_PROPERTY_AARCH64_FEATURE_1_BTI AND */ \
95-
/* GNU_PROPERTY_AARCH64_FEATURE_1_PAC */ \
109+
.long GNU_PROPERTY SEPARATOR \
96110
.long 0 SEPARATOR \
97111
.popsection SEPARATOR
98-
#define AARCH64_BTI bti c
99-
#else
112+
#endif
113+
#endif
114+
#if !defined(AARCH64_BTI)
100115
#define AARCH64_BTI
101116
#endif
102117

0 commit comments

Comments
 (0)