File 9306.patch of Package ruby3.2
From 36a574f661d4e3ad3d96d2eebfe48ca710660221 Mon Sep 17 00:00:00 2001
From: Yuta Saito <kateinoigakukun@gmail.com>
Date: Thu, 21 Dec 2023 14:42:39 +0900
Subject: [PATCH 1/4] coroutine/arm64: Sign return address if PAC enabled
---
coroutine/arm64/Context.S | 24 ++++++++++++++++++++----
coroutine/arm64/Context.h | 22 ++++++++++++++++++++--
2 files changed, 40 insertions(+), 6 deletions(-)
diff --git a/coroutine/arm64/Context.S b/coroutine/arm64/Context.S
index 07d50d30df39e..2cf3e489877cb 100644
--- a/coroutine/arm64/Context.S
+++ b/coroutine/arm64/Context.S
@@ -18,9 +18,19 @@
.align 2
#endif
+## NOTE(PAC): Use we HINT mnemonics instead of PAC mnemonics to
+## keep compatibility with those assemblers that don't support PAC.
+##
+## See "Providing protection for complex software" for more details about PAC/BTI
+## https://developer.arm.com/architectures/learn-the-architecture/providing-protection-for-complex-software
+
.global PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
+#if defined(__ARM_FEATURE_PAC_DEFAULT) && (__ARM_FEATURE_PAC_DEFAULT != 0)
+ # paciasp
+ hint #25
+#endif
# Make space on the stack for caller registers
sub sp, sp, 0xb0
@@ -59,14 +69,20 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
ldp x27, x28, [sp, 0x80]
ldp x29, x30, [sp, 0x90]
- # Load return address into x4
- ldr x4, [sp, 0xa0]
+ # Load return address into x17
+ ldr x17, [sp, 0xa0]
# Pop stack frame
add sp, sp, 0xb0
- # Jump to return address (in x4)
- ret x4
+#if defined(__ARM_FEATURE_PAC_DEFAULT) && (__ARM_FEATURE_PAC_DEFAULT != 0)
+ mov x16, sp
+ # autia1716
+ hint #12
+#endif
+
+ # Jump to return address (in x17)
+ ret x17
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
diff --git a/coroutine/arm64/Context.h b/coroutine/arm64/Context.h
index 1472621f48017..168ec18c4aa2d 100644
--- a/coroutine/arm64/Context.h
+++ b/coroutine/arm64/Context.h
@@ -50,6 +50,23 @@ static inline void coroutine_initialize_main(struct coroutine_context * context)
context->stack_pointer = NULL;
}
+#if defined(__ARM_FEATURE_PAC_DEFAULT) && __ARM_FEATURE_PAC_DEFAULT != 0
+// Sign the given instruction address with the given modifier and key A
+static inline void *ptrauth_sign_instruction_addr(void *addr, void *modifier) {
+ register void *r17 __asm("r17") = addr;
+ register void *r16 __asm("r16") = modifier;
+ // Use HINT mnemonic instead of PACIA1716 for compatibility with older assemblers.
+ asm ("hint #8;" : "+r"(r17) : "r"(r16));
+ addr = r17;
+ return addr;
+}
+#else
+// No-op if PAC is not enabled
+static inline void *ptrauth_sign_instruction_addr(void *addr, void *modifier) {
+ return addr;
+}
+#endif
+
static inline void coroutine_initialize(
struct coroutine_context *context,
coroutine_start start,
@@ -66,12 +83,13 @@ static inline void coroutine_initialize(
// Stack grows down. Force 16-byte alignment.
char * top = (char*)stack + size;
- context->stack_pointer = (void**)((uintptr_t)top & ~0xF);
+ top = (char *)((uintptr_t)top & ~0xF);
+ context->stack_pointer = (void**)top;
context->stack_pointer -= COROUTINE_REGISTERS;
memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
- context->stack_pointer[0xa0 / 8] = (void*)start;
+ context->stack_pointer[0xa0 / 8] = ptrauth_sign_instruction_addr((void*)start, (void*)top);
}
struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);
From 831e94893410749f187cb8a2316d21e546ad5715 Mon Sep 17 00:00:00 2001
From: Yuta Saito <kateinoigakukun@gmail.com>
Date: Thu, 21 Dec 2023 15:19:25 +0900
Subject: [PATCH 2/4] coroutine/arm64/Context.S: Insert `bti c` as BTI landing
pad
---
coroutine/arm64/Context.S | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/coroutine/arm64/Context.S b/coroutine/arm64/Context.S
index 2cf3e489877cb..0eb08e326d0b6 100644
--- a/coroutine/arm64/Context.S
+++ b/coroutine/arm64/Context.S
@@ -28,8 +28,12 @@
PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
#if defined(__ARM_FEATURE_PAC_DEFAULT) && (__ARM_FEATURE_PAC_DEFAULT != 0)
- # paciasp
+ # paciasp (it also acts as BTI landing pad, so no need to insert BTI also)
hint #25
+#elif defined(__ARM_FEATURE_BTI_DEFAULT) && (__ARM_FEATURE_BTI_DEFAULT != 0)
+ # For the the case PAC is not enabled but BTI is.
+ # bti c
+ hint #34
#endif
# Make space on the stack for caller registers
sub sp, sp, 0xb0
From 0298eaf76f0125523119c2ddaf0f752307dcf723 Mon Sep 17 00:00:00 2001
From: Yuta Saito <kateinoigakukun@gmail.com>
Date: Thu, 21 Dec 2023 15:21:37 +0900
Subject: [PATCH 3/4] coroutine/arm64/Context.S: Append PAC/BTI note section if
needed
Fixes https://bugs.ruby-lang.org/issues/20029
---
coroutine/arm64/Context.S | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/coroutine/arm64/Context.S b/coroutine/arm64/Context.S
index 0eb08e326d0b6..cdcc6ca6dd4bf 100644
--- a/coroutine/arm64/Context.S
+++ b/coroutine/arm64/Context.S
@@ -91,3 +91,37 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif
+
+#if __ARM_FEATURE_BTI_DEFAULT != 0 || __ARM_FEATURE_PAC_DEFAULT != 0
+/* See "ELF for the Arm 64-bit Architecture (AArch64)"
+ https://github.com/ARM-software/abi-aa/blob/2023Q3/aaelf64/aaelf64.rst#program-property */
+# define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1<<0)
+# define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1<<1)
+
+# if __ARM_FEATURE_BTI_DEFAULT != 0
+# define BTI_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_BTI
+# else
+# define BTI_FLAG 0
+# endif
+# if __ARM_FEATURE_PAC_DEFAULT != 0
+# define PAC_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_PAC
+# else
+# define PAC_FLAG 0
+# endif
+
+ # The note section format is described by Note Section in Chapter 5
+ # of "System V Application Binary Interface, Edition 4.1".
+ .pushsection .note.gnu.property, "a"
+ .p2align 3
+ .long 0x4 /* Name size ("GNU\0") */
+ .long 0x10 /* Descriptor size */
+ .long 0x5 /* Type: NT_GNU_PROPERTY_TYPE_0 */
+ .asciz "GNU" /* Name */
+ # Begin descriptor
+ .long 0xc0000000 /* Property type: GNU_PROPERTY_AARCH64_FEATURE_1_AND */
+ .long 0x4 /* Property size */
+ .long (BTI_FLAG|PAC_FLAG)
+ .long 0x0 /* 8-byte alignment padding */
+ # End descriptor
+ .popsection
+#endif
From e13bfc020b15d5b1097d1036f5c900eb1479d45c Mon Sep 17 00:00:00 2001
From: Yuta Saito <kateinoigakukun@gmail.com>
Date: Fri, 22 Dec 2023 08:52:20 +0900
Subject: [PATCH 4/4] coroutine/arm64: Skip saving/restoring x30 twice and use
`autiasp`
We don't need to save/restore x30 twice, and we can just use `ret`,
which uses x30 as return address register instead of explicit `ret <reg>`
instruction. This also allows us to use `autiasp` instead of `autia1716`
and we can skip setting SP/LR to x16/x17.
Also the size of register save area is shrunk by 16 bytes due to the
removal of extra x30 save/restore.
---
coroutine/arm64/Context.S | 19 ++++++-------------
coroutine/arm64/Context.h | 4 ++--
2 files changed, 8 insertions(+), 15 deletions(-)
diff --git a/coroutine/arm64/Context.S b/coroutine/arm64/Context.S
index cdcc6ca6dd4bf..eeb0f774a37c3 100644
--- a/coroutine/arm64/Context.S
+++ b/coroutine/arm64/Context.S
@@ -36,7 +36,7 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
hint #34
#endif
# Make space on the stack for caller registers
- sub sp, sp, 0xb0
+ sub sp, sp, 0xa0
# Save caller registers
stp d8, d9, [sp, 0x00]
@@ -50,9 +50,6 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
stp x27, x28, [sp, 0x80]
stp x29, x30, [sp, 0x90]
- # Save return address
- str x30, [sp, 0xa0]
-
# Save stack pointer to x0 (first argument)
mov x2, sp
str x2, [x0, 0]
@@ -73,20 +70,16 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
ldp x27, x28, [sp, 0x80]
ldp x29, x30, [sp, 0x90]
- # Load return address into x17
- ldr x17, [sp, 0xa0]
-
# Pop stack frame
- add sp, sp, 0xb0
+ add sp, sp, 0xa0
#if defined(__ARM_FEATURE_PAC_DEFAULT) && (__ARM_FEATURE_PAC_DEFAULT != 0)
- mov x16, sp
- # autia1716
- hint #12
+ # autiasp: Authenticate x30 (LR) with SP and key A
+ hint #29
#endif
- # Jump to return address (in x17)
- ret x17
+ # Jump to return address (in x30)
+ ret
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
diff --git a/coroutine/arm64/Context.h b/coroutine/arm64/Context.h
index 168ec18c4aa2d..1819fa5be9328 100644
--- a/coroutine/arm64/Context.h
+++ b/coroutine/arm64/Context.h
@@ -17,7 +17,7 @@
#define COROUTINE __attribute__((noreturn)) void
-enum {COROUTINE_REGISTERS = 0xb0 / 8};
+enum {COROUTINE_REGISTERS = 0xa0 / 8};
#if defined(__SANITIZE_ADDRESS__)
#define COROUTINE_SANITIZE_ADDRESS
@@ -89,7 +89,7 @@ static inline void coroutine_initialize(
context->stack_pointer -= COROUTINE_REGISTERS;
memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
- context->stack_pointer[0xa0 / 8] = ptrauth_sign_instruction_addr((void*)start, (void*)top);
+ context->stack_pointer[0x98 / 8] = ptrauth_sign_instruction_addr((void*)start, (void*)top);
}
struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);