public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/vendors/ARM/heads/gcs)] aarch64: Add GCS support to the unwinder
@ 2024-02-14 15:27 Szabolcs Nagy
0 siblings, 0 replies; 2+ messages in thread
From: Szabolcs Nagy @ 2024-02-14 15:27 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:49b5b4f954449e307ab57c5e736f6f89dcb2c44b
commit 49b5b4f954449e307ab57c5e736f6f89dcb2c44b
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
Date: Wed Apr 19 14:01:36 2023 +0100
aarch64: Add GCS support to the unwinder
TODO:
- Follows the current linux ABI that uses single signal entry token
and shared shadow stack between thread and alt stack.
- Could be behind __ARM_FEATURE_GCS_DEFAULT ifdef (only do anything
special with gcs compat codegen) but there is a runtime check anyway.
libgcc/ChangeLog:
* config/aarch64/aarch64-unwind.h (_Unwind_Frames_Extra): Update.
(_Unwind_Frames_Increment): Define.
Diff:
---
libgcc/config/aarch64/aarch64-unwind.h | 59 +++++++++++++++++++++++++++++++++-
1 file changed, 58 insertions(+), 1 deletion(-)
diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h
index daf96624b5e1..c22a3fc20d2e 100644
--- a/libgcc/config/aarch64/aarch64-unwind.h
+++ b/libgcc/config/aarch64/aarch64-unwind.h
@@ -78,6 +78,9 @@ aarch64_demangle_return_addr (struct _Unwind_Context *context,
return addr;
}
+/* GCS enable flag for chkfeat instruction. */
+#define CHKFEAT_GCS 1
+
/* SME runtime function local to libgcc, streaming compatible
and preserves more registers than the base PCS requires, but
we don't rely on that here. */
@@ -85,12 +88,66 @@ __attribute__ ((visibility ("hidden")))
void __libgcc_arm_za_disable (void);
/* Disable the SME ZA state in case an unwound frame used the ZA
- lazy saving scheme. */
+ lazy saving scheme. And unwind the GCS for EH. */
#undef _Unwind_Frames_Extra
#define _Unwind_Frames_Extra(x) \
do \
{ \
__libgcc_arm_za_disable (); \
+ if (__builtin_aarch64_chkfeat (CHKFEAT_GCS) == 0) \
+ { \
+ for (_Unwind_Word n = (x); n != 0; n--) \
+ __builtin_aarch64_gcspopm (); \
+ } \
+ } \
+ while (0)
+
+/* On signal entry the OS places a token on the GCS that can be used to
+ verify the integrity of the GCS pointer on signal return. It also
+ places the signal handler return address (the restorer that calls the
+ signal return syscall) on the GCS so the handler can return.
+ Because of this token, each stack frame visited during unwinding has
+ exactly one corresponding entry on the GCS, so the frame count is
+ the number of entries that will have to be popped at EH return time.
+
+ Note: This depends on the GCS signal ABI of the OS.
+
+ When unwinding across a stack frame for each frame the corresponding
+ entry is checked on the GCS against the computed return address from
+ the normal stack. If they don't match then _URC_FATAL_PHASE2_ERROR
+ is returned. This check is omitted if
+
+ 1. GCS is disabled. Note: asynchronous GCS disable is supported here
+ if GCSPR and the GCS remains readable.
+ 2. Non-catchable exception where exception_class == 0. Note: the
+ pthread cancellation implementation in glibc sets exception_class
+ to 0 when the unwinder is used for cancellation cleanup handling,
+ so this allows the GCS to get out of sync during cancellation.
+ This weakens security but avoids an ABI break in glibc.
+ 3. Zero return address which marks the outermost stack frame.
+ 4. Signal stack frame, the GCS entry is an OS specific token then
+ with the top bit set.
+ */
+#undef _Unwind_Frames_Increment
+#define _Unwind_Frames_Increment(exc, context, frames) \
+ do \
+ { \
+ frames++; \
+ if (__builtin_aarch64_chkfeat (CHKFEAT_GCS) != 0 \
+ || exc->exception_class == 0 \
+ || _Unwind_GetIP (context) == 0) \
+ break; \
+ const _Unwind_Word *gcs = __builtin_aarch64_gcspr (); \
+ if (_Unwind_IsSignalFrame (context)) \
+ { \
+ if (gcs[frames] >> 63 == 0) \
+ return _URC_FATAL_PHASE2_ERROR; \
+ } \
+ else \
+ { \
+ if (gcs[frames] != _Unwind_GetIP (context)) \
+ return _URC_FATAL_PHASE2_ERROR; \
+ } \
} \
while (0)
^ permalink raw reply [flat|nested] 2+ messages in thread
* [gcc(refs/vendors/ARM/heads/gcs)] aarch64: Add GCS support to the unwinder
@ 2024-04-10 10:48 Szabolcs Nagy
0 siblings, 0 replies; 2+ messages in thread
From: Szabolcs Nagy @ 2024-04-10 10:48 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:2185dc7cdb6d536e4d9a49a77c552e58041cb0bc
commit 2185dc7cdb6d536e4d9a49a77c552e58041cb0bc
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
Date: Wed Apr 19 14:01:36 2023 +0100
aarch64: Add GCS support to the unwinder
TODO:
- Follows the current linux ABI that uses single signal entry token
and shared shadow stack between thread and alt stack.
- Could be behind __ARM_FEATURE_GCS_DEFAULT ifdef (only do anything
special with gcs compat codegen) but there is a runtime check anyway.
libgcc/ChangeLog:
* config/aarch64/aarch64-unwind.h (_Unwind_Frames_Extra): Update.
(_Unwind_Frames_Increment): Define.
Diff:
---
libgcc/config/aarch64/aarch64-unwind.h | 59 +++++++++++++++++++++++++++++++++-
1 file changed, 58 insertions(+), 1 deletion(-)
diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h
index daf96624b5e..c22a3fc20d2 100644
--- a/libgcc/config/aarch64/aarch64-unwind.h
+++ b/libgcc/config/aarch64/aarch64-unwind.h
@@ -78,6 +78,9 @@ aarch64_demangle_return_addr (struct _Unwind_Context *context,
return addr;
}
+/* GCS enable flag for chkfeat instruction. */
+#define CHKFEAT_GCS 1
+
/* SME runtime function local to libgcc, streaming compatible
and preserves more registers than the base PCS requires, but
we don't rely on that here. */
@@ -85,12 +88,66 @@ __attribute__ ((visibility ("hidden")))
void __libgcc_arm_za_disable (void);
/* Disable the SME ZA state in case an unwound frame used the ZA
- lazy saving scheme. */
+ lazy saving scheme. And unwind the GCS for EH. */
#undef _Unwind_Frames_Extra
#define _Unwind_Frames_Extra(x) \
do \
{ \
__libgcc_arm_za_disable (); \
+ if (__builtin_aarch64_chkfeat (CHKFEAT_GCS) == 0) \
+ { \
+ for (_Unwind_Word n = (x); n != 0; n--) \
+ __builtin_aarch64_gcspopm (); \
+ } \
+ } \
+ while (0)
+
+/* On signal entry the OS places a token on the GCS that can be used to
+ verify the integrity of the GCS pointer on signal return. It also
+ places the signal handler return address (the restorer that calls the
+ signal return syscall) on the GCS so the handler can return.
+ Because of this token, each stack frame visited during unwinding has
+ exactly one corresponding entry on the GCS, so the frame count is
+ the number of entries that will have to be popped at EH return time.
+
+ Note: This depends on the GCS signal ABI of the OS.
+
+ When unwinding across a stack frame for each frame the corresponding
+ entry is checked on the GCS against the computed return address from
+ the normal stack. If they don't match then _URC_FATAL_PHASE2_ERROR
+ is returned. This check is omitted if
+
+ 1. GCS is disabled. Note: asynchronous GCS disable is supported here
+ if GCSPR and the GCS remains readable.
+ 2. Non-catchable exception where exception_class == 0. Note: the
+ pthread cancellation implementation in glibc sets exception_class
+ to 0 when the unwinder is used for cancellation cleanup handling,
+ so this allows the GCS to get out of sync during cancellation.
+ This weakens security but avoids an ABI break in glibc.
+ 3. Zero return address which marks the outermost stack frame.
+ 4. Signal stack frame, the GCS entry is an OS specific token then
+ with the top bit set.
+ */
+#undef _Unwind_Frames_Increment
+#define _Unwind_Frames_Increment(exc, context, frames) \
+ do \
+ { \
+ frames++; \
+ if (__builtin_aarch64_chkfeat (CHKFEAT_GCS) != 0 \
+ || exc->exception_class == 0 \
+ || _Unwind_GetIP (context) == 0) \
+ break; \
+ const _Unwind_Word *gcs = __builtin_aarch64_gcspr (); \
+ if (_Unwind_IsSignalFrame (context)) \
+ { \
+ if (gcs[frames] >> 63 == 0) \
+ return _URC_FATAL_PHASE2_ERROR; \
+ } \
+ else \
+ { \
+ if (gcs[frames] != _Unwind_GetIP (context)) \
+ return _URC_FATAL_PHASE2_ERROR; \
+ } \
} \
while (0)
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2024-04-10 10:48 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-02-14 15:27 [gcc(refs/vendors/ARM/heads/gcs)] aarch64: Add GCS support to the unwinder Szabolcs Nagy
2024-04-10 10:48 Szabolcs Nagy
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).