From 3668daf135dea7d18737b01ce32774a7a2ffba32 Mon Sep 17 00:00:00 2001 From: Bill Roberts <152999275+billatarm@users.noreply.github.com> Date: Tue, 20 Aug 2024 21:20:45 -0500 Subject: [PATCH] Enable pac bti support (#3775) * readme: update meson build command Fixes warning: WARNING: Running the setup command as `meson [options]` instead of `meson setup [options]` is ambiguous and deprecated. Signed-off-by: Bill Roberts * meson.build: fix suffix on HAVE_NEON_AARCH64 rename HAVE_NEON_AARCH64 to the in-use define for controlling NEON: HAVE_NEON_AARCH64 Signed-off-by: Bill Roberts * aarch64: enable PAC/BTI Enable Pointer Authentication Codes (PAC) and Branch Target Identification (BTI) support for ARM 64 targets. OpenH264 does not require any of the PAC signing and verification as the leaf functions do not store x30 to the stack. Also, no indirect branches are performed so no need to annotate branch targets with bti j landing pad instructions. The only thing required is to label the function entry points with bti c instructions and ensure the GNU Notes are updated for their respective features when enabled for ELF files. A detailed summary on how PAC and BTI work are provided below for clarity. PAC works by signing the LR with either an A key or B key and verifying the return address. There are quite a few instructions capable of doing this, however, the Linux ARM ABI is to use hint compatible instructions that can be safely NOP'd on older hardware and can be assembled and linked with older binutils. This limits the instruction set to paciasp, pacibsp, autiasp and autibsp. Instructions prefixed with pac are for signing and instructions prefixed with aut are for signing. Both instructions are then followed with an a or b to indicate which signing key they are using. The keys can be controlled using -mbranch-protection=pac-ret for the A key and -mbranch-protection=pac-ret+b-key for the B key. BTI works by marking all indirect call and jump positions with bti c and bti j instructions respectively. If execution control transfers to an instruction other than a BTI instruction, the execution is killed via SIGILL. Note that to remove one instruction, the aforementioned pac instructions will also work as a BTI landing pad for bti c usages. For BTI to work, all object files linked for a unit of execution, whether an executable or a library must have the GNU Notes section of the ELF file marked to indicate BTI support. This is so loader/linkers can apply the proper permission bits (PROT_BRI) on the memory region. PAC can also be annotated in the GNU ELF notes section, but it's not required for enablement, as interleaved PAC and non-pac code works as expected since it's the callee that performs all the checking. Testing was done under the following CFLAGS and CXXFLAGS for all combinations: 1. -mbranch-protection=none 2. -mbranch-protection=standard 3. -mbranch-protection=pac-ret 4. -mbranch-protection=pac-ret+b-key 5. -mbranch-protection=bti Signed-off-by: Bill Roberts --------- Signed-off-by: Bill Roberts --- README.md | 2 +- codec/common/arm64/arm_aarch64_common.h | 85 ++++++++++++++++++++ codec/common/arm64/arm_arch64_common_macro.S | 3 + meson.build | 4 +- 4 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 codec/common/arm64/arm_aarch64_common.h diff --git a/README.md b/README.md index dbb80cde64..2184aeec05 100644 --- a/README.md +++ b/README.md @@ -159,7 +159,7 @@ See for instructions on how to install meson, then: ``` shell -meson builddir +meson setup builddir ninja -C builddir ``` diff --git a/codec/common/arm64/arm_aarch64_common.h b/codec/common/arm64/arm_aarch64_common.h new file mode 100644 index 0000000000..df7ac70bee --- /dev/null +++ b/codec/common/arm64/arm_aarch64_common.h @@ -0,0 +1,85 @@ +/*! + *@page License + * + * \copy + * Copyright (c) 2024, ARM Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CODEC_COMMON_ARM64_ARM_AARCH64_COMMON_H_ +#define CODEC_COMMON_ARM64_ARM_AARCH64_COMMON_H_ + +/* + ; Support macros for + ; - Armv8.3-A Pointer Authentication and + ; - Armv8.5-A Branch Target Identification + ; Further documentation can be found at: + ; - https://developer.arm.com/documentation/101028/0012/5--Feature-test-macros + ; + ; Since openh264 aarch64 assembly code provides functions with no storage of the + ; LR(x30) on the stack, PAC is not needed as modification of the LR value would + ; require modification of x30 and not memory. Additionally, no indirect control + ; flow changes are performed, so bti j instructions are not needed. Thus, just + ; mark the entry points with bti c landing pads and the ELF files as supporting + ; BTI and PAC. + */ +#if defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT == 1 + /* BTI is enabled */ + #define BTI_C hint 34 + #define GNU_PROPERTY_AARCH64_BTI 0x1 /* Property for notes section in ELF */ +#else + /* BTI is NOT enabled */ + #define BTI_C + #define GNU_PROPERTY_AARCH64_BTI 0 +#endif + +#if defined(__ARM_FEATURE_PAC_DEFAULT) + /* PAC is enabled */ + #define GNU_PROPERTY_AARCH64_POINTER_AUTH 0x2 /* Property for notes section in ELF */ +#else + /* PAC is not enabled */ + #define GNU_PROPERTY_AARCH64_POINTER_AUTH 0 +#endif + +/* Add the notes section to ELF only */ +#if defined(__ELF__) + .pushsection .note.gnu.property, "a"; + .balign 8; + .long 4; + .long 0x10; + .long 0x5; + .asciz "GNU"; + .long 0xc0000000; /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ + .long 4; + .long(GNU_PROPERTY_AARCH64_POINTER_AUTH | GNU_PROPERTY_AARCH64_BTI); + .long 0; + .popsection; +#endif + +#endif /* CODEC_COMMON_ARM64_ARM_AARCH64_COMMON_H_ */ diff --git a/codec/common/arm64/arm_arch64_common_macro.S b/codec/common/arm64/arm_arch64_common_macro.S index e6e2d590fb..420c7cbcd1 100644 --- a/codec/common/arm64/arm_arch64_common_macro.S +++ b/codec/common/arm64/arm_arch64_common_macro.S @@ -30,6 +30,8 @@ * */ +#include "arm_aarch64_common.h" + #ifdef __APPLE__ .text @@ -60,6 +62,7 @@ ret .func \funcName #endif \funcName: + BTI_C .endm .macro WELS_ASM_AARCH64_FUNC_END diff --git a/meson.build b/meson.build index 304cdbb016..e5e772b498 100644 --- a/meson.build +++ b/meson.build @@ -85,8 +85,8 @@ if ['linux', 'android', 'ios', 'darwin'].contains(system) casm_inc = include_directories(join_paths('codec', 'common', 'arm')) elif cpu_family == 'aarch64' asm_format = asm_format64 - add_project_arguments('-DHAVE_NEON_ARM64', language: 'c') - add_project_arguments('-DHAVE_NEON_ARM64', language: 'cpp') + add_project_arguments('-DHAVE_NEON_AARCH64', language: 'c') + add_project_arguments('-DHAVE_NEON_AARCH64', language: 'cpp') casm_inc = include_directories(join_paths('codec', 'common', 'arm64')) elif cpu_family == 'loongarch32' asm_format = asm_format32