mirror of
https://github.com/python/cpython.git
synced 2026-06-04 16:50:51 +00:00
gh-139808: Add branch protections for aarch64 in asm_trampoline.S (#130864)
Apply protection against ROP/JOP attacks for aarch64 on asm_trampoline.S. The BTI flag must be applied in assembler sources for this class of attacks to be mitigated on newer aarch64 processors. See also: https://sourceware.org/annobin/annobin.html/Test-branch-protection.html and https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/enabling-pac-and-bti-on-aarch64 Co-authored-by: Victor Stinner <vstinner@python.org>
This commit is contained in:
parent
0534774a47
commit
da8477b25c
4 changed files with 75 additions and 0 deletions
|
|
@ -0,0 +1,2 @@
|
|||
Add branch protections for AArch64 (BTI/PAC) in assembly code used by
|
||||
:option:`-X perf_jit <-X>` (Linux perf profiler integration).
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
#include "asm_trampoline_aarch64.h"
|
||||
|
||||
.text
|
||||
#if defined(__APPLE__)
|
||||
.globl __Py_trampoline_func_start
|
||||
|
|
@ -29,10 +31,12 @@ _Py_trampoline_func_start:
|
|||
#if defined(__aarch64__) && defined(__AARCH64EL__) && !defined(__ILP32__)
|
||||
// ARM64 little endian, 64bit ABI
|
||||
// generate with aarch64-linux-gnu-gcc 12.1
|
||||
SIGN_LR
|
||||
stp x29, x30, [sp, -16]!
|
||||
mov x29, sp
|
||||
blr x3
|
||||
ldp x29, x30, [sp], 16
|
||||
VERIFY_LR
|
||||
ret
|
||||
#endif
|
||||
#ifdef __riscv
|
||||
|
|
|
|||
56
Python/asm_trampoline_aarch64.h
Normal file
56
Python/asm_trampoline_aarch64.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#ifndef ASM_TRAMPOLINE_AARCH_64_H_
|
||||
#define ASM_TRAMPOLINE_AARCH_64_H_
|
||||
|
||||
/*
|
||||
* References:
|
||||
* - https://developer.arm.com/documentation/101028/0012/5--Feature-test-macros
|
||||
* - https://github.com/ARM-software/abi-aa/blob/main/aaelf64/aaelf64.rst
|
||||
*/
|
||||
|
||||
#if defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT == 1
|
||||
#define BTI_J hint 36 /* bti j: for jumps, IE br instructions */
|
||||
#define BTI_C hint 34 /* bti c: for calls, IE bl instructions */
|
||||
#define GNU_PROPERTY_AARCH64_BTI 1 /* bit 0 GNU Notes is for BTI support */
|
||||
#else
|
||||
#define BTI_J
|
||||
#define BTI_C
|
||||
#define GNU_PROPERTY_AARCH64_BTI 0
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_FEATURE_PAC_DEFAULT)
|
||||
#if __ARM_FEATURE_PAC_DEFAULT & 1
|
||||
#define SIGN_LR hint 25 /* paciasp: sign with the A key */
|
||||
#define VERIFY_LR hint 29 /* autiasp: verify with the A key */
|
||||
#elif __ARM_FEATURE_PAC_DEFAULT & 2
|
||||
#define SIGN_LR hint 27 /* pacibsp: sign with the b key */
|
||||
#define VERIFY_LR hint 31 /* autibsp: verify with the b key */
|
||||
#endif
|
||||
#define GNU_PROPERTY_AARCH64_POINTER_AUTH 2 /* bit 1 GNU Notes is for PAC support */
|
||||
#else
|
||||
#define SIGN_LR BTI_C
|
||||
#define VERIFY_LR
|
||||
#define GNU_PROPERTY_AARCH64_POINTER_AUTH 0
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_FEATURE_GCS_DEFAULT) && __ARM_FEATURE_GCS_DEFAULT == 1
|
||||
#define GNU_PROPERTY_AARCH64_GCS 4 /* bit 2 GNU Notes is for GCS support */
|
||||
#else
|
||||
#define GNU_PROPERTY_AARCH64_GCS 0
|
||||
#endif
|
||||
|
||||
/* Add the BTI, PAC and GCS support to GNU Notes section */
|
||||
#if GNU_PROPERTY_AARCH64_BTI != 0 || GNU_PROPERTY_AARCH64_POINTER_AUTH != 0 || GNU_PROPERTY_AARCH64_GCS != 0
|
||||
.pushsection .note.gnu.property, "a"; /* Start a new allocatable section */
|
||||
.balign 8; /* align it on a byte boundry */
|
||||
.long 4; /* size of "GNU\0" */
|
||||
.long 0x10; /* size of descriptor */
|
||||
.long 0x5; /* NT_GNU_PROPERTY_TYPE_0 */
|
||||
.asciz "GNU";
|
||||
.long 0xc0000000; /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */
|
||||
.long 4; /* Four bytes of data */
|
||||
.long (GNU_PROPERTY_AARCH64_BTI|GNU_PROPERTY_AARCH64_POINTER_AUTH|GNU_PROPERTY_AARCH64_GCS); /* BTI, PAC or GCS is enabled */
|
||||
.long 0; /* padding for 8 byte alignment */
|
||||
.popsection; /* end the section */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -60,6 +60,9 @@ enum {
|
|||
DWRF_CFA_offset_extended_sf = 0x11, // Extended signed offset
|
||||
DWRF_CFA_advance_loc = 0x40, // Advance location counter
|
||||
DWRF_CFA_offset = 0x80, // Simple offset instruction
|
||||
#if defined(__aarch64__)
|
||||
DWRF_CFA_AARCH64_negate_ra_state = 0x2d, // Toggle return address signing state
|
||||
#endif
|
||||
DWRF_CFA_restore = 0xc0 // Restore register
|
||||
};
|
||||
|
||||
|
|
@ -562,6 +565,13 @@ static void elf_init_ehframe_perf(ELFObjectContext* ctx) {
|
|||
DWRF_UV(8); // New offset: SP + 8
|
||||
#elif defined(__aarch64__) && defined(__AARCH64EL__) && !defined(__ILP32__)
|
||||
/* AArch64 calling convention unwinding rules */
|
||||
#if defined(__ARM_FEATURE_PAC_DEFAULT) || \
|
||||
(defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT == 1)
|
||||
DWRF_U8(DWRF_CFA_advance_loc | 1); // Advance past SIGN_LR (4 bytes)
|
||||
#endif
|
||||
#if defined(__ARM_FEATURE_PAC_DEFAULT)
|
||||
DWRF_U8(DWRF_CFA_AARCH64_negate_ra_state); // Saved LR is PAC-signed from here
|
||||
#endif
|
||||
DWRF_U8(DWRF_CFA_advance_loc | 1); // Advance by 1 instruction (4 bytes)
|
||||
DWRF_U8(DWRF_CFA_def_cfa_offset); // CFA = SP + 16
|
||||
DWRF_UV(16); // Stack pointer moved by 16 bytes
|
||||
|
|
@ -570,6 +580,9 @@ static void elf_init_ehframe_perf(ELFObjectContext* ctx) {
|
|||
DWRF_U8(DWRF_CFA_offset | DWRF_REG_RA); // x30 (link register) saved
|
||||
DWRF_UV(1); // At CFA-8 (1 * 8 = 8 bytes from CFA)
|
||||
DWRF_U8(DWRF_CFA_advance_loc | 3); // Advance by 3 instructions (12 bytes)
|
||||
#if defined(__ARM_FEATURE_PAC_DEFAULT)
|
||||
DWRF_U8(DWRF_CFA_AARCH64_negate_ra_state); // LR is authenticated, no longer PAC-signed
|
||||
#endif
|
||||
DWRF_U8(DWRF_CFA_def_cfa_register); // CFA = FP (x29) + 16
|
||||
DWRF_UV(DWRF_REG_FP);
|
||||
DWRF_U8(DWRF_CFA_restore | DWRF_REG_RA); // Restore x30 - NO DWRF_UV() after this!
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue